view webserver.rhope @ 149:804e48af1027

Fix file not found handling
author Mike Pavone <pavone@retrodev.com>
date Mon, 22 Nov 2010 20:38:03 +0000
parents f582fd6c75ee
children 47ab97730865
line wrap: on
line source


Import net.rhope

_Dict Split[dict,entry,index,keydelim:out]
{
	parts <- [entry]Split[keydelim]
	out <- [dict]Set[[parts]Index[0],[parts]Index[1]]
}

Dict Split[string,keydelim,entrydelim:out]
{
	out <- Fold[_Dict Split[?, ?, ?, keydelim], Dictionary[], [string]Split[entrydelim]] 
}

_Key Value Join[dict,key,key sep,val sep,string:out]
{
	new string <- [[[string]Append[String[key]]]Append[key sep]]Append[ String[[dict]Index[key]] ]
	[dict]Next[key]
	{
		out <- _Key Value Join[dict, ~, key sep, val sep, [new string]Append[val sep]]
	}{
		out <- Val[new string]
	}
}

Key Value Join[dict,key sep,val sep:out]
{
	[dict]First
	{
		out <- _Key Value Join[dict, ~, key sep, val sep, ""]
	}{
		out <- ""
	}
}

Get Content Type[path:out]
{
	parts <- [path]Split["."]
	ext <- [parts]Index[ [[parts]Length] - [1] ]
	If[ [ext] = ["html"] ]
	{
		out <- "text/html; charset=ISO-8859-1"
	}{ 
		If[ [ext] = ["jpg"] ]
		{
			out <- "image/jpeg"
		}{ 
			If[ [ext] = ["gif"] ]
			{
				out <- "image/gif"
			}{
				If[ [ext] = ["css"] ]
				{
					out <- "text/css"
				}{
					out <- "application/octet-stream"
				}
			}
		}
	}
}

HTTP OK[client,type,content length,headers:out]
{
	out <- HTTP Response[client, type, content length, headers, "200 OK"]
}

HTTP Response[client,type,content length,headers,code:out]
{
	start headers <- [Dictionary[]]Set["Content-Type", type]
	If[[content length] < [0]]
	{
		default headers <- [start headers]Set["Transfer-Encoding", "Chunked"]
	}{
		default headers <- [start headers]Set["Content-Length", content length]
	}
	
	out <- [
				[
					[
						[
							["HTTP/1.1 "]Append[code]
						]Append["\r\n"]
					]Append[
						[
							Combine[headers, default headers]
						]Key Value Join[": ", "\r\n"]
					]
				]Append["\r\n\r\n"]
			]Write to File[client]
}

HTTP Not Found[client]
{
	string <- "<html><head><title>Document Not Found</title></head><body>The document you requested is not available on this server.</body></html>"
	HTTP Response[client, Get Content Type[".html"], [string]Length, Dictionary[], "404 Not Found"]
	{
		[[string]Write to File[~]]Close
	}
}

Good Path?[path:yep,nope]
{
	nope <- If[[path]Starts With["."]] {}
	{ nope <- If[[path]Starts With["/"]] {}
	{ nope <- If[[path]Contains[".."]] {}
	{ nope,yep <- If[[path]Contains["//"]] }}}
}

Handle Request[client,type,query,headers,handler]
{
	parts <- [query]Split["?"]
	path <- [parts]Index[0]
	[[path]Split["/"]]Index[1]
	{
		handlerpath <- ["/"]Append[~]
	}{
		handlerpath <- "/"
	}
	host <- [headers]Index["Host"] {}
	{
		host <- ""
	}
	
	the handler <- [handler]Index[[host]Append[handlerpath]] {}
	{
		the handler <- [handler]Index[handlerpath] {}
		{
			,newpath <- [path]Slice[1]
			Good Path?[newpath]
			{
				file,bad file <- Open[File[newpath],"r"]
				content length <- Length[file]
				,bad file <- If[[content length] > [0]]
				{
					data <- [file]Read[content length]
					[[HTTP OK[client, Get Content Type[path], content length, Dictionary[]]
					]Write[data]
					]Close
					{ Close[file] }
				}
				Val[bad file]
				{
					HTTP Not Found[client]
				}
			}{
				HTTP Not Found[client]
			}
		}
	}

	Val[the handler]
	{
		If[[[parts]Length] > [1]]
		{
			queryvars <- Dict Split[[parts]Index[1], "=", "&"]
		}{
			queryvars <- Dictionary[]
		}
		[~]Call[client,path,type,queryvars,headers]
	}
	
}

Connection Start[con,address,handlers]
{
	,client <- [con]Read Delim[["\r\n"]Buffer >>]
	{ request <- String[~] }
	parts <- [request]Split[" "]
	Print[[[request]Append[" "]]Append[address]]
	[client]Read Delim[["\r\n\r\n"]Buffer >>]
	{
		headers <- Map[Dict Split[String[~], ":", "\r\n"], Trim[?, " \t"]]
	}{
		Handle Request[~, [parts]Index[0], [parts]Index[1], headers, handlers]
	}
}