230 lines
5.8 KiB
C#
230 lines
5.8 KiB
C#
using System;
|
|
using System.IO;
|
|
using System.Text;
|
|
using System.Collections.Generic;
|
|
using System.Linq;
|
|
using System.Net;
|
|
using System.Net.Sockets;
|
|
using appsrv.exceptions;
|
|
using appsrv.http;
|
|
|
|
namespace appsrv.server
|
|
{
|
|
public class HttpRequest
|
|
{
|
|
private Stream stream;
|
|
private StreamReader streamReader;
|
|
private List<HttpRequest> currentRequests = new List<HttpRequest>();
|
|
|
|
private MemoryStream responseStream;
|
|
private StreamWriter responseWriter;
|
|
|
|
Dictionary<String, String> requestHeaders = new Dictionary<string, string>();
|
|
Dictionary<String, String> responseHeaders = new Dictionary<string, string>();
|
|
|
|
public EndPoint Client { get; private set; }
|
|
|
|
public ApplicationServer ApplicationServer { get; private set; }
|
|
public Uri URI { get; private set; }
|
|
|
|
public String Method { get; private set; }
|
|
public String RequestURL { get; private set; }
|
|
public String Protocol { get; private set; }
|
|
|
|
public String Hostname { get; private set; }
|
|
public int Port { get; private set; }
|
|
|
|
public QueryStringParameters Query { get; private set; }
|
|
|
|
|
|
public int StatusCode { get; set; } = 200;
|
|
|
|
public HttpRequest(ApplicationServer applicationServer, TcpClient client)
|
|
{
|
|
this.ApplicationServer = applicationServer;
|
|
|
|
this.Client = client.Client.RemoteEndPoint;
|
|
this.stream = client.GetStream();
|
|
this.streamReader = new StreamReader(this.stream);
|
|
|
|
String rLine = this.streamReader.ReadLine();
|
|
String[] rTokens = SplitWhitespace(
|
|
rLine
|
|
);
|
|
Console.WriteLine("Tokens: {0}", rTokens);
|
|
|
|
if (rTokens.Length != 3){
|
|
throw new IllegalRequestException(rLine);
|
|
}
|
|
|
|
this.Method = rTokens[0];
|
|
this.RequestURL = rTokens[1];
|
|
this.Protocol = rTokens[2];
|
|
|
|
}
|
|
|
|
public override string ToString()
|
|
{
|
|
return string.Format("[HttpRequest: Client={0}, ApplicationServer={1}, Hostname={6} Port={7} URI={2}, Method={3}, RequestURL={4}, Protocol={5} Query={8}]", Client, ApplicationServer, URI, Method, RequestURL, Protocol, Hostname, Port,Query);
|
|
}
|
|
|
|
public String GetRequestHeader(String name, String def = "")
|
|
{
|
|
name = name.ToLowerInvariant();
|
|
|
|
if (requestHeaders.ContainsKey(name))
|
|
return requestHeaders[name];
|
|
|
|
return def;
|
|
}
|
|
|
|
public String GetResponseHeader(String name, String def = "")
|
|
{
|
|
name = name.ToLowerInvariant();
|
|
|
|
if (responseHeaders.ContainsKey(name))
|
|
return responseHeaders[name];
|
|
|
|
return def;
|
|
}
|
|
public void SetResponseHeader(String name,String value){
|
|
name = name.ToLowerInvariant();
|
|
if (value == null)
|
|
{
|
|
this.responseHeaders.Remove(name);
|
|
}
|
|
else
|
|
{
|
|
this.responseHeaders[name] = value;
|
|
}
|
|
}
|
|
|
|
public Stream ResponseStream
|
|
{
|
|
get {
|
|
if (responseStream == null)
|
|
responseStream = new MemoryStream();
|
|
|
|
return responseStream;
|
|
}
|
|
}
|
|
|
|
public TextWriter ResponseWriter
|
|
{
|
|
get
|
|
{
|
|
if (this.responseWriter == null)
|
|
{
|
|
this.responseWriter = new StreamWriter(this.responseStream);
|
|
}
|
|
return this.responseWriter;
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
private String[] SplitWhitespace(String line){
|
|
LinkedList<String> tokens = new LinkedList<string>();
|
|
StringBuilder sb = new StringBuilder();
|
|
|
|
for (int n = 0; n < line.Length;)
|
|
{
|
|
for (; n < line.Length && !Char.IsWhiteSpace(line[n]); n++)
|
|
sb.Append(line[n]);
|
|
|
|
tokens.AddLast(sb.ToString());
|
|
sb.Clear();
|
|
|
|
for (; n < line.Length && Char.IsWhiteSpace(line[n]); n++) {}
|
|
}
|
|
return tokens.ToArray();
|
|
}
|
|
|
|
private void ReadHttpHeaders(){
|
|
String headerLine = this.streamReader.ReadLine();
|
|
String hName = null;
|
|
|
|
while (!headerLine.Equals(String.Empty)){
|
|
if (Char.IsWhiteSpace(headerLine[0]) && hName != null)
|
|
{
|
|
requestHeaders[hName] = requestHeaders[hName] + "," + headerLine.Trim();
|
|
} else {
|
|
String[] split = headerLine.Split(new char[] { ':' }, 2);
|
|
if (split.Length != 2){
|
|
throw new IllegalRequestException("malformed header");
|
|
}
|
|
|
|
hName = split[0].ToLowerInvariant();
|
|
requestHeaders[hName] = split[1];
|
|
}
|
|
|
|
headerLine = this.streamReader.ReadLine();
|
|
}
|
|
|
|
foreach (String hname in requestHeaders.Keys.ToArray()){
|
|
requestHeaders[hname] = requestHeaders[hname].Trim();
|
|
}
|
|
|
|
}
|
|
|
|
private void InterpretRequestHeaders()
|
|
{
|
|
String host = GetRequestHeader("host");
|
|
String[] hostTokens = host.Split(':');
|
|
Hostname = hostTokens[0];
|
|
if (hostTokens.Length > 1){
|
|
Port = int.Parse(hostTokens[1]);
|
|
}
|
|
|
|
URI = new Uri(String.Format("http://{0}:{1}/{2}", Hostname, Port, RequestURL));
|
|
|
|
Query = new QueryStringParameters(URI.Query);
|
|
|
|
}
|
|
|
|
private void SendResponse()
|
|
{
|
|
using (StreamWriter writer = new StreamWriter(this.stream))
|
|
{
|
|
ResponseStream.Position = 0;
|
|
SetResponseHeader("Content-Length", responseStream.Length.ToString());
|
|
|
|
writer.WriteLine("{0} {1} {2}", Protocol, StatusCode, HttpStatusCodes.GetStatusMessage(StatusCode));
|
|
foreach (String rhName in responseHeaders.Keys){
|
|
writer.WriteLine("{0}: {1}", rhName, responseHeaders[rhName]);
|
|
}
|
|
writer.WriteLine();
|
|
writer.Flush();
|
|
|
|
responseStream.CopyTo(this.stream);
|
|
}
|
|
}
|
|
|
|
public void Handle(){
|
|
this.ReadHttpHeaders();
|
|
this.InterpretRequestHeaders();
|
|
|
|
Console.WriteLine("Request Handled: {0}",this);
|
|
|
|
foreach (String key in this.requestHeaders.Keys){
|
|
Console.WriteLine("HH: {0} = {1}",key,this.requestHeaders[key]);
|
|
}
|
|
|
|
ApplicationServer.HandleRequest(this);
|
|
|
|
SendResponse();
|
|
|
|
this.streamReader.Close();
|
|
this.stream.Close();
|
|
}
|
|
}
|
|
}
|