Basic TCPClient GET request failing

Hi all.

Code as follows:

#define REPORT_DOMAIN "my.site.com"
TCPClient client;

void postKey(char* key) 
{

    Serial.print("Attempting to post..:");
    if (client.connect(REPORT_DOMAIN, 80)) {
        Serial.print("Connection OK:");
        client.println("GET http://"+(String)REPORT_DOMAIN+"/r.php?key="+(String)key+" HTTP/1.0");
        client.println("Host: "+(String)REPORT_DOMAIN);
        client.println();
        
        Serial.println("---");
        Serial.println("GET http://"+(String)REPORT_DOMAIN+"/r.php?key="+(String)key+" HTTP/1.0");
        Serial.println("Host: "+(String)REPORT_DOMAIN);
        Serial.println();        
        Serial.println("---");

        uint32_t startWait = micros();
        while(!client.available() && micros() < startWait + 5000) {delayMicroseconds(5);} 
        client.flush();
        client.stop();          
        Serial.print("Posted");
    } else {
        Serial.print("Connection failed..:");
    }
}

When the postKey function is called, I see via the serial debug:

Attempting to post..:Connection OK:---
GET http://my.site.com/r.php?key=TEST HTTP/1.0
Host: my.site..com

---
Posted

However - on the receiving end - nothing shows up.
If I copy / paste the printed data into nc:

[qx.qx-PC] ➤ nc my.site.com 80
GET http://my.site.com/r.php?key=TEST HTTP/1.0
Host: my.site.com
Content-Length: 0

HTTP/1.1 200 OK
Server: nginx

It works.
I’m at a loss at how to further debug this. Anyone had any success with this?
Any update on the webhooks? I thought they were meant to materialise in March :wink:

Thanks kindly.

Hi @simon

So get HTTP GET requests work great for me, so I know the core can do it.

Is the key string URL encoded? Could it contain funny characters, not like your TEST example?

What about a Connection: close header?

Or a Content-length: 0 header like in your nc example?

I also send an Accept: text/html, text/plain header.

I think you are using up some memory casting your C strings to Arduino String since I am not sure the compiler is smart enough to do the static analysis here. You can just print your C strings like this:

client.print("Host: ");
client.println(REPORT_DOMAIN);

Also you are only waiting 5ms for the response. That might be OK for a local host on the same subnet, but I know for instance that spark.io is about 140 ms away for me, so might want to try waiting longer.

Hi @bko - The test strings were actually just TEST
I will try to implement your suggestions and let you know.

Thank you kindly for your support!

And that seemed to do the trick!
It would appear it was the string casts - thanks very much for the suggestion !

2 Likes

Hey @bko
Actually, very strange thing:

void postKey(char* key) 
{

    Serial.print("Attempting to post..:");
    if (client.connect(REPORT_DOMAIN, 80)) {
        Serial.print("Connection OK:");
        client.print("GET http://");
        client.print(REPORT_DOMAIN);
        client.print("/r.php?key=");
        client.print(key);
        client.println(" HTTP/1.1");
        client.print("HOST: ");
        client.println(REPORT_DOMAIN);
        client.println("Connection: close");
        client.println();
        
        uint32_t startWait = micros();
        while(!client.available() && micros() < startWait + 5000) {delayMicroseconds(500);} 
        client.flush();
        client.stop();          
        Serial.print("Posted");
    } else {
        Serial.print("Connection failed..:");
    }
}

Fails - but when I change it to (note the LACK of space)

        client.println("HTTP/1.1");

It works. On the receiving end, I get:

array (
  'key' => 'TESTHTTP/1.1:',
)

Which is obviously wrong - but if I add the space in before the HTTP/1.1 - it fails.

This is bang-your-head-on-the-wall type frustrating… any ideas?

Hi @simon

You don’t need the “http://” or the host name parts on the GET request. It should look like:

client.print("GET ");
client.print("/r.php?key=");
client.print(key);
client.println(" HTTP/1.1");