Parsing GET Variables

strcmp() and strncmp() return one of 3 values. A negative number means that the first string comes after the 2nd string in the dictionary. A positive number means that the first string comes before the 2nd string in the dictionary. A zero means that the strings are the same.

The snippet you posted will not compile, so it's hard to says what you mean for it to do.

i ment like

 if(strncmp(pch,"r=",2) == 0)
            {

but anyway my actual code

void loop () {
  word len = ether.packetReceive();
  word pos = ether.packetLoop(len);
  
  
  if (pos) {
  char* data = (char *) Ethernet::buffer + pos;
  
 if (strncmp("GET /", data, 6) ==0)
 
 char *token = strtok(data, "/"); // Get everything up to the /


if(token) // If we got something
{
  if (strncmp("mode=blink&", NULL, 5)) {
    
  char *name =strtok(NULL, "mode=blink&");
  char *type =strtok(NULL, "rate=");
  char *type =strncopy(
  Serial.print(type);
  char *code =strtok(NULL, "&color=");
  Serial.print(code);
  }  
}
  }
}

so the problem is "rate" which is between rate= and the next &.
When the pointer goes from token to type, then type is kind of copy from token?
How i can save the actual splitted string for example with color=yellow to yellow that i have yellow in an seperate value and
then be able to split the rest further?

  if (strncmp("mode=blink&", NULL, 5)) {

You are checking to see if 5 characters of a hardcoded string are NULL. Why, you already know the answer to that question.

  char *name =strtok(NULL, "mode=blink&");

So, the delimiters are 'm', 'o', 'd', 'e', '=', 'b', 'l', 'i', 'n', 'k', and '&'. Does that really make sense?

  char *type =strtok(NULL, "rate=");

Here, the delimiters are 'r', 'a', 't', 'e', and '='. The appearance of any one of the letters will define the end of the token, and will be removed from the string. Is that what you really want?

Please, at least try to compile code before you post it.

PaulS:

  char *name =strtok(NULL, "mode=blink&");

So, the delimiters are 'm', 'o', 'd', 'e', '=', 'b', 'l', 'i', 'n', 'k', and '&'. Does that really make sense?

i thought it makes sense because i know there is an string with that beginning.
so mode=blink&rate=30&color=yellow will then start at
rate=30&color=yellow.
After that i wanted to extract the 30 for example ( i don't know how long the value after rate= is)

The tokens (delimiters) are "?& ". Those are the characters that separate your variables. strtok is not the same as strcmp. These are from a C++ example, but it is the same for C.
http://www.cplusplus.com/reference/clibrary/cstring/strtok/
http://www.cplusplus.com/reference/clibrary/cstring/strcmp/
http://www.cplusplus.com/reference/clibrary/cstring/strncmp/

My example above still works. :slight_smile:

edit: I forgot the space as a delimiter so you can separate the HTTP/1.1 from the end of the request, so I added it.

SurferTim:
My example above still works. :slight_smile:

edit: I forgot the space as a delimiter so you can separate the HTTP/1.1 from the end of the request, so I added it.

i tried to understand your code but i couldnt follow. i think its to much for my humble knowledge.
would it be ok for you if you give me an example with my mode=blink&rate=30&color=yellow example?
Otherwise i think i will end in a kind of guesswork.

i have no idea how i can make it possible that
when "i" know the mode i can insert the rate and color option into my programm.

i would try to difference it by making an if construct.

This is about as simple as I can make it.

#include <SPI.h>
#include <Ethernet.h>

byte mac[] = { 0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED };
IPAddress ip( 192,168,0,2 );
IPAddress gateway( 192,168,0,1 );
IPAddress subnet( 255,255,255,0 );
IPAddress dns( 192,168,0,1 );

EthernetServer server(80);

void setup()
{
  Serial.begin(9600);
  pinMode(4,OUTPUT);
  digitalWrite(4,HIGH);
  Ethernet.begin(mac, ip, dns, gateway, subnet);
  delay(2000);
  server.begin();
  Serial.println("Ready");
}

void loop()
{
 
  EthernetClient client = server.available();
  if(client) {
    boolean currentLineIsBlank = true;
    boolean currentLineIsGet = true;
    int tCount = 0;
    char tBuf[64];
    int rate;
    char *pch;
    
    Serial.print("Client request: ");
    
    while (client.connected()) {
      while(client.available()) {
        char c = client.read();

        if(currentLineIsGet && tCount < 63)
        {
          tBuf[tCount] = c;
          tCount++;
          tBuf[tCount] = 0;          
        }

        if (c == '\n' && currentLineIsBlank) {

          while(client.available()) client.read();
          Serial.println(tBuf);
          pch = strtok(tBuf,"?");

          while(pch != NULL)
          {
            if(strcmp(pch,"mode=blink") == 0)
            {
                Serial.println("mode=blink");
                // do mode = blink stuff
            }
            else if(strcmp(pch,"mode=steady") == 0)
            {
                Serial.println("mode=steady");
                // do mode = steady stuff
            }
            else if(strcmp(pch,"color=yellow") == 0)
            {
                Serial.println("color=yellow");
                // do color=yellow stuff
            }
            else if(strcmp(pch,"color=red") == 0)
            {
                Serial.println("color=red");
                // do color=red stuff
            }
            else if(strncmp(pch,"rate=",5) == 0)
            {
              rate = atoi(pch+5);
              Serial.print("rate = ");              
              Serial.println(rate,DEC);
            }

            pch = strtok(NULL,"& ");
          }

          Serial.println("Sending response");
          client.write("HTTP/1.0 200 OK\r\nContent-Type: text/html\r\n\r\n<html><body><H1>TEST</H1>");

          client.write("<form method=GET>Mode: <input type=text name=mode>
");
          client.write("Rate: <input type=text name=rate>
");
          client.write("Color: <input type=text name=color>
<input type=submit></form>");
          
          client.write("</body></html>\r\n\r\n");
          client.stop();
        }
        else if (c == '\n') {
          currentLineIsBlank = true;
          currentLineIsGet = false;
        } 
        else if (c != '\r') {
          currentLineIsBlank = false;
        }
      }
    }
    Serial.println("done");
  }
}

Do you understand the code?

edit: changed text field names to reflect the changed variables.

Thank you for the snippet. I can understand the code but it doesn't fit with my ethercard.
I'm not using the arduino original shield but an board with the ethercard libary.

Anyway, as far as i understand the code you read the value rate with a count to the end of rate=*.
So what is if i dont know if there are one or two digits? In the example the code is based on the knowledge that it must be pch+5 which would say that the
value can only 0-9. But what if the possible range is unknown? Same thing for the color in my project there would be an valu that comes in hexcode with unknown length of symbols.
like rate=302&color=c2c4

Anyway, as far as i understand the code you read the value rate with a count to the end of rate=*.
So what is if i dont know if there are one or two digits? In the example the code is based on the knowledge that it must be pch+5 which would say that the
value can only 0-9. But what if the possible range is unknown?

atoi does not just convert the one character. It will convert all numeric characters until it hits a non-numeric character.

Your request should look like this
GET /?mode=steady&rate=305&color=yellow HTTP/1.0
so when you do the atoi(pch+5), it would return the integer value 305. The (pch+5) is a pointer addition. It will start converting to an integer at the 5th position after the start of the string. That is the character after the '='.

edit: As the program goes through the loop, pch will be equal to (pointing at) these strings in each iteration:
GET /
mode=steady
rate=305
color=yellow
HTTP/1.0

Based on the above here is how I managed to get the variable part for http:///?interval=12.

if (pos) {
  char* data = (char *) Ethernet::buffer + pos;
  Serial.println(data);
  if (strncmp("GET /", data, 5) ==0){
  String str;

  char *token = strtok(data, "H"); // Get everything up to the /
  Serial.pri[/glow]nt("Token: ");Serial.println(token);
  char * pch;

  pch = strtok (token, "?");
  while(pch != NULL)
          {
            Serial.print("Pointer is: ");Serial.println(pch);
            if(strncmp(pch,"interval=",9) == 0){
              interval = atoi(pch+9);
              Serial.print("interval = ");              
              Serial.println(interval,DEC);
            }
           pch = strtok(NULL,"?");
      
 }
}
  String str;

In the midst of all that string manipulation, this is just perverse.

Hi im trying to parse some data from an HTTP request I have tried diferent codes but my problem is that the server also have to respond to other request like page stuff from SD card so I think that the GET from files and the GET to parse are interacting in the wrong way here is my code so far
if someone could help me please

 EthernetClient client = server.available();  // try to get client

  if (client) {  // got client?
    boolean currentLineIsBlank = true;
    while (client.connected()) {
      if (client.available()) {   // client data available to read
        char c = client.read(); // read 1 byte (character) from client
        // limit the size of the stored received HTTP request
        // buffer first part of HTTP request in HTTP_req array (string)
        // leave last element in array as 0 to null terminate string (REQ_BUF_SZ - 1)
        if (req_index < (REQ_BUF_SZ - 1)) {
          HTTP_req[req_index] = c;          // save HTTP request character
          req_index++;
        }
         if( client.find("?") ) {  // search for '?'
          // find tokens starting with "?" and stop on the first blank line
          // search to the end of line for 'pin'
          while(client.findUntil("joy", "\n\r")){  
            char type = client.read(); // D or A
            // the next ascii integer value in the stream is the pin
            float value = client.parseFloat(); 
            if( type == 't') {
              Serial.print("Throttle ");
              throt = value;
              int t1 = int (throt * 100);
              contr[0] = t1;
            }
            else if( type == 'y'){
              Serial.print("Steer ");
              steer = value;
              int t2 = int (steer * 100);
              contr[1] = t2;
            }
            else {
              Serial.print("Unexpected type ");
              Serial.print(type);
            }
           }
           Mirf.setTADDR((byte *)"clie1");
           Mirf.payload = sizeof(contr);
           Mirf.send(contr);
           while(Mirf.isSending()){
           }
        }
          
        // last line of client request is blank and ends with \n
        // respond to client only after last line received
        if (c == '\n' && currentLineIsBlank) {
          // send a standard http response header
          client.println("HTTP/1.1 200 OK");
          // remainder of header follows below, depending on if
          // web page or XML page is requested
          // Ajax request - send XML file
          /*if (StrContains(HTTP_req, "ajax_inputs")) {
           // send rest of HTTP header
           client.println("Content-Type: text/xml");
           client.println("Connection: keep-alive");
           client.println();
           SetLEDs();
           // send XML file containing input states
           XML_response(client);
           }
           
           else*/          if (StrContains(HTTP_req, "GET /cont.htm")) {
            // send rest of HTTP header
            client.println("Content-Type: text/html");
            client.println("Connection: keep-alive");
            client.println();
            // send web page  
            webFile = SD.open("cont.htm");        // open web page file

            // send web page to client
            if (webFile) {
              while(webFile.available()) {
                client.write(webFile.read());
              }
              webFile.close();
            }
          }