WebServer multiple html pages

Hi there,

I wish to get two type of output from my Arduino WebServer…

  1. If I type only the IP address, the output would be a simple HTML “Hello world!”, page 1.
  2. But, if I type the IP address and /test the output would another HTML output, page 2.
#include "UIPEthernet.h"

String inStr;
 
byte mac[] = {0x54,0x34,0x41,0x30,0x30,0x31};
byte ip[] = {192,168,0,176};
byte gateway[] = {192,168,0,251};
byte subnet[] = {255,255,255,0};

EthernetServer server(80);
EthernetClient client;

void setup() {
  Serial.begin(9600);
  Ethernet.begin(mac, ip, gateway, subnet);
  server.begin();
}

void page1() {
  client.println(F("HTTP/1.1 200 OK"));
  client.println(F("Content-Type: text/html"));
  client.println();
  client.println(F("<HTML>"));
  client.println(F("<HEAD>"));
  client.println(F("<TITLE>Hello World - Page 1</TITLE>"));
  client.println(F("</HEAD>"));
  client.println(F("<BODY>"));
  client.println(F("<p>Hello World - Page 1</p>"));
  client.println(F("</BODY>"));
  client.println(F("</HTML>"));  
  delay(1);
  client.stop();
}

void page2() {
  client.println(F("HTTP/1.1 200 OK"));
  client.println(F("Content-Type: text/html"));
  client.println();
  client.println(F("<HTML>"));
  client.println(F("<HEAD>"));
  client.println(F("<TITLE>Hello World - Page 2</TITLE>"));
  client.println(F("</HEAD>"));
  client.println(F("<BODY>"));
  client.println(F("<p>Hello World - Page 2</p>"));
  client.println(F("</BODY>"));
  client.println(F("</HTML>"));  
  delay(1);
  client.stop();
}

void loop() {
    client = server.available();
    if (client) {
        while (client.connected()) {
            if (client.available()) {
                char c = client.read();
                if (inStr.length() < 100) {
                    inStr += c;
                }
                //If the HTTP request is successful
                if (c == '\n') {
                    // Write to the serial monitor for debugging
                    Serial.println(inStr);
                    
                    if(strncmp("GET /page2", c, 10) == 0){
                      page2();
                    }else{
                      page1(); 
                    }
                  inStr=""; 
                }
            }
        }
    }
}

I would like to use it like this:

192.168.0.176 or 192.168.0.176/page1 or 192.168.0.176/page2

Thank you!

I would like to use it like this:

