HOWTO: Useful ASP page that sends various formats of valid HTTP response
A common problem faced by ISAPI Filter writers that buffer/modify HTTP response is to ensure that this code works for all of the valid formats of HTTP responses that can be sent by the web server.
Question:
*) Can you suggest any tools / techniques that will enable me to test all code paths. At the moment i am at the mercy of the servers in that they determine what the response format should be, i need to thoroughly test my chunked code, content-length code and non-content length.
Answer:
Sure. The following ASP page will generate all of the valid HTTP response formats to allow you to test your handling of chunked, content-length, and non-content-length (i.e. connection close) responses.
The ASP page takes in three parameters via querystring to generate the variety of valid HTTP response formats. Syntax:
- chunksize - the bytes of response data per response chunk
- numchunks - the number of response chunks to send
- type - the format of the response. Either "chunk" for chunk-encoded, "cl" for content-lengith, or "neither" for neither header, just send data and close connection
Sample requests and outputs:
Sends 5 chunks of 10 bytes each, keep-alive possible
WWWConnect::Connect("localhost","80")\n source port: 3725\n REQUEST: **************\n GET /output.asp?chunksize=10&numchunks=5&type=chunk HTTP/1.1\r\n Host: localhost\r\n Accept: */*\r\n \r\n RESPONSE: **************\n HTTP/1.1 200 OK\r\n Server: Microsoft-IIS/5.0\r\n Date: Mon, 15 Aug 2005 11:39:18 GMT\r\n Content-Type: text/html\r\n Set-Cookie: ASPSESSIONIDASTATTTA=PIMPPEJBIMEGJLHOBNPHMIDC; path=/\r\n Cache-control: private\r\n Transfer-Encoding: chunked\r\n \r\n a\r\n XXXXXXXXXX\r\n a\r\n XXXXXXXXXX\r\n a\r\n XXXXXXXXXX\r\n a\r\n XXXXXXXXXX\r\n a\r\n XXXXXXXXXX\r\n 0\r\n \r\n finished.
Sends 50 bytes with content-length, keep-alive possible
REQUEST: **************\n GET /output.asp?chunksize=10&numchunks=5&type=cl HTTP/1.1\r\n Host: localhost\r\n Accept: */*\r\n \r\n RESPONSE: **************\n HTTP/1.1 200 OK\r\n Server: Microsoft-IIS/5.0\r\n Date: Mon, 15 Aug 2005 11:39:59 GMT\r\n Content-Length: 50\r\n Content-Type: text/html\r\n Set-Cookie: ASPSESSIONIDASTATTTA=AJMPPEJBCGEMEKINJEKEKAJO; path=/\r\n Cache-control: private\r\n \r\n XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX finished.
Sends 50 bytes without content-length and closes connection afterwards
REQUEST: **************\n GET /output.asp?chunksize=10&numchunks=5&type=neither HTTP/1.1\r\n Host: localhost\r\n Accept: */*\r\n \r\n RESPONSE: **************\n HTTP/1.1 200 OK\r\n Server: Microsoft-IIS/5.0\r\n Date: Mon, 15 Aug 2005 11:40:25 GMT\r\n Connection: close\r\n Content-Type: text/html\r\n Set-Cookie: ASPSESSIONIDASTATTTA=BJMPPEJBMAANLOOIBJEOJJBA; path=/\r\n Cache-control: private\r\n \r\n XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX WWWConnect::Close("localhost","80")\n closed source port: 3725\r\n finished.
Enjoy.
//David
<%
DIM i, outputType, szChunk, dwRepeat
outputType = UCASE( Request.QueryString( "type" ) )
szChunk = STRING( CINT( Request.QueryString( "chunksize" ) ), "X" )
dwRepeat = CINT( Request.QueryString( "numchunks" ) )
IF outputType = "CHUNK" THEN
Response.Buffer = false
ELSEIF outputType = "CL" THEN
Response.Buffer = true
ELSE
Response.Buffer = true
Response.Flush
END IF
FOR i = 1 TO dwRepeat
Response.Write szChunk
NEXT
%>