Skip to content

Errors and very slow when using a simple node.js server #165

Closed
@dhalbert

Description

@dhalbert

https://forums.adafruit.com/viewtopic.php?f=60&t=189508, user jeremyamoore:

User is using the simple node.js server below. When I try with the simple client program, further down, fetching consecutively longer strings, requests gets stuck or runs very slowly after a few fetches.

User node.js server

const http = require('http');
const serverPort = 8080
const requestListener = function (req, res) {
   UrlPath = parseInt(req.url.split('/')[1])
   
console.log(UrlPath)
outstring = ''
if (typeof UrlPath == 'number' & UrlPath < 100000 & UrlPath > 0) {
   while (UrlPath)
   {
    outstring += 'x';
   UrlPath--;}
   
   }
   else
   {outstring = 'Bad number'}
  res.writeHead(200);
  res.end(outstring);
}

const server = http.createServer(requestListener);
console.log('Starting web server on port ' + serverPort)
server.listen(serverPort);

Simple client I tried, running on a Metro M4 AirLift Lite

import time
import board
from digitalio import DigitalInOut

import adafruit_requests as requests
import adafruit_esp32spi.adafruit_esp32spi_socket as socket
from adafruit_esp32spi import adafruit_esp32spi

from secrets import secrets
esp32_cs = DigitalInOut(board.ESP_CS)
esp32_ready = DigitalInOut(board.ESP_BUSY)
esp32_reset = DigitalInOut(board.ESP_RESET)

url_template = "http://192.168.1.222:8080/{n}"

esp = adafruit_esp32spi.ESP_SPIcontrol(board.SPI(), esp32_cs, esp32_ready, esp32_reset)
requests.set_socket(socket, esp)

print("Connecting to AP...")
while not esp.is_connected:
    try:
        esp.connect_AP(secrets["ssid"], secrets["password"])
    except RuntimeError as e:
        print("could not connect to AP, retrying: ", e)
        continue
print("Connected to", str(esp.ssid, "utf-8"), "\tRSSI:", esp.rssi)

secs = 1
while True:
    url = url_template.format(n=secs)
    print("Fetching", url)
    print(requests.get(url).text)
    time.sleep(1)
    secs += 1

I wrote a simpleFlask server , which works fine with the client above

from flask import Flask

app = Flask(__name__)

@app.route('/<length>')
def top(length):
    try:
        return 'x' * int(length)
    except ValueError:
        return "not an integer"

app.run(host="0.0.0.0", port=8080)

User gets errors like this with their client program

I see errors like this in some cases with their server, but not with the client above, unless I try https://192.168.1.222:8080/0/, and then I do get the ValueError below.

Traceback (most recent call last):
  File "code.py", line 1, in <module>
  File "code_meteobridge.py", line 69, in <module>
  File "adafruit_requests.py", line 446, in text
  File "adafruit_requests.py", line 426, in content
  File "adafruit_requests.py", line 489, in iter_content
  File "adafruit_requests.py", line 352, in _readinto
  File "adafruit_requests.py", line 241, in _recv_into
  File "adafruit_esp32spi/adafruit_esp32spi_socket.py", line 175, in recv_into
ValueError: Can only read number of bytes between 0 and length of supplied buffer

User's diagnosis

Just tested with 7.3.0-beta.2 and 20220507 libraries. Looks like in adafruit_esp32spi_socket recv_into, it gets to the last set of data in the buffer and passes in nbytes that is smaller than the buffer size (which should be OK). When it does the avail = self.available() the value of avail is more than nbytes. So the returned value is larger than nbytes. In adafruit_requests _readinto, self._remaining -= read becomes a negative number. The next call to socket recv_into gets called with a negative nbytes value and the message. If I rename the socket method recv_into to something else, it makes self._backwards_compatible in requests to be true and does the simplified read. So not sure what the root cause is but seems to be either the logic in socket recv_into or deeper into _the_interface.socket_available for the PyPortal.

Curl

I tried both servers with curl:

Flask server

$ curl -v http://192.168.1.222:8000/30
*   Trying 192.168.1.222:8000...
* Connected to 192.168.1.222 (192.168.1.222) port 8000 (#0)
> GET /30 HTTP/1.1
> Host: 192.168.1.222:8000
> User-Agent: curl/7.81.0
> Accept: */*
> 
* Mark bundle as not supporting multiuse
< HTTP/1.1 200 OK
< Server: Werkzeug/2.1.2 Python/3.10.4
< Date: Fri, 20 May 2022 01:32:50 GMT
< Content-Type: text/html; charset=utf-8
< Content-Length: 30
< Connection: close
< 
* Closing connection 0
xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx

node.js server

$ curl -v http://192.168.1.222:8000/30
*   Trying 192.168.1.222:8000...
* Connected to 192.168.1.222 (192.168.1.222) port 8000 (#0)
> GET /30 HTTP/1.1
> Host: 192.168.1.222:8000
> User-Agent: curl/7.81.0
> Accept: */*
> 
* Mark bundle as not supporting multiuse
< HTTP/1.1 200 OK
< Date: Fri, 20 May 2022 01:33:52 GMT
< Connection: keep-alive
< Keep-Alive: timeout=5
< Transfer-Encoding: chunked
< 
* Connection #0 to host 192.168.1.222 left intact
xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx

Note that the node.js server is doing Transfer-Encoding: chunked, and the Python server is not.

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't working

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions