adafruit / Adafruit_CircuitPython_Requests

Requests-like interface for web interfacing
MIT License
51 stars 36 forks source link

When sending data get the bytes length not the string length #112

Closed Neradoc closed 1 year ago

Neradoc commented 1 year ago

This always converts data from string to bytes before getting the length. Otherwise data that contains UTF-8 characters gets truncated if the server follows the content length. data is still converted to bytes if not a string. (Is it necessary ?)

This was reported in the support forums by testing with pushover.net (using the desktop in-browser interface to receive the messages).

import ssl
import time
import wifi
import socketpool
import adafruit_requests
from secrets import secrets

# URLs
PUSHOVER_JSON_URL = 'https://api.pushover.net/1/messages.json'

wifi.radio.connect(secrets['ssid'], secrets['password'])
pool = socketpool.SocketPool(wifi.radio)
requests = adafruit_requests.Session(pool, ssl.create_default_context())

data = {
    'token': secrets['pushover_app_token'],
    'user': secrets['pushover_user_key'],
    'title': "Test Requests Content Length",
    'message': 'The ñ temperature is, 32°C...',
}
with requests.post(PUSHOVER_JSON_URL, data=data) as response:
    print("API Response: ", response.text)

ñ and ° are encoded with 2 bytes.

>>> len('The ñ temperature is, 32°C...')
29
>>> len('The ñ temperature is, 32°C...'.encode())
31

This is the result in the browser, before the fix is the bottom one. 2 characters are missing.

Capture d’écran 2022-08-03 à 14 40 40

Note that what gets cut depends on the order in which the parameters end up, dicts are not ordered in CP so the loop goes through them in no particular order. In this example it's the message that ends up last.

I only tested that, and some of the examples from this repository.