Search code examples
httpsarduinoinfluxdbethernetteensy

400 Bad Request while posting to InfluxDB with NativeEthernet


For a project we are trying to monitor a status protocol sent on local network over TCP and post these status messages over HTTPS to a InfluxDB instance on AWS at https://www.influxdata.com/products/influxdb-cloud/.

We are using a teensy 4.1 with a ethernet kit in combination with the Native Ethernet library by vjmuzik https://github.com/vjmuzik/NativeEthernet.

Posting a string to a test instance over LAN to a IP works fine, but whenever we try to post to the AWS subdomain we are greeted with this response:

HTTP/1.1 400 Bad Request
Server: awselb/2.0
Date: Mon, 27 Sep 2021 18:13:02 GMT
Content-Type: text/html
Content-Length: 122
Connection: close

<html>
<head><title>400 Bad Request</title></head>
<body>
<center><h1>400 Bad Request</h1></center>
</body>
</html>

Since we verified the headers and body of the post are correct when we post locally, and posting to AWS works when using Postman, we are at a loss at the moment. Unfortunately I have no information about the configuration of the server we try to POST to.

We have tried:

  • Using different ethernet libraries, at the moment we are using NativeEthernet from vjmuzik https://github.com/vjmuzik/NativeEthernet
  • Different sets of headers
  • Adding google dns in ethernet.begin()
  • Post over http followed by a post over https after following the redirect response generated by the plain html request
  • Adding certificates
  • Verifying the InfluxDB line protocol with postman

As a test we set-up the WebClientRepeatingTLS example using our own POST headers and body.

#include <NativeEthernet.h>

uint8_t mac[6];
void teensyMAC(uint8_t *mac) {
  for (uint8_t by = 0; by < 2; by++) mac[by] = (HW_OCOTP_MAC1 >> ((1 - by) * 8)) & 0xFF;
  for (uint8_t by = 0; by < 4; by++) mac[by + 2] = (HW_OCOTP_MAC0 >> ((3 - by) * 8)) & 0xFF;
  Serial.printf("MAC: %02x:%02x:%02x:%02x:%02x:%02x\n", mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]);
}

// initialize the library instance:
EthernetClient client;
const int port = 443;

char server[] = "influxdata.com";  

//IPAddress server(192, 168, 1, 246);

String outputMSG = "measurementName,tagKey=tagValue fieldKey=1i";
unsigned long lastConnectionTime = 0;           // last time you connected to the server, in milliseconds
const unsigned long postingInterval = 5 * 1000; // delay between updates, in milliseconds

void setup() {
  teensyMAC(mac);
  Serial.begin(9600);
  while (!Serial) {
    ; 
  }

  Serial.println("Initialize Ethernet with DHCP:");
  if (Ethernet.begin(mac) == 0) {
    Serial.println("Failed to configure Ethernet using DHCP");
    if (Ethernet.hardwareStatus() == EthernetNoHardware) {
      Serial.println("Ethernet shield was not found.  Sorry, can't run without hardware. :(");
      while (true) {
        delay(1);
      }
    }
    if (Ethernet.linkStatus() == LinkOFF) {
      Serial.println("Ethernet cable is not connected.");
    }
  } else {
    Serial.print("  DHCP assigned IP ");
    Serial.println(Ethernet.localIP());
  }
  delay(1000);
}

void loop() {
  if (client.available()) {
    char c = client.read();
    Serial.write(c);
  }
  if (millis() - lastConnectionTime > postingInterval) {
    httpRequest();
  }

}

void httpRequest() {
  client.stop();
  Serial.print("Content-Length: ");
  Serial.println(outputMSG.length());
  Serial.println("");

  if (client.connect(server, port, true)) { 
    Serial.println("connecting to ");
    Serial.print(server);
    Serial.print(":");
    Serial.println(port);

        client.println("POST /api/v2/write?org=ORG_HERE&bucket=BUCKET_HERE&precision=s HTTP/1.1");
        client.println("Host: https://eu-central-1-1.aws.cloud2.influxdata.com");
        client.println("Authorization: Token <<TOKEN HERE>>");
        client.println("Content-Type: text/plain");
        client.print("Content-Length: ");
        client.println(outputMSG.length());
        client.println("Accept-Encoding: gzip, deflate, br");
        client.println("Connection: keep-alive");
        client.println();
        client.println(outputMSG);
        client.println();
        
    lastConnectionTime = millis();
  } else {
    Serial.println("connection failed");
  }
}

Could anyone help us understand why the post to aws is not going through?

Cheers, Boy


Solution

  • Using the EthernetWebServerSSL library in combination with theQNEthernet library made it possible for the teensy to connect to the AWS subdomain and therefor allowed it to post to the Influxdb database.