ovidiucp / TinyWebServer

Small web server for Arduino, fits in 10KB ROM, less than 512 bytes RAM
http://www.webweavertech.com/ovidiu/weblog/archives/000484.html
GNU Lesser General Public License v2.1
245 stars 65 forks source link

Handling "100-Continue" in POST Request #19

Open FulvioSpelta opened 11 years ago

FulvioSpelta commented 11 years ago

Using POST request from httpclient Apache (my test client is openremote controller) I've found that their http 1.1 implementation ask for a "100-Continue" return code before sending the body request. See the example (I've "hard modified the code to send the "100-Continue" server answer in order to complete the request):

Client 1st request:


POST /wm3/json/d/6 HTTP/1.1User-Agent: OpenRemoteController
Content-Length: 1
Content-Type: text/plain; charset=UTF-8
Host: 192.168.10.90:9090
Connection: Keep-Alive
Expect: 100-Continue

Server answer:

HTTP/1.1 100 Continue

Client 2nd request (request body):
1
Server answer:
HTTP/1.1 200 OK
Content-Type: application/json

Could you insert this handling into the library as standard POST request handling? thanks More details in hex form of all packet:

00000000  50 4F 53 54 20 2F 77 6D  33 2F 6A 73 6F 6E 2F 64   POST /wm 3/json/d 
00000010  2F 36 20 48 54 54 50 2F  31 2E 31 0D 0A 55 73 65   /6 HTTP/ 1.1..Use 
00000020  72 2D 41 67 65 6E 74 3A  20 4F 70 65 6E 52 65 6D   r-Agent:  OpenRem 
00000030  6F 74 65 43 6F 6E 74 72  6F 6C 6C 65 72 0D 0A 43   oteContr oller..C 
00000040  6F 6E 74 65 6E 74 2D 4C  65 6E 67 74 68 3A 20 31   ontent-L ength: 1 
00000050  0D 0A 43 6F 6E 74 65 6E  74 2D 54 79 70 65 3A 20   ..Conten t-Type:  
00000060  74 65 78 74 2F 70 6C 61  69 6E 3B 20 63 68 61 72   text/pla in; char 
00000070  73 65 74 3D 55 54 46 2D  38 0D 0A 48 6F 73 74 3A   set=UTF- 8..Host: 
00000080  20 31 39 32 2E 31 36 38  2E 31 30 2E 39 30 3A 39    192.168 .10.90:9 
00000090  30 39 30 0D 0A 43 6F 6E  6E 65 63 74 69 6F 6E 3A   090..Con nection: 
000000A0  20 4B 65 65 70 2D 41 6C  69 76 65 0D 0A 45 78 70    Keep-Al ive..Exp 
000000B0  65 63 74 3A 20 31 30 30  2D 43 6F 6E 74 69 6E 75   ect: 100 -Continu 
000000C0  65 0D 0A 0D 0A                                     e....

00000000  48 54 54 50 2F 31 2E 31  20 31 30 30 20 43 6F 6E   HTTP/1.1  100 Con 
00000010  74 69 6E 75 65 0A 0A                               tinue..

00000000  31                                                 1

00000000  48 54 54 50 2F 31 2E 31  20 32 30 30 20 4F 4B 0D   HTTP/1.1  200 OK. 
00000010  0A 43 6F 6E 74 65 6E 74  2D 54 79 70 65 3A 20 61   .Content -Type: a 
00000020  70 70 6C 69 63 61 74 69  6F 6E 2F 6A 73 6F 6E 0D   pplicati on/json. 
00000030  0A 0D 0A                                           ...
FulvioSpelta commented 11 years ago

My solution in sketch:

I've defined an "Expect" header:

const char\* headers[] = {
  "Content-Length",
  "Expect",
  NULL
};
then in POST handling function I've added the code:
  const char\* expectHeader = web_server.get_header_value("Expect");
  // Handle the optional presence of Expect: 100-Continue  
  if ((strcmp(expectHeader , "100-Continue") == 0) {
    web_server.write( "HTTP/1.1 100 Continue\n\n" );
    startTime = millis();
    // wait for response till timeout
    while( millis()-startTime <= CONTINUE_TIMEOUT && !client.available()) {};
  };
Comments welcome :-)
ovidiucp commented 11 years ago

The problem with this code is that you're blocking the web server for the duration of CONTINUE_TIMEOUT, which means no other requests can be served during that time.

A better approach is to add a timer class that's initialized with a timeout value. Upon the execution of the run loop you check the values of all timers, and take the appropriate action when a timeout occurs.

socketpair commented 8 years ago

There is a bug in application, that generates traffic you dumped. It should terminate HTTP/1.1 100 continue with \r\n\r\n instead of \n\n