Excellent Arduino Ethernet Shield Web Server Tutorial

The only reservation I have about your/zoomkat's code is it does leave characters in the w5100 socket rx buffer. I have lost many sockets doing that. My server code empties the rx buffer (including any POST data in the request body) before sending a response. That pretty much insures a clean close without losing a socket. But that just me... :smiley:

Thanks, knowledge is king. Now to learn about sockets, :-).

The below meta refresh test code is for checking the turnaround time for a client/server interaction. The server code doesn't seem prone to hanging up on its own from what I can tell. The code has a counter to count the interactions.

// zoomkat's meta refresh data frame test page 8/17/13
// use http://192.168.1.102:84 in your brouser for main page
// http://192.168.1.102:84/data static data page
// http://192.168.1.102:84/datastart meta refresh data page
// for use with W5100 based ethernet shields
// set the refresh rate to 0 for fastest update
// use STOP for single data updates

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

const int analogInPin0 = A0;
const int analogInPin1 = A1;
const int analogInPin2 = A2;
const int analogInPin3 = A3;
const int analogInPin4 = A4;
const int analogInPin5 = A5;

byte mac[] = { 0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED }; //physical mac address
byte ip[] = { 192, 168, 1, 102 }; // arduino ip in lan
byte gateway[] = { 192, 168, 1, 1 }; // internet access via router
byte subnet[] = { 255, 255, 255, 0 }; //subnet mask
EthernetServer server(84); //server port
unsigned long int x=0; //set refresh counter to 0
String readString; 

//////////////////////

void setup(){
  Serial.begin(9600);
    // disable SD SPI if memory card in the uSD slot
  pinMode(4,OUTPUT);
  digitalWrite(4,HIGH);

  Ethernet.begin(mac, ip, gateway, gateway, subnet);
  server.begin();
  Serial.println("meta refresh data frame test 8/17/13"); // so I can keep track of what is loaded
}

void loop(){
  EthernetClient client = server.available();
  if (client) {
    while (client.connected()) {
      if (client.available()) {
        char c = client.read();
         if (readString.length() < 100) {
          readString += c; 
         } 
        //check if HTTP request has ended
        if (c == '\n') {

          //check get atring received
          Serial.println(readString);

          //output HTML data header
          //client.println("HTTP/1.1 200 OK");
          //client.println("Content-Type: text/html");
          //client.println();
          
          client.print(F("HTTP/1.0 200 OK\r\nContent-Type: text/html\r\n\r\n"));

          //generate data page
          if(readString.indexOf("data") >0) {  //checks for "data" page
            x=x+1; //page upload counter
            client.print("<HTML><HEAD>");
            //meta-refresh page every 1 seconds if "datastart" page
            if(readString.indexOf("datastart") >0) client.print("<meta http-equiv='refresh' content='1'>"); 
            //meta-refresh 0 for fast data
            if(readString.indexOf("datafast") >0) client.print("<meta http-equiv='refresh' content='0'>"); 
            client.print("<title>Zoomkat's meta-refresh test</title></head><BODY>
");
            client.print("page refresh number: ");
            client.print(x); //current refresh count
            client.print("

");
            
              //output the value of each analog input pin
            client.print("analog input0 is: ");
            client.print(analogRead(analogInPin0));
            
            client.print("
analog input1 is: ");
            client.print(analogRead(analogInPin1));
                        
            client.print("
analog input2 is: ");
            client.print(analogRead(analogInPin2));
            
            client.print("
analog input3 is: ");
            client.print(analogRead(analogInPin3));
                                    
            client.print("
analog input4 is: ");
            client.print(analogRead(analogInPin4));
            
            client.print("
analog input5 is: ");
            client.print(analogRead(analogInPin5));
            client.print("
</BODY></HTML>");
           }
          //generate main page with iframe
          else
          {
            client.print(F("<HTML><HEAD><TITLE>Zoomkat's frame refresh test</TITLE></HEAD>"
            "Zoomkat's Arduino frame meta refresh test 8/17/13"
            "

Arduino analog input data frame:
"
            "&nbsp;&nbsp;<a href='/datastart' target='DataBox' title=''yy''>META-REFRESH</a>"
            "&nbsp;&nbsp;&nbsp;&nbsp;<a href='/data' target='DataBox' title=''xx''>SINGLE-STOP</a>"
            "&nbsp;&nbsp;&nbsp;&nbsp;<a href='/datafast' target='DataBox' title=''zz''>FAST-DATA</a>
"
            "<iframe src='/data' width='350' height='250' name='DataBox'>"
            "</iframe>
</HTML>"));
          }
          delay(1);
          //stopping client
          client.stop();
          //clearing string for next read
          readString="";
        }
      }
    }
  }
}

I wrote a socket test sketch a few months ago. It is a web server, plus does a dns request for Google and ntp request every 30 seconds. It shows the socket status at different points during each. It shows for each socket
Socket#: D:(remote port)

The common status byte codes are
0x00 = available (not used)
0x14 = server waiting for client
0x17 = server with client
0x22 = udp

Insure network settings are correct, including a valid dns server.

#include <SPI.h>
#include <Ethernet.h>
#include <EthernetUdp.h>
#include <utility/w5100.h>
#include <Dns.h>

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

IPAddress timeServer;
EthernetServer server(80);
EthernetUDP Udp;
DNSClient dnsC;

long timer = 0L;
const int NTP_PACKET_SIZE= 48; // NTP time stamp is in the first 48 bytes of the message
byte packetBuffer[ NTP_PACKET_SIZE]; //buffer to hold incoming and outgoing packets 

void setup() {
  Serial.begin(9600);

  pinMode(4, OUTPUT);
  digitalWrite(4, HIGH);
        
  Ethernet.begin(mac, ip, dnServer, gateway, subnet);

  Serial.println("Start");
  server.begin();
  ShowSockStatus();
  timer = millis();
  dnsC.begin(dnServer);

  if(dnsC.getHostByName("pool.ntp.org",timeServer)) {
    Serial.print("\r\nNTP address = ");
    Serial.println(timeServer);            
  }  
  else Serial.println("dns fail");
  ShowSockStatus();
}

void loop()
{ 
  IPAddress remoteAddr;
  //Check if a web client has attached.
  checkServer();
        
  if ((millis() - timer) > 30000) {
    if(dnsC.getHostByName("www.google.com",remoteAddr)) {
      Serial.print(F("\r\nIP address = "));
      Serial.println(remoteAddr);            
    }  
    else Serial.println(F("dns fail"));
          
    ShowSockStatus();
    delay(10);          
    timer = millis();
    checkTime();
  }
}

void ShowSockStatus()
{
  for (int i = 0; i < MAX_SOCK_NUM; i++) {
    Serial.print(F("Socket#"));
    Serial.print(i);
    uint8_t s = W5100.readSnSR(i);
    Serial.print(F(":0x"));
    Serial.print(s,16);
    Serial.print(F(" "));
    Serial.print(W5100.readSnPORT(i));
    Serial.print(F(" D:"));
    uint8_t dip[4];
    W5100.readSnDIPR(i, dip);
    for (int j=0; j<4; j++) {
      Serial.print(dip[j],10);
      if (j<3) Serial.print(".");
    }
    Serial.print(F("("));
    Serial.print(W5100.readSnDPORT(i));
    Serial.println(F(")"));
  }
}

unsigned long sendNTPpacket(EthernetUDP & Udp, IPAddress& address)
{
  memset(packetBuffer, 0, NTP_PACKET_SIZE); 
  packetBuffer[0] = 0b11100011;   // LI, Version, Mode
  packetBuffer[1] = 0;     // Stratum, or type of clock
  packetBuffer[2] = 6;     // Polling Interval
  packetBuffer[3] = 0xEC;  // Peer Clock Precision
  packetBuffer[12]  = 49; 
  packetBuffer[13]  = 0x4E;
  packetBuffer[14]  = 49;
  packetBuffer[15]  = 52;
  Udp.beginPacket(address, 123); //NTP requests are to port 123
  Udp.write(packetBuffer,NTP_PACKET_SIZE);
  Udp.endPacket(); 
}

void checkTime()
{
  Udp.begin(8888);
  sendNTPpacket(Udp, timeServer); // send an NTP packet to a time server
  Serial.println("\r\nTime check");
  ShowSockStatus();
  // wait to see if a reply is available
  delay(1000);  

  if ( Udp.parsePacket() ) {  
    // We've received a packet, read the data from it
    Udp.read(packetBuffer,NTP_PACKET_SIZE);  // read the packet into the buffer

    //the timestamp starts at byte 40 of the received packet and is four bytes,
    // or two words, long. First, esxtract the two words:

    unsigned long highWord = word(packetBuffer[40], packetBuffer[41]);
    unsigned long lowWord = word(packetBuffer[42], packetBuffer[43]);  
    // combine the four bytes (two words) into a long integer
    // this is NTP time (seconds since Jan 1 1900):
    unsigned long secsSince1900 = highWord << 16 | lowWord;  

    // now convert NTP time into everyday time:
    Serial.print("Unix time = ");
    // Unix time starts on Jan 1 1970. In seconds, that's 2208988800:
    const unsigned long seventyYears = 2208988800UL;     
    // subtract seventy years:
    unsigned long epoch = secsSince1900 - seventyYears;  
    // print Unix time:
    Serial.println(epoch);  
  }  
  else Serial.println("No NTP packet received");

  Udp.stop();
  ShowSockStatus();
}

void checkServer()
{
  EthernetClient client = server.available();
  if(client) {
    boolean currentLineIsBlank = true;
    boolean currentLineIsGet = true;
    int tCount = 0;
    char tBuf[64];
    int r,t;
    char *pch;

    Serial.println(F("\r\nServer client"));
    ShowSockStatus();

    Serial.print(F("\r\nClient request: "));

    // this controls the timeout
    int loopCount = 0;

    while (client.connected()) {
      while(client.available()) {
        // if packet, reset loopCount
        loopCount = 0;
        char c = client.read();
        if(currentLineIsGet && tCount < 63)
        {
          tBuf[tCount] = c;
          tCount++;
          tBuf[tCount] = 0;          
        }

        if (c == '\n' && currentLineIsBlank) {
          // send a standard http response
          Serial.println(tBuf);
          Serial.print(F("POST data: "));
          while(client.available()) Serial.write(client.read());
          Serial.println();

          pch = strtok(tBuf,"?");

          while(pch != NULL)
          {
            if(strncmp(pch,"t=",2) == 0)
            {
              t = atoi(pch+2);
              Serial.print(F("t="));
              Serial.println(t,DEC);             
            }

            if(strncmp(pch,"r=",2) == 0)
            {
              r = atoi(pch+2);
              Serial.print(F("r="));              
              Serial.println(r,DEC);
            }


            pch = strtok(NULL,"& ");
          }
          Serial.println(F("Sending response"));
          client.print(F("HTTP/1.0 200 OK\r\nContent-Type: text/html\r\n\r\n<html>"));
          client.println(F("<body><H1>TEST</H1>"));
          client.println(F("<form method=GET>T: <input type=text name=t>
"));
          client.println(F("R: <input type=text name=r>
<input type=submit></form>"));


          client.println(F("</body></html>"));
          client.stop();
        }
        else if (c == '\n') {
          currentLineIsBlank = true;
          currentLineIsGet = false;
        } 
        else if (c != '\r') {
          currentLineIsBlank = false;
        }
      }

      loopCount++;

      // if 10000ms has passed since last packet
      if(loopCount > 10000) {
        // close connection
        client.stop();
        Serial.println(F("\r\nTimeout"));
      }

      // delay 1ms for timeout timing
      delay(1);
    }
    Serial.println(F("done"));
  }
}

edit: The timeServer ip will be assigned by dns from pool.ntp.org.
The available (0x00) and server waiting (0x14) sockets will show the remote ip and ports settings from the previous use of that socket.

Hi,

I use in my house an Arduino UNO with Ethernet Shield connected to the router that controls the lights of the house through the computer and smartphone by socket commands.

I am now trying to create a mini Webserver by Arduino to control the lights by Smart TV also through the browser, and I’m following the instructions in Part 5 of the tutorial.

I adapted the code from the tutorial with the code that I already used, but I have questions in some parts:

void loop() {

EthernetClient client = server.available();

// SE receber um caracter...

delay(50); 
if (client) {

boolean currentLineIsBlank = true;

// guarda o caracter na string 'msg'
msg[0]=msg[1];
msg[1]=msg[2];
msg[2]=msg[3];
msg[3]=msg[4];
msg[4]= client.read();


char c = msg[4]; // Lê 1 byte (caractere) do cliente
HTTP_req += c;  // Salva o pedido HTTP 1 caractere de cada vez


if (msg[4]=='#')
{
			   
   LOOKS AND EXECUTE SOCKET COMMANDS
   
} // Fim IF msg[4]
else
{
 while (client.connected())
 {
   if (client.available())
   {
	 if (c == '\n' && currentLineIsBlank)
	 {
		// Envia um cabeçalho de resposta padrão HTTP
		client.println("HTTP/1.1 200 OK");
		client.println("Content-Type: text/html");
		client.println("Connection: close");
		client.println();
		// Envia a página
		client.println("<!DOCTYPE html>");
		client.println("<html>");
		client.println("<head>");
		client.println("<title>Arduino - Luzes da Casa</title>");
		client.println("</head>");
		client.println("<body>");
		client.println("<center>");
		client.println("<h1>Luzes da Casa</h1>");
		client.println("<p>Clique para Acender ou Apagar a luz.</p>");
		client.println("<form method=\"get\">");
		ProcessButton(client);
		client.println("</form>");
		client.println("</center>");
		client.println("</body>");
		client.println("</html>");
		Serial.print(HTTP_req);
		HTTP_req = "";    // Termina o pedido, limpa a String
		break;
	 }
	 
	 if (c == '\n')
	 {
	   currentLineIsBlank = true;
	 } 
	 else if (c != '\r')
	 {
	   currentLineIsBlank = false;
	 }
   } // Fim (client.available())
 } // Fim while (client.connected())
 delay(1);      // Dar tempo ao navegador para receber os dados
 client.stop(); // Fecha a conexão
} // Fim ELSE
} // Fim client
} // Fim Loop

// Mudar LUZ e enviar de volta para a caixa HTML
void ProcessButton(EthernetClient cl)
{
if (HTTP_req.indexOf("luz=Quarto") > 0)
{
  if (digitalRead(4) == LOW)
  {
	  digitalWrite(4, HIGH);
  }
  else
  {
	  digitalWrite(4, LOW);
  }
}

if (HTTP_req.indexOf("luz=Sala") > 0)
{
  if (digitalRead(5) == LOW)
  {
	  digitalWrite(5, HIGH);
  }
  else
  {
	  digitalWrite(5, LOW);
  }
}

cl.println F("<input type=\"submit\" value=\"Quarto\" onclick=\"submit();\" name=\"luz\" style=\"height:300px; width:300px; font-size:50px\">");
cl.println F("<input type=\"submit\" value=\"Sala\" onclick=\"submit();\" name=\"luz\" style=\"height:300px; width:300px; font-size:50px\">");
}

When making a socket connection, the Arduino would not be stuck in “While” blocking of analyzing the messages to be sent? And if I delete the “While”, the Arduino would not be resubmitting the page every time it goes by Loop?

And in “client.stop ();”, when making a socket connection, it would also be closed?

If you mean Part 5 of this tutorial, you will notice [as I mentioned a few posts ago], his elements are wrong. He needs either a or " />" to close them, and make them correct [at least I think so]. If you do what he does with multiple controls, and not just one, then they interact and the control logic gets mucked up.

oric_dan:
If you mean Part 5 of this tutorial, you will notice [as I mentioned a few posts ago], his elements are wrong. He needs either a or " />" to close them, and make them correct [at least I think so]. If you do what he does with multiple controls, and not just one, then they interact and the control logic gets mucked up.

LED Control with Arduino Ethernet Shield Web Server

Now I put the " />".

But when making a socket connection, the Arduino would not be stuck in “While” blocking of analyzing the messages to be sent? And if I delete the “While”, the Arduino would not be resubmitting the page every time it goes by Loop?

And in “client.stop ();”, when making a socket connection, it would also be closed?

Tim will have to answer those questions. I'm just learning this stuff, like the " />", :-).

I changed the code, I wonder if will work the Webserver and Socket connection:

...

void loop() {
      
      EthernetClient client = server.available();
    
     // SE receber um caracter...
        
      delay(50); 
      if (client) {
        
        boolean currentLineIsBlank = true;
        while (client.connected())
         {
           if (client.available())
           {
              // guarda o caracter na string 'msg'
              msg[0]=msg[1];
              msg[1]=msg[2];
              msg[2]=msg[3];
              msg[3]=msg[4];
              msg[4]= client.read();
              
              
              char c = client.read(); // Lê 1 byte (caractere) do cliente
              HTTP_req += c;  // Salva o pedido HTTP 1 caractere de cada vez
              
      
             if (msg[4]=='#')
             {

                LOOKS AND EXECUTE SOCKET COMMANDS
        
             } // Fim IF msg[4]
             else
             {
               if (c == '\n' && currentLineIsBlank)
               {
                  // Envia um cabeçalho de resposta padrão HTTP
                  client.println("HTTP/1.1 200 OK");
                  client.println("Content-Type: text/html");
                  client.println("Connection: close");
                  client.println();
                  // Envia a página
                  client.println("<!DOCTYPE html>");
                  client.println("<html>");
                  client.println("<head>");
                  client.println("<title>Arduino - Luzes da Casa</title>");
                  client.println("</head>");
                  client.println("<body>");
                  client.println("<center>");
                  client.println("<h1>Luzes da Casa</h1>");
                  client.println("<p>Clique para Acender ou Apagar a luz.</p>");
                  client.println("<form method=\"get\">");
                  ProcessButton(client);
                  client.println("</form>");
                  client.println("</center>");
                  client.println("</body>");
                  client.println("</html>");
                  Serial.print(HTTP_req);
                  HTTP_req = "";    // Termina o pedido, limpa a String
                  break;
               }
               
               if (c == '\n')
               {
                 currentLineIsBlank = true;
               } 
               else if (c != '\r')
               {
                 currentLineIsBlank = false;
               }
             } // Fim ELSE
           } // Fim (client.available())
        } // Fim while (client.connected())
        
        delay(1);      // Dar tempo ao navegador para receber os dados
        client.stop(); // Fecha a conexão
     } // Fim client
   } // Fim Loop
   
  // Mudar LUZ e enviar de volta para a caixa HTML
  void ProcessButton(EthernetClient cl)
  {
      if (HTTP_req.indexOf("luz=Quarto") > 0)
      {
          if (digitalRead(4) == LOW)
          {
              digitalWrite(4, HIGH);
          }
          else
          {
              digitalWrite(4, LOW);
          }
      }
      
      if (HTTP_req.indexOf("luz=Sala") > 0)
      {
          if (digitalRead(5) == LOW)
          {
              digitalWrite(5, HIGH);
          }
          else
          {
              digitalWrite(5, LOW);
          }
      }
      
      cl.println F("<input type=\"submit\" value=\"Quarto\" onclick=\"submit();\" name=\"luz\" style=\"height:300px; width:300px; font-size:50px\" />");
      cl.println F("<input type=\"submit\" value=\"Sala\" onclick=\"submit();\" name=\"luz\" style=\"height:300px; width:300px; font-size:50px\" />");
  }

...

I changed the code, I wonder if will work the Webserver and Socket connection:

You changed it so it will fail.

Did you try this code?
http://playground.arduino.cc/Code/WebServerST

How many characters will this String store before you run out of SRAM?

              HTTP_req += c;  // Salva o pedido HTTP 1 caractere de cada vez

SurferTim:
How many characters will this String store before you run out of SRAM?

              HTTP_req += c;  // Salva o pedido HTTP 1 caractere de cada vez

This part of the code is equal to the Tutorial:

The string "HTTP_req" will not copy the answer from "c" to examine the response?

The string "HTTP_req" will not copy the answer from "c" to examine the response?

Yes, until the Arduino runs out of SRAM, at which time the SRAM will overflow (wrap around) and crash. Actually, you will probably have a stack collision before it wraps around.

My point was that is not really an excellent web server tutorial. There are some good example sections in that code, but if it doesn't work for you, it isn't excellent, is it?

SurferTim:

The string "HTTP_req" will not copy the answer from "c" to examine the response?

Yes, until the Arduino runs out of SRAM, at which time the SRAM will overflow (wrap around) and crash. Actually, you will probably have a stack collision before it wraps around.

My point was that is not really an excellent web server tutorial. There are some good example sections in that code, but if it doesn't work for you, it isn't excellent, is it?

What tutorial do you recommend?

Currently I use the Arduino with socket commands through of the smartphone and laptop, but I want also put a Webserver to control by browser of the Smart TV.

They are all socket commands in a way. I posted my server code earlier. And zoomkat posted his code also. You can also get some good examples from that tutorial once you get the client request without crashing your code.

Those are the basics. Then you must modify those examples, or pay someone like zoomkat or me to complete your code. Besides being a network routing specialist, that is part of my job. :slight_smile:

SurferTim:
They are all socket commands in a way. I posted my server code earlier. And zoomkat posted his code also. You can also get some good examples from that tutorial once you get the client request without crashing your code.

Those are the basics. Then you must modify those examples, or pay someone like zoomkat or me to complete your code. Besides being a network routing specialist, that is part of my job. :slight_smile:

I'm looking this example you showed:
http://playground.arduino.cc/Code/WebServerST

But I confess that I do not understanding what part I can change so that the page stay more or less this:

<!DOCTYPE html>
<html>
<head>
<title>Arduino - Luzes da Casa</title>
</head>
<body leftmargin="0" topmargin="0" marginwidth="0" marginheight="0" bgcolor="#CCCCCC">
<center>
<div style="background-color:#333333; color:#FFFFFF; font-size: 39px; font-weight: bold">Luzes da Casa</div>


<div style="font-size: 21px; font-weight: bold">Clique para Acender ou Apagar a luz.</div>


<form method="get">
<input type="submit" value="Quarto" onclick="submit();" name="luz" style="height:300px; width:300px; font-size:50px" />
<input type="submit" value="Sala" onclick="submit();" name="luz" style="height:300px; width:300px; font-size:50px" />
</form>
</center>
</body>
</html>

The buttons will turn on or off of the light of the room and the bedroom:

if (digitalRead(4) == LOW)
          {
              digitalWrite(4, HIGH);
          }
          else
          {
              digitalWrite(4, LOW);
          }
      
      if (digitalRead(5) == LOW)
          {
              digitalWrite(5, HIGH);
          }
          else
          {
              digitalWrite(5, LOW);
          }

You need to replace this with your web page.

          client.println(F("<head><script type=\"text/javascript\">"));
          client.println(F("function show_alert() {alert(\"This is an alert\");}"));
          client.println(F("</script></head>"));
          client.println(F("<body><H1>TEST</H1>"));
          client.println(F("<form method=GET onSubmit=\"show_alert()\">T: <input type=text name=t>
"));
          client.println(F("R: <input type=text name=r>
<input type=submit></form>"));
          client.println(F("</body></html>"));

Then search the request for your variables when it is submitted like mine does for "r" and "t".

oric_dan:
If you mean Part 5 of this tutorial, you will notice [as I mentioned a few posts ago], his elements are wrong. He needs either a or " />" to close them, and make them correct [at least I think so].

LED Control with Arduino Ethernet Shield Web Server

Actually, Dan, the code is perfectly valid HTML -- <input ...> is one of those tags that do not require a closing tag, usually called "self-closing tags" or sometimes "unpaired tags" or even "void elements" (<img ...> being another common one).

Have a google!

SurferTim:
Then search the request for your variables when it is submitted like mine does for "r" and "t".

My question is exactly this, because I do not understanding how can I do to become more or less this:

void ProcessButton(EthernetClient cl)
{
if (HTTP_req.indexOf("luz=Quarto") > 0)
{
if (digitalRead(4) == LOW)
{
digitalWrite(4, HIGH);
}
else
{
digitalWrite(4, LOW);
}
}

if (HTTP_req.indexOf("luz=Sala") > 0)
{
if (digitalRead(5) == LOW)
{
digitalWrite(5, HIGH);
}
else
{
digitalWrite(5, LOW);
}
}

cl.println F("<input type=\"submit\" value=\"Quarto\" onclick=\"submit();\" name=\"luz\" style=\"height:300px; width:300px; font-size:50px\">");
cl.println F("<input type=\"submit\" value=\"Sala\" onclick=\"submit();\" name=\"luz\" style=\"height:300px; width:300px; font-size:50px\">");
}

Is "HTTP_req" a String type? If so, I can't help you. zoomkat says that data type works ok, but I have not found that to be correct. Just my experience.