Webclient: Unable to construct request-string ..

I took the Webclient (repeating) example. I want to make dynamic requests to my web server.
But I fail to construct the right "String"(?).. See my code below. Actuall the function shall be called with two integer variables and it shall do a request to the server.

In my code are already 3 test cases, from which only one works (1).

  • With case 1, I "hardcode" the string and send it to the server
  • With case 2, I use a String variable holding exactly(?) the same data => fails
  • With case 3, Here I just split the (working) string (see case1) on two lines => also fails

Hardcoding the request (case 1) works like a charm. Any other method I tried fails and I do not know why??? :~

The reply that I get from the web server is:

HTTP/1.0 400 Bad Request
Content-Type: text/html
Connection: close

<title>Bad Request</title>Only HTTP 1.x supported

And here is my code (of course I enable only one of the cases at a time!!:

void xs1Request(int actor, int funct) {
  // if there's a successful connection:
  if (client.connect(server, 80)) {
    Serial.println("connecting...");
    // send the HTTP PUT request:
    
    //--- This is what I actually want to do, but it failed (like with cmd3)
    String cmd0 = "GET /control?callback=cname&cmd=set_state_actuator&number=";
    String cmd1 = cmd0 + 1 +"&function="+2+" HTTP/1.1";
    
    // Sendind cmd1 failed, so I simplified to this for testing (case 3)  
    String cmd3 = "GET /control?callback=cname&cmd=set_state_actuator&number=1&function=2 HTTP/1.1";
    
     
    // case 1 works:           
     client.println("GET /control?callback=cname&cmd=set_state_actuator&number=1&function=2 HTTP/1.1");
  
    // case 2 does not work (see reply above):
    // client.println(cmd3);
    
    // case 3 does not work too (damn, is the same as case 1, or is it not???):
    // client.print("GET /control?callback=cname&cmd=set_state_actuator&number=");
    // client.println("1&function=2 HTTP/1.1");
      
    client.println("Host: www.arduino.cc");
    client.println("User-Agent: arduino-ethernet");
    client.println("Connection: close");
    client.println();
    
    // note the time that the connection was made:
    lastConnectionTime = millis();
  } 
  else {
    // if you couldn't make a connection:
    Serial.println("connection failed");
    Serial.println("disconnecting.");
    client.stop();
  }
}

I stay away from the String data type. It has proven to be unreliable, and a bit slow. Here is the code I use for this:
http://playground.arduino.cc/Code/WebClient
Insure the pageAdd[] array is large enough to hold your request.

 client.println("Host: www.arduino.cc");

What? arduino.cc is not hosting your web server.

When I use that sample code, I get an error on line:

Serial.println(F("Starting ethernet..."));

'PSTR' was not declared in this scope.

I have to say I use th Arduino IDE 1.5.2, because I have a Arduino Due (the UNO was to small for my purpose).

.. oh no.. arduino.cc is not hosting my server.. I just forgot to change this from the original sketch.. sorry

Ok.. the F statement does not work in my scenario because of the DUE not having any flash.. no problem, removed F and got it compiled.

Nevertheless the error persists!!!

Here is what works, when put into a browser tab and hit enter:

http://10.0.0.242/control?callback=cname&cmd=set_state_actuator&number=1&function=2

The code example from your link does (again) not work.. I changed the corresponding lines to this:

 sprintf(pageAdd,"GET /control?callback=cname&cmd=set_state_actuator&number=1&function=2");

The error code is the same:

connecting...connected
HTTP/1.0 400 Bad Request
Content-Type: text/html
Connection: close

<title>Bad Request</title>Unsupported HTTP method.
disconnecting.

Why is that? I can not spot the problem/difference... as said in my first post, I wonder why this works with static strings and not with dynamic variables.

Does anyone have a clue?

Does anyone have a clue?

No, but it's interesting that the code says HTTP/1.1 and the error message says HTTP/1.0.

Have you tried printing out the data being sent to the client, to the serial port, to assure that the correct S/string is being created?

@PaulS: Good eye there!

That is a localnet ip, so it is accessible only from your localnet. What OS and server software are you using?

I am talking to a little box called XS1 (it is a RF transceiver, and the http request I have taken form the manual and verified in normal browser).

Here is what works:

client.println("GET /control?callback=cname&cmd=set_state_actuator&number=1&function=2 HTTP/1.1");
client.println("Host: www.arduino.cc");
client.println("User-Agent: arduino-ethernet");
client.println("Connection: close");
client.println();

Serial.println("GET /control?callback=cname&cmd=set_state_actuator&number=1&function=2 HTTP/1.1");
Serial.println("Host: www.arduino.cc");
Serial.println("User-Agent: arduino-ethernet");
Serial.println("Connection: close");
Serial.println();

and this is what the Serial says:

GET /control?callback=cname&cmd=set_state_actuator&number=1&function=2 HTTP/1.1
Host: www.arduino.cc
User-Agent: arduino-ethernet
Connection: close

and this is what the reply from the little box (XS1) says in the Serial. (I expect it to return a JSON package, so this is fine):

HTTP/1.1 200 OK
Server: EZcontrol
Content-Type: text/javascript; charset=UTF-8
Cache-Control: no-cache, must-revalidate
Pragma: no-cache
Connection: close
Date: We, 28 Aug 2013 14:48:56 GMT

cname({
	"version": 16,
	"type": "set_state_actuator",
	"actuator": {
		"number": 1,
		"name": "Kuechenzeile",
		"type": "switch",
		"value": 100.0,
		"newvalue": 100.0,
		"unit": "%",
		"utime": 1377701336,
		"date": {
			"weekday": "we",
			"day": 28,
			"month": 8,
			"year": 2013
		},
		"time": {
			"hour": 16,
			"min": 48,
			"sec": 56
		}
	}
})

This is ALMOST the same, but does not work:
This is the code:

String cmd3 = "GET /control?callback=cname&cmd=set_state_actuator&number=1&function=2 HTTP/1.1";
client.println(cmd3);
client.println("Host: www.arduino.cc");
client.println("User-Agent: arduino-ethernet");
client.println("Connection: close");
client.println();
  
Serial.println("GET /control?callback=cname&cmd=set_state_actuator&number=1&function=2 HTTP/1.1");
Serial.println("Host: www.arduino.cc");
Serial.println("User-Agent: arduino-ethernet");
Serial.println("Connection: close");
Serial.println();

This is on the Serial:

GET /control?callback=cname&cmd=set_state_actuator&number=1&function=2 HTTP/1.1
Host: www.arduino.cc
User-Agent: arduino-ethernet
Connection: close

An this is the reply from the little box.

HTTP/1.0 400 Bad Request
Content-Type: text/html
Connection: close

<title>Bad Request</title>Unsupported HTTP method.

as you can see: In the Serial log, it is exactly the same what is send to the little box.. but there must be a difference here.


Here is in addition the adopted example you suggested:

  // Modify next line to load different page
  // or pass values to server
  //sprintf(pageAdd,"/",totalCount);   
  // sprintf(pageAdd,"/arduino.php?test=%u",totalCount);
    
  sprintf(pageAdd,"GET /control?callback=cname&cmd=set_state_actuator&number=1&function=2");

  if(!getPage(server,serverPort,pageAdd)) Serial.print(("Fail "));
  else Serial.print(("Pass "));
  totalCount++;
  Serial.println(totalCount,DEC);

The result on the Serial:

HTTP/1.0 400 Bad Request
Content-Type: text/html
Connection: close

<title>Bad Request</title>Unsupported HTTP method.

So pretty much the same..
It works only with a static string, but not if I somehow construct the URL.. I do not get it..

Thanks for helping (anyway).. :~

Why do you still have the Host: command being sent?

I do not know what to put in place for the HOST: information. I use the setup only on a local intranet.. I am looking for solving the first problem, before changing anything else (and get more problems.) -- I just right know searching the internet what to put in this place.. or if I can leave it empty..

I just changed it to the IP of the little box that I am talking to. (=server)

Nevertheless I am still out of luck with my inital problem. :frowning:

Any idea, someone?

I do not know what to put in place for the HOST: information. I use the setup only on a local intranet.. I am looking for solving the first problem, before changing anything else (and get more problems.) -- I just right know searching the internet what to put in this place.. or if I can leave it empty..

You only need a Host: line if the domain is hosted by a company that hosts multiple domains. Since that does not appear to be your case, leave the Host: line out altogether.

Client test code you can try. If it connects to my server, then you can try your server IP address and your request string.

//zoomkat 4-04-12
//simple client test
//for use with IDE 1.0
//open serial monitor and send an e to test
//for use with W5100 based ethernet shields

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

byte mac[] = { 0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED }; //physical mac address
byte myserver[] = { 208, 104, 2, 86 }; // zoomkat web page server IP address
EthernetClient client;
//////////////////////

void setup(){

  Ethernet.begin(mac);
  Serial.begin(9600); 
  Serial.println("Better client test 4/04/12"); // so I can keep track of what is loaded
  Serial.println("Send an e in serial monitor to test"); // what to do to test
}

void loop(){
  // check for serial input
  if (Serial.available() > 0) //if something in serial buffer
  {
    byte inChar; // sets inChar as a byte
    inChar = Serial.read(); //gets byte from buffer
    if(inChar == 'e') // checks to see byte is an e
    {
      sendGET(); // call sendGET function below when byte is an e
    }
  }  
} 

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

void sendGET() //client function to send/receive GET request data.
{
  if (client.connect(myserver, 80)) {  //starts client connection, checks for connection
    Serial.println("connected");
    client.println("GET /~shb/arduino.txt HTTP/1.0"); //download text
    client.println(); //end of get request
  } 
  else {
    Serial.println("connection failed"); //error message if no client connect
    Serial.println();
  }

  while(client.connected() && !client.available()) delay(1); //waits for data
  while (client.connected() || client.available()) { //connected or data available
    char c = client.read(); //gets byte from ethernet buffer
    Serial.print(c); //prints byte to serial monitor 
  }

  Serial.println();
  Serial.println("disconnecting.");
  Serial.println("==================");
  Serial.println();
  client.stop(); //stop client

}