[SOLVED] HTTP POST request on local network

For some project, I have to POST periodically some data to a http server inside my local network. I made this basic code :

TCPClient client;
byte ServerIP[]={192,168,1,125};//this is the IP address of the HTTP server

void setup() {
    Serial.begin(9600);
    Serial.println("starting...");
}

void loop() {
if(!client.connected())
{
Serial.println("disconnected");
if(client.connect(ServerIP,80))//the server is accessible on port 80
{
    Serial.println("connected");

     client.println("POST /myressource HTTP/1.0");
     client.println("From: mySpark");
     client.println("User-Agent: HTTPTool/1.0");
     client.println("Content-Type: application/json");
     client.println("Content-Length: 20");
     client.println("");
     client.println("{\"humidity\":\"43.5\"}");
     client.println();
}
else
{
    Serial.println("connection failed");
}
}
if (client.available())
{
    char c = client.read();
    Serial.print(c);
}
else
    delay(2000);
}

But I am not able to send this POST request to the server. I know it because of a wireshark analysis server-side.
As opposite, and with the same code structure, I was able to make a GET (with the appropriate http header fields) on the same server and it worked.
Do anyone see what’s going wrong with this code?

Thank you!

I’m not saying this is your problem, but HTTP header lines should be terminated by CRLF, not just LF as is generated by println. If you’re manually generating HTTP headers you should use print instead and manually terminate each line with \r\n or use some other technique. And the header is terminated by a blank line, which essentially ends up being \r\n\r\n. Once you’re in the POST body, you can generally use LF only (println) again.

1 Like

Thanks for helping.

I re tried, taking into account your thoughts:

client.print("POST /myressource HTTP/1.0\r\n");
client.print("From: mySpark\r\n");
client.print("User-Agent: HTTPTool/1.0\r\n");
client.print("Content-Type: application/json\r\n");
client.print("Content-Length: 20\r\n\r\n");
client.println("{\"humidity\":\"43.5\"}");
client.println();

Unfortunately, the behaviour remains the same…

@jipe_rey in the first line, you need make return and add a new line, meaning do this \r\n\r\n

Also set the HTTP version to 1.1, just in case.

I modified the POST request taking into account the \r\n on the beginning of the header. I also changed protocol to 1.1 and modified the Content-Length field (19 instead of 20).

client.print("\r\nPOST /myressource HTTP/1.1\r\n");
client.print("From: mySpark\r\n");
client.print("User-Agent: HTTPTool/1.0\r\n");
client.print("Content-Type: application/json\r\n");
client.print("Content-Length: 19\r\n\r\n");
client.println("{\"humidity\":\"43.5\"}");
client.println();

@davidgatti this seems to work !!! Thank you!

Wo interesting, I was thinking more about

client.print("POST /myressource HTTP/1.0\r\n\r\n");

But if what you did works, then lets just enjoy it :smiley:

Actually it worked with
client.print("\r\nPOST /myressource HTTP/1.1\r\n");
but I will test your suggestion, as I am still having problem, the server responds with something like
"connection: keep-alive" and actually I don’t want to keep the connection up.

double line change ends the request header, it shouldnt come after the POST line, but only after the last header line, in this case content-length.

Ooo now I see. Many thanks for dropping some knowledge :slight_smile:

Just wondering if you finally got this to work completely? I am just starting investigation into the same sort of thing and also noticing that after 2 years, not many working samples of how to do a POST.

I'm having similar issues. I think this topic has me pointed in the right direction, but when you need to connect to a service locally e.g. phant server. It requires your url to be /<yourservernamehere>/<yourpublickeyhere> That's not a problem, but then you also have to specify the header of the phant_private_key.
If I was using curl, it would looke something like this.

curl -X POST 'http://<ServerAddress>:8080/input/<PublicKey>' \
	-H 'Phant-Private-Key: <YourPrivateKeyHere>' \
	-d 'buttonPressed=<Value>'

Is the some special way you need to do the "client.print" to specify that one set of information is the header?

From your example, it looks like the -d or the data portion would look like client.println("{\"buttonPressed\":\"<value>\}");