So, what is the problem?

                    if(strncmp("GET /page2", c, 10) == 0){

RTFM. The second argument to strncmp is NOT a character.

beic:
Hi there,

I wish to get two type of output from my Arduino WebServer…

  1. If I type only the IP address, the output would be a simple HTML “Hello world!”, page 1.
  2. But, if I type the IP address and /test the output would another HTML output, page 2.
#include "UIPEthernet.h"

String inStr;

byte mac = {0x54,0x34,0x41,0x30,0x30,0x31};
byte ip = {192,168,0,176};
byte gateway = {192,168,0,251};
byte subnet = {255,255,255,0};

EthernetServer server(80);
EthernetClient client;

void setup() {
 Serial.begin(9600);
 Ethernet.begin(mac, ip, gateway, subnet);
 server.begin();
}

void page1() {
 client.println(F(“HTTP/1.1 200 OK”));
 client.println(F(“Content-Type: text/html”));
 client.println();
 client.println(F(""));
 client.println(F(""));
 client.println(F(“Hello World - Page 1”));
 client.println(F(""));
 client.println(F(""));
 client.println(F(“

Hello World - Page 1

”));
 client.println(F(""));
 client.println(F(""));  
 delay(1);
 client.stop();
}

void page2() {
 client.println(F(“HTTP/1.1 200 OK”));
 client.println(F(“Content-Type: text/html”));
 client.println();
 client.println(F(""));
 client.println(F(""));
 client.println(F(“Hello World - Page 2”));
 client.println(F(""));
 client.println(F(""));
 client.println(F(“

Hello World - Page 2

”));
 client.println(F(""));
 client.println(F(""));  
 delay(1);
 client.stop();
}

void loop() {
   client = server.available();
   if (client) {
       while (client.connected()) {
           if (client.available()) {
               char c = client.read();
               if (inStr.length() < 100) {
                   inStr += c;
               }
               //If the HTTP request is successful
               if (c == ‘\n’) {
                   // Write to the serial monitor for debugging
                   Serial.println(inStr);
                   
                   if(strncmp(“GET /page2”, c, 10) == 0){
                     page2();
                   }else{
                     page1();
                   }
                 inStr="";
               }
           }
       }
   }
}




I would like to use it like this:


192.168.0.176 or 192.168.0.176/page1 or 192.168.0.176/page2





Thank you!

You need to understand the http request protocol.

Read through this page: Introduction to HTTP Basics

A simple browser request results in a block of data:

 http://www.nowhere123.com/doc/index.html

causes most browsers to send a block like this to the ‘server’:

GET /docs/index.html HTTP/1.1
Host: www.nowhere123.com
Accept: image/gif, image/jpeg, */*
Accept-Language: en-us
Accept-Encoding: gzip, deflate
User-Agent: Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1)
(blank line)

Where (blank line) is a \r\n

Your simple:

if(strncmp("GET /page2", c, 10) == 0){

is almost usable, but not quite.

I would recommend you not use the String() object. It causes heap fragmentation, and is very inefficient in RAM usage.

If you don’t care about the data after the GET line do something like this for your loop

void loop() {
client = server.available();
if (client) {

 bool foundGet=false;
 bool gotPageName=false; // some status / control variables
 bool eatInput= false; // read all input from client until the \r\n\r\n end marker is found
 bool blankLine = true; // no characters have been read into the pageName[] buffer.
 bool done= false;
 char pageName[100]; // a character buffer to store the request page name
 uint8_t len=0; // current count of characters in pageName

 while (client.connected()) {
   if (client.available()) {
     char c = client.read();
     if(!eatInput){ // actuall process characters, else just trash them.
       if(c == '\n' ){ // found an end of line, so pageName.  lines should be terminate \r\n but \n is acceptable
         if(blankLine) { // a blank line marks the end of the 'header' section
           done = true;
           }
         else{ // now we need to look for GET
           if(!foundGet){
             int result=strcmp("GET ",pageName); // strcmp return 0 strings match
             if(result==0) {
               foundGet=true; 
        // now I delete "GET " from the pageName.
               memmove(&pageName[0],&pageName[4],strlen(pageName)-3); // have to move the \0 also
 // now I trim off the 'HTTP' verision info, by looking for a ' ' space as the separator.
               char* space=strchr(pageName,' '); // start looking for a space
               if(space!=NULL){ // found the space, just inject a \0 overtop the ' '
                 space[0] = '\0';
                 gotPageName = true; // all done, found the referenced page
                 eatInput = true; // just discard all additional data until the end of the header
                 }
               } // found 'get'
             }
          blankLine=true; //starting new line, might be blank.
          }
       }
    else { //  c contains the current character read from the header block.
      if((c >= 32)&&(c <=127)) { // a valid character, maybe add it to the pageName buffer
        blankLine = false; // this line had a character.
        if((!gotPageName)&&(len<99)){ // build name, room in buffer
          pageName[len++] = c; // store the character, increment length
          pageName[len] = '\0';  // append a null to mark the end of the string.
          }
        }
     }
   }
 } // data available from client.
if(done){ // processed all data in header from client
  if (gotPageName){ // now we decide what to return to the client.
    if(strcmp("/page2",pageName)==0){ 
      page2();
      }
    else {
      page1();
      }
    }
 else { // an error happend, report it
   }
 
 delay(10);// allow the ethernet to actually send the block
      client.close(); // end the connection 
 }
 
 }

This code is untested.

Chuck.

Here is my example server code. It will serve several file types, but requires the files to be on a SD card. It is tested, but the code is a bit big for an Uno. I use a Mega2560. http://playground.arduino.cc/Code/WebServerST

SurferTim: Here is my example server code. It will serve several file types, but requires the files to be on a SD card. It is tested, but the code is a bit big for an Uno. I use a Mega2560. http://playground.arduino.cc/Code/WebServerST

Thank you, but can't use it, because I'm using ENC28J60 Ethernet module, whole different approach.

chucktodd:
You need to understand the http request protocol.

Read through this page: Introduction to HTTP Basics

A simple browser request results in a block of data:

 http://www.nowhere123.com/doc/index.html

causes most browsers to send a block like this to the ‘server’:

GET /docs/index.html HTTP/1.1

Host: www.nowhere123.com
Accept: image/gif, image/jpeg, /
Accept-Language: en-us
Accept-Encoding: gzip, deflate
User-Agent: Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1)
(blank line)




Where **(blank line)** is a \r\n

Your simple:


if(strncmp(“GET /page2”, c, 10) == 0){




is almost usable, but not quite.

I would recommend you not use the **String()** object. It causes heap fragmentation, and is very inefficient in RAM usage.

If you don't care about the data after the **GET** line do something like this for your loop



void loop() {
client = server.available();
if (client) {

bool foundGet=false;
bool gotPageName=false; // some status / control variables
bool eatInput= false; // read all input from client until the \r\n\r\n end marker is found
bool blankLine = true; // no characters have been read into the pageName buffer.
bool done= false;
char pageName[100]; // a character buffer to store the request page name
uint8_t len=0; // current count of characters in pageName

while (client.connected()) {
  if (client.available()) {
    char c = client.read();
    if(!eatInput){ // actuall process characters, else just trash them.
      if(c == ‘\n’ ){ // found an end of line, so pageName.  lines should be terminate \r\n but \n is acceptable
        if(blankLine) { // a blank line marks the end of the ‘header’ section
          done = true;
          }
        else{ // now we need to look for GET
          if(!foundGet){
            int result=strcmp("GET “,pageName); // strcmp return 0 strings match
            if(result==0) {
              foundGet=true;
       // now I delete “GET " from the pageName.
              memmove(&pageName[0],&pageName[4],strlen(pageName)-3); // have to move the \0 also
// now I trim off the ‘HTTP’ verision info, by looking for a ’ ’ space as the separator.
              char* space=strchr(pageName,’ '); // start looking for a space
              if(space!=NULL){ // found the space, just inject a \0 overtop the ’ ’
                space[0] = ‘\0’;
                gotPageName = true; // all done, found the referenced page
                eatInput = true; // just discard all additional data until the end of the header
                }
              } // found ‘get’
            }
         blankLine=true; //starting new line, might be blank.
         }
      }
   else { //  c contains the current character read from the header block.
     if((c >= 32)&&(c <=127)) { // a valid character, maybe add it to the pageName buffer
       blankLine = false; // this line had a character.
       if((!gotPageName)&&(len<99)){ // build name, room in buffer
         pageName[len++] = c; // store the character, increment length
         pageName[len] = ‘\0’;  // append a null to mark the end of the string.
         }
       }
    }
  }
} // data available from client.
if(done){ // processed all data in header from client
 if (gotPageName){ // now we decide what to return to the client.
   if(strcmp(”/page2”,pageName)==0){
     page2();
     }
   else {
     page1();
     }
   }
else { // an error happend, report it
  }

delay(10);// allow the ethernet to actually send the block
     client.close(); // end the connection
}

}





This code is untested.

Chuck.

Ok, but what you think about this?

if (c == '\n') {
  if (inStr.indexOf("page1") > 0) {
    page1();
  } else if (inStr.indexOf("page2") > 0) {
    page2();
  } else {
    error();
}

beic: Ok, but what you think about this?

if (c == '\n') {
  if (inStr.indexOf("page1") > 0) {
    page1();
  } else if (inStr.indexOf("page2") > 0) {
    page2();
  } else {
    error();
}

The else case will trigger for each line received that does not contain "page1" or "page2".

in my example: it would trigger error() 6 times.

Is that what you want?

Chuck.

chucktodd: The else case will trigger for each line received that does not contain "page1" or "page2".

in my example: it would trigger error() 6 times.

Is that what you want?

Chuck.

No, I don't want that, but can your example be a little bit shorter maybe (I'm on 87% usage)?

Regards