arduino-libraries / ArduinoHttpClient

Arduino HTTP Client library
282 stars 170 forks source link

Status code -3 after two requests in a row #30

Open geovannyAvelar opened 7 years ago

geovannyAvelar commented 7 years ago

I'm trying to authenticate with my API and send a POST.

void saveWeatherData(WEATHER_DATA data) {
  String jsonData = weatherDataToJson(data);
  Serial.println("Data has been collected");
  Serial.println(jsonData);
  Serial.println("Saving data...");

  HttpClient client = HttpClient(ethernetClient, SERVER_IP, SERVER_PORT);

  String urlAuth = generateAuthenticationUrl("root", "root", "password");

  client.beginRequest();
  client.post(urlAuth, "application/json", "");
  client.sendHeader("Authorization", "Basic d2VhdGhlcmxvZ2dlcjp3ZWF0aGVybG9nZ2Vy");
  client.endRequest();

  String token;
  int statusAuth = client.responseStatusCode();

  if(statusAuth == 200) {
      Serial.println("Authentication OK");
      String stringResponse = client.responseBody();

      DynamicJsonBuffer jsonBuffer;
      JsonObject& jsonResponse = jsonBuffer.parseObject(stringResponse);

      token = jsonResponse["access_token"].as<String>();
  } else {
    Serial.write("Error on authentication ");
    Serial.println(statusAuth);
  }

  delay(3000);

  String authHeader = "Bearer ";
  authHeader.concat(token);

  client.beginRequest();
  client.post("/", "application/json", jsonData);
  client.sendHeader("Authorization", authHeader);
  client.endRequest();

  int status = client.responseStatusCode();

  if(status == 201) {
    Serial.println("Data has been saved");
  } else {
    Serial.write("Error ");
    Serial.println(status);
  }

  client.stop();
  delay(5000);

}

Request to authentication enpoint works well, returning the access token. But the second request always return -3 status. If i make only one request to a random url it works, but the second fails. The second request never appears in my API logs.

melvinpmathew commented 7 years ago

I am also kind off in the same boat. SSL connection not working when using local SSL server, give me -3 error code. HTTPS failing 🙁

Turning off SSL-regular HTTP request works fine with basic auth and POST messaging.

Is this a known issue? Is there any support or other ways to achieve SSL?

sandeepmistry commented 6 years ago

@geovannyAvelar @melvinpmathew could you please share a full sketch to reproduce this and let us know what hardware you are using.

Bl4cksunLtd commented 6 years ago

I've had the same issue. Firstly I connect to /endpoint1 (and download some data) then later connect to /endpoint2 (to upload data). The server accepts the data sent to /endpoint2 (it's a json message) and continues without issue, however the client fails at that point with a timeout error (-3). Repeatedly calling the /endpoint2 send routine (after a delay(5000), will fail every time with a -3. I've found a work around for me that might be useful to others and maybe highlight the potential cause of the problem. Instead of using a single wificlient and httpclient for requests to both endpoints, I added a second wificlient and httpclient that use the same server address and port, but the second set of clients are used with /endpoint2. I can repeatedly make calls to the second endpoint after grabbing data from the first endpoint (with the original set of clients). So it seems like the problem is caused by changing endpoints between calls. Scratch all the above. It did appear to get round the problem, but I started getting the timeout (-3) errors on the 4th or 5th call to /endpoint2.

Warlib1975 commented 4 years ago

I've got the same -3 error instead of 403 error when using SSL connection. When I try to connect to the server using c# application it shows standard 403 auth error. It's ok. -3 code is informative.

dansiviter commented 3 months ago

Same issue here, first request (whatever it is) works, second fails. When using it on Giga it seems to be related to using InternetSocket#open(NetworkStack) which returns a NSAPI_ERROR_PARAMETER:

"NSAPI_ERROR_PARAMETER in case the provided stack was invalid or a stack was already created and socket opened successfully."

It appears when using TLS the HttpClient library should reuse or properly close down the socket before next request. I had hoped a workaround would be calling HttpClient#stop() but that just seems to crash the Giga.


Update: it seems HttpClient#connectionKeepAlive() does help a little and ensure you've drained the response with HttpClient#responseBody(). It's not fool proof, but I can get several requests off before it goes 💥