1

I'm running a modifed code on Arduino Uno + WiFi shield (updated), and I have seen strange behaviors with String ; here is my code, the goal is to parse a HTML request to know which page was requested :

String line = client.readStringUntil("\n");
Serial.print("Line : [");
Serial.print(line);
Serial.println("]");

String cmd = line.substring(0, 3);
Serial.print("Command : [");
Serial.print(cmd);
Serial.print("]");

My problem comes from what appears in the console :

Line : [GET / HTTP/1.1
Host: 192.168.43.200
Connection: keep-alive
Cache-Control: max-age=0
Upgrade-Insecure-Requests: 1
User-Agent: Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/56.0.2924.87 Safari/537.36
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8
Accept-Encoding: gzip, deflate, sdch
Ac] 
Command : []

I was expecting the cmd variable to contain GET, and I do not understand why it contains nothing.

I suspect this behavior comes from the lack of RAM (compiler says there are only 670 bytes available for local variables), but if it's the case, I do not know how to solve it, as I'm pretty inexperienced in C++ and I need to store a String containing the values that are sent as a reply to the HTTP request.

PS. I'm also wondering why the client.readStringUntil("\n") method sends the full request instead of only the first line.

0

In general, you don't want to be copying strings around when you don't have to because it's inefficient. For parsing things like command lines, you can often just work with the existing String (or better yet, string; see Majenko's tutorial).

In this particular example, you have a string and you want to know if it's an HTTP GET command. That's simple enough; the first four characters will be GET (we check the space on the end because we don't want to interpret GETMORE /foo as a GET command).

This is extremely easy:

String s = "GET /foo/bar";

if (s.startsWith("GET "))  
    Serial.println("GET command");
else
    Serial.println("Not GET command");

For stuff in the middle of a string you obviously can't use startsWith, but there are other functions that can help. For example, once you know it's a GET command, you know that the URL starts at position 4 (the 5th character, since counting starts at 0). You could test to see if it starts with '/foo' with

if (s.indexOf("/foo") == 4)
    Serial.println("Path starts with /foo.");
else
    Serial.println("Path doesn't start with /foo.");

That said, while this kind of thing is workable for quick tests, in the long run you probably want to move towards parsing in C in the way that Majenko's tutorial above talks about, and likely parsing as much as possible as you do the reading (rather than reading everything into memory and then parsing it) due to HTTP requests being relatively large compared to the memory you have to handle them.

  • In the end I used your link to learn more about C-style strings, and translated my whole code to use them, so I'm marking your answer as a solution, however the bigger problem was the string litterals : replacing them using the 'F()' macro freed 40% of the SRAM, and solved this problem. – CLOVIS Apr 15 '17 at 16:36
  • I'm glad to hear you got things worked out! I expect that the RAM being used by string literals being a problem didn't occur to anybody here because there's almost no use of string literals in the question, but that's certainly something to keep in mind if you have more than a few of them. – Curt J. Sampson Apr 15 '17 at 16:54
  • Well I'm coming here from Java, and I have this strange habit of using println()s to log everything instead of commenting my code :/ looks like it can backclash sometimes – CLOVIS Apr 15 '17 at 17:13
  • I have an other problem with memory usage of growing strings here ... If you have any tips for this one, I'd be glad to hear them – CLOVIS Apr 15 '17 at 17:18

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.