Convert memory content to char or string

Hi all,
I have found this code that read from a web site ( api.ipify.org) my IP public address and must return me. What i need is to have it in char or string format.

Part of the code is this :

.......
......

   if (sitoweb.connect(server, 80)) {
           int timeout = millis() + 5000;
           sitoweb.print("GET /?format=text HTTP/1.1\r\nHost: api.ipify.org\r\n\r\n");
            while (sitoweb.available() == 0) {
                   if (timeout - millis() < 0) {
                         Serial.println(">>> Client Timeout !");
                         sitoweb.stop();
                   }
             }
             int size;
             while ((size = sitoweb.available()) > 0) {
                       uint8_t* msg = (uint8_t*)malloc(size);
                       size = sitoweb.read(msg, size);
                       Serial.write(msg, size);
                       free(msg);
              }
    }

It works and give this output :

HTTP/1.1 200 OK
Server: Cowboy
Connection: keep-alive
Content-Type: text/plain
Vary: Origin
Date: Wed, 14 Jul 2021 20:16:22 GMT
Content-Length: 14
Via: 1.1 vegur

123.456.789.123 (changed by me but it is my ip public address)

What i need is to get ONLY the IP address (ever line 9) but in char or string format.

What i have is only a pointer to a memory zone where the data is :

         uint8_t* msg = (uint8_t*)malloc(size);
         size = sitoweb.read(msg, size);
         Serial.write(msg, size);

that is written to the serial.

I need that data into a string !!!!
But HOW to convert the content of the memory to char ?

I have tried to use this

added at the beginning of declaration.

    char ms[500];

and in the loop changed so to add the snprintf .

   while ((size = sitoweb.available()) > 0) {
        uint8_t* msg = (uint8_t*)malloc(size);
        size = sitoweb.read(msg, size);
        Serial.write(msg, size);
        
        snprintf_P(ms, 200, "%s", *msg);

       free(msg);
    }

The snprintf added doesn't work.

i need to have "msg" in a char or string to manipulate it.

Can you help me ?

Really thanks

Those first few lines of the response are the response "header". Then there is a blank line before the "body" which contains the data you requested.

Instead of using complex memory pointers and dynamic memory allocation with malloc() and free() it would be safer and easier for you to use Strings (note the capital S in String, as opposed to ordinary C-strings which are character arrays).

For example you could use

while (sitoweb.readStringUntil('\n') != ""); //Discard response header and blank line
String ip = sitoweb.readStringUntil('\n');

(Untested!)

Hi Paul, really thanks.
I will check this afternoom at home (now i am at work).
I will let you know.
Really thanks for the answer.

Hi paul,
i have just checked and it doesn't work.
I don't know why but inside the IP variable there is blank. Nothing

Any other suggestion ?

Thanks

Don't try to parse the HTTP response manually, use a library: arduino-esp32/BasicHttpClient.ino at master · espressif/arduino-esp32 · GitHub

Also:

Hi, i have tried this :

    String leo;
    r = 1;

    while ((size = sitoweb.available()) > 0) {
        leo = sitoweb.readStringUntil('\n');
        Serial.print("R = ");
        Serial.print(r);
        Serial.print(" - ");
        Serial.println(leo);
        ++r;
        if (r == 11) {
            ipad = leo;
        }
    }

The absurd things i cannot understand is that the output is :

R = 1 - H
R = 2 - S
R = 3 - C
R = 4 - C
R = 5 - V
R = 6 - D
R = 7 - C
R = 8 - V
R = 9 -
R = 10 - 8
8

It shows only the first character instead of the whole string !!!!!!!!!!!!

It shoud be :

1-HTTP/1.1 200 OK
2-Server: Cowboy
3-Connection: keep-alive
4-Content-Type: text/plain
5-Vary: Origin
6-Date: Wed, 14 Jul 2021 20:16:22 GMT
7-Content-Length: 14
8-Via: 1.1 vegur
9 -
10-123.456.789.123

123.456.789.123

Any ideas ??

What board?
If you use an esp, then it's this simple:

Serial.println(WiFi.localIP());

That prints the local IP address, not the public one.

Hi Steve, that print the LOCAL ip ethernet properties.
My routine goes to fetch form the internet site the properties of my PUBLIC ip address i'm surfing with.
Thanks anyway for the appreciated help.

I don't have any recent experience with using GET, but when I type: https://api.ipify.org into my browser, all I get is my public IP address.

That's because your browser only shows the body of the response, it doesn't show the actual HTTP headers that it received.

OP's code doesn't use any HTTP parsers, he's just reading the raw bytes coming over the TCP socket, so he'll get the HTTP response headers first, then an empty line, followed by the contents of the body.
IMO, there's no reason to do this manually, and it's very easy to write an HTTP parser that's not robust if one of the headers changes in the future. Just use an HTTP library.

Got it.

Hi PieterP,
i don't use Esp8266 nor Esp32 so i don't have Wifi.
What i don't understand that is making me mad, is that sometimes it works and sometimes not.

It seems that the delay after the Serial.begin and Ethernet.begin should be more than 2000 to make it works !!!! Amazing !!!!!!!!!!!!!

Any ideas ?

Really thanks

Steve, i don't want to see it in browser. In my browser it works, but what i refer to is the Serial Output.

That is strange. Can you post your complete code please, or at least a short version which demonstrates the problem?

The blank line between the headers and the body of an http response is part of the standard, I think, and so won't be changing. Using a library to discard lines until a blank line is read seems overkill to me.

My comment about changing headers was in response to the code in reply #6 that always reads the 11th line of the message.

Perhaps, but these libraries are known to work, and there's no need to reinvent the wheel. Case in point, this thread has multiple “simple” solutions that simply don't work.

That sounds like a hacky solution. You might want to try Stream.setTimeout() - Arduino Reference instead of adding delays.

Certainly would be amazing, because that should make no difference at all! So you are saying that a delay (2000) in setup() fixed the problem of only printing the first character of each line, and now you see the lines in full?

We need to see that full code. You are talking about lines of code that we have never seen.

I was thinking along similar lines.

@dottstrange When your sketch was printing only the first character of each line, was there a 1 second delay between printing each of those lines? I am asking because the default timeout is 1000ms, so if .readStringUntil() does not find that '/n' character within 1 second, it will time out and return the string it has when it times out. But if that's happening, where are the other characters in the lines going? It doesn't make any sense!

That's fair enough, I completely agree. Relying on the header being 10 lines long (including the blank line) would be unwise. But detecting that blank line between the header and body should be perfectly reliable, I think.