community
community copied to clipboard
`UrlRequest` decodes bytes response to string regardless of `decode` param
Software Versions
- Python: 3.9.2
- OS: "Debian GNU/Linux 11 (bullseye)" on Raspberry Pi 4
- Kivy: 2.3.0
- Kivy installation method: pip
Describe the bug
UrlRequest decodes the response in bytes to string regardless of what is passed in the decode parameter. Note my response header is application/octet-stream.
The issue could be in this line -> https://github.com/kivy/kivy/blob/aeb27bbbcfa2d118da95d42c89237cfc19c69c53/kivy/network/urlrequest.py#L341
Expected behavior
The response should be in bytes.
To Reproduce
- Run a simple HTTP server on port 5001 (see example below)
- send response as
bytesin/testendpoint
- Call
UrlRequestto POST to/testendpoint
Code and Logs and screenshots
Simple server
server.py:
from http.server import BaseHTTPRequestHandler, ThreadingHTTPServer
class TestRequestHandler(BaseHTTPRequestHandler):
protocol_version = 'HTTP/1.1'
def _set_response(self, status_code: int, content_type: str, content_length: int):
self.send_response(status_code)
self.send_header('Content-Type', content_type)
self.send_header('Content-Length', content_length)
self.end_headers()
def send(self, status_code: int, content_type: str, data):
"""Set response and send data"""
self._set_response(
status_code=status_code, content_type=content_type, content_length=len(data)
)
self.wfile.write(data)
def do_POST(self):
"""Handle POST"""
if self.path == '/test':
self.send(status_code=200, content_type='application/octet-stream', data=bytes(True))
if __name__ == '__main__':
print('Starting server...')
with ThreadingHTTPServer(('localhost', 5001), TestRequestHandler) as server:
server.serve_forever()
Calling requests with UrlRequest
urlrequest_test.py:
from kivy.clock import Clock
from kivy.network.urlrequest import UrlRequest
url = 'http://localhost:5001/test'
class Test:
def __init__(self):
self.req = None
self.res = None
def on_success(self, req, res):
self.req = req
self.res = res
def call(self):
UrlRequest(url=url, method='POST', on_success=self.on_success, decode=False)
test = Test()
test.call()
Clock.tick()
Clock.tick()
print(f'response data type: {type(test.res)}')
print(f'response headers: {test.req.resp_headers}')
Output
Run server
$ python3 server.py
Starting server...
In another terminal, run the UrlRequest call.
Notice the data type of the response is str.
$ python3 urlrequest_test.py
[INFO ] [Logger ] Record log in /root/.kivy/logs/kivy_24-10-09_16.txt
[INFO ] [Kivy ] v2.3.0
[INFO ] [Kivy ] Installed at "/var/dev/osensa-dashboard/venv/lib/python3.9/site-packages/kivy/__init__.py"
[INFO ] [Python ] v3.9.2 (default, Feb 28 2021, 17:03:44)
[GCC 10.2.1 20210110]
[INFO ] [Python ] Interpreter at "/var/dev/osensa-dashboard/venv/bin/python3"
[INFO ] [Logger ] Purge log fired. Processing...
[INFO ] [Logger ] Purge finished!
response data type: <class 'str'>
response headers: {'Server': 'BaseHTTP/0.6 Python/3.9.2', 'Date': 'Wed, 09 Oct 2024 20:58:46 GMT', 'Content-Type': 'application/octet-stream', 'Content-Length': '1', 'Set-Cookie': ''}
Additional context
When using the requests lib, the response is in bytes, which is correct.
req.py:
import requests
r = requests.post('http://localhost:5001/test')
print(f'response: {r.content}')
print(f'response data type: {type(r.content)}')
$ python req.py
response: b'\x00'
response data type: <class 'bytes'>