namespace Nwc.XmlRpc
{
using System;
using System.IO;
using System.Net.Sockets;
using System.Collections;
///Very basic HTTP request handler.
///This class is designed to accept a TcpClient and treat it as an HTTP request.
/// It will do some basic header parsing and manage the input and output streams associated
/// with the request.
public class SimpleHttpRequest
{
private String _httpMethod = null;
private String _protocol;
private String _filePathFile = null;
private String _filePathDir = null;
private String __filePath;
private TcpClient _client;
private StreamReader _input;
private StreamWriter _output;
private Hashtable _headers;
/// A constructor which accepts the TcpClient.
/// It creates the associated input and output streams, determines the request type,
/// and parses the remaining HTTP header.
/// The TcpClient associated with the HTTP connection.
public SimpleHttpRequest(TcpClient client)
{
_client = client;
_output = new StreamWriter(client.GetStream());
_input = new StreamReader(client.GetStream());
GetRequestMethod();
GetRequestHeaders();
}
/// The output StreamWriter associated with the request.
public StreamWriter Output
{
get { return _output; }
}
/// The input StreamReader associated with the request.
public StreamReader Input
{
get { return _input; }
}
/// The TcpClient with the request.
public TcpClient Client
{
get { return _client; }
}
private String _filePath
{
get { return __filePath; }
set
{
__filePath = value;
_filePathDir = null;
_filePathFile = null;
}
}
/// The type of HTTP request (i.e. PUT, GET, etc.).
public String HttpMethod
{
get { return _httpMethod; }
}
/// The level of the HTTP protocol.
public String Protocol
{
get { return _protocol; }
}
/// The "path" which is part of any HTTP request.
public String FilePath
{
get { return _filePath; }
}
/// The file portion of the "path" which is part of any HTTP request.
public String FilePathFile
{
get
{
if (_filePathFile != null)
return _filePathFile;
int i = FilePath.LastIndexOf("/");
if (i == -1)
return "";
i++;
_filePathFile = FilePath.Substring(i, FilePath.Length - i);
return _filePathFile;
}
}
/// The directory portion of the "path" which is part of any HTTP request.
public String FilePathDir
{
get
{
if (_filePathDir != null)
return _filePathDir;
int i = FilePath.LastIndexOf("/");
if (i == -1)
return "";
i++;
_filePathDir = FilePath.Substring(0, i);
return _filePathDir;
}
}
private void GetRequestMethod()
{
string req = _input.ReadLine();
if (req == null)
throw new ApplicationException("Void request.");
if (0 == String.Compare("GET ", req.Substring(0, 4), true))
_httpMethod = "GET";
else if (0 == String.Compare("POST ", req.Substring(0, 5), true))
_httpMethod = "POST";
else
throw new InvalidOperationException("Unrecognized method in query: " + req);
req = req.TrimEnd();
int idx = req.IndexOf(' ') + 1;
if (idx >= req.Length)
throw new ApplicationException("What do you want?");
string page_protocol = req.Substring(idx);
int idx2 = page_protocol.IndexOf(' ');
if (idx2 == -1)
idx2 = page_protocol.Length;
_filePath = page_protocol.Substring(0, idx2).Trim();
_protocol = page_protocol.Substring(idx2).Trim();
}
private void GetRequestHeaders()
{
String line;
int idx;
_headers = new Hashtable();
while ((line = _input.ReadLine()) != "")
{
if (line == null)
{
break;
}
idx = line.IndexOf(':');
if (idx == -1 || idx == line.Length - 1)
{
Logger.WriteEntry("Malformed header line: " + line, LogLevel.Information);
continue;
}
String key = line.Substring(0, idx);
String value = line.Substring(idx + 1);
try
{
_headers.Add(key, value);
}
catch (Exception)
{
Logger.WriteEntry("Duplicate header key in line: " + line, LogLevel.Information);
}
}
}
///
/// Format the object contents into a useful string representation.
///
///String representation of the SimpleHttpRequest as the HttpMethod FilePath Protocol.
override public String ToString()
{
return HttpMethod + " " + FilePath + " " + Protocol;
}
///
/// Close the SimpleHttpRequest. This flushes and closes all associated io streams.
///
public void Close()
{
_output.Flush();
_output.Close();
_input.Close();
_client.Close();
}
}
}