Created
January 13, 2011 23:46
-
-
Save bvanderveen/778856 to your computer and use it in GitHub Desktop.
Janky example of how to use JacksonH's C# port of a Java port of Ryan Dahl's http-parser
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
using System; | |
using System.Collections.Generic; | |
using System.Linq; | |
using System.Text; | |
namespace ParserDriver | |
{ | |
public class Parser | |
{ | |
public string Method; | |
public string Path; | |
public string QueryString; | |
public string Fragment; | |
public Dictionary<string, string> Headers; | |
Action<ArraySegment<byte>> onData; | |
public Parser(ISocket socket, Action<ArraySegment<byte>> onData) | |
{ | |
// will be called whenever the parser encounters HTTP request data. | |
this.onData = onData; | |
var parser = new HttpParser(ParserType.HTTP_REQUEST); | |
Headers = new Dictionary<string, string>(); | |
// terrible! why not provide an interface IParserEventHandler? | |
var settings = new ParserSettings(); | |
settings.OnMessageBegin = OnMessageBegin; | |
settings.OnPath = OnPath; | |
settings.OnQueryString = OnQueryString; | |
settings.OnFragment = OnFragment; | |
settings.OnHeaderField = OnHeaderField; | |
settings.OnHeaderValue = OnHeaderValue; | |
settings.OnHeadersComplete = OnHeadersComplete; | |
settings.OnBody = OnBody; | |
settings.OnMessageComplete = OnMessageComplete; | |
settings.OnError = OnError; | |
// this gets called whenever data is available on the socket--we feed the data to the parser | |
socket.OnData = d => parser.Execute(settings, new ByteBuffer(d.Array, d.Offset, d.Count)); | |
} | |
public int OnMessageBegin(HttpParser parser) | |
{ | |
// possibly push a data structure which collects the data we parse into a queue for handling by the app, | |
// save a reference to it, etc. | |
return 0; | |
} | |
StringBuilder path = new StringBuilder(); | |
public int OnPath(HttpParser parser, ByteBuffer data, int pos, int len) | |
{ | |
path.Append(Encoding.ASCII.GetString(data.Bytes, pos, len)); | |
return 0; | |
} | |
StringBuilder queryString = new StringBuilder(); | |
public int OnQueryString(HttpParser parser, ByteBuffer data, int pos, int len) | |
{ | |
queryString.Append(Encoding.ASCII.GetString(data.Bytes, pos, len)); | |
return 0; | |
} | |
StringBuilder fragment = new StringBuilder(); | |
public int OnFragment(HttpParser parser, ByteBuffer data, int pos, int len) | |
{ | |
fragment.Append(Encoding.ASCII.GetString(data.Bytes, pos, len)); | |
return 0; | |
} | |
StringBuilder headerField = new StringBuilder(); | |
public int OnHeaderField(HttpParser parser, ByteBuffer data, int pos, int len) | |
{ | |
if (headerValue.Length != 0) | |
CommitHeader(); | |
headerField.Append(Encoding.ASCII.GetString(data.Bytes, pos, len)); | |
return 0; | |
} | |
StringBuilder headerValue = new StringBuilder(); | |
public int OnHeaderValue(HttpParser parser, ByteBuffer data, int pos, int len) | |
{ | |
if (headerField.Length == 0) | |
throw new HttpException("Got header value without field name."); | |
headerValue.Append(Encoding.ASCII.GetString(data.Bytes, pos, len)); | |
return 0; | |
} | |
public int OnHeadersComplete(HttpParser parser) | |
{ | |
if (headerField.Length > 0) | |
CommitHeader(); | |
Method = parser.HttpMethod.ToString().Replace("HTTP_", ""); | |
Path = path.ToString(); | |
QueryString = queryString.ToString(); | |
Fragment = fragment.ToString(); | |
return 0; | |
} | |
void CommitHeader() | |
{ | |
var name = headerField.ToString(); | |
var value = headerValue.ToString(); | |
if (Headers.ContainsKey(name)) | |
Headers[name] += ", " + value; | |
else | |
Headers[name] = value; | |
headerField.Length = 0; headerValue.Length = 0; | |
} | |
public int OnBody(HttpParser parser, ByteBuffer data, int pos, int len) | |
{ | |
onData(new ArraySegment<byte>(data.Bytes, pos, len)); | |
return 0; | |
} | |
public int OnMessageComplete(HttpParser parser) | |
{ | |
// parser will automatically restart if more data is recieved on the socket | |
return 0; | |
} | |
public void OnError(HttpParser parser, string message, ByteBuffer buffer, int initial_position) | |
{ | |
// who cares? | |
// TODO: handle error D: | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment