public HttpServerSocketDelegate(IHttpServerTransaction transaction, IHttpServerTransactionDelegate transactionDelegate) { this.transaction = transaction; this.transactionDelegate = transactionDelegate; transactionTransform = new ParserToTransactionTransform(transaction, transactionDelegate); parser = new HttpParser(new ParserDelegate(transactionTransform)); }
public void OnBody(HttpParser parser, ArraySegment<byte> data) { if (_headersComplete && data != null && data.Count > 0 && _onRequestBodyReceivedHandler != null) { _request.ReceivedLength += data.Count; _onRequestBodyReceivedHandler(data); } }
public void OnHeaderValue(HttpParser parser, string value) { string existingValue = _request.Headers[_headerName]; if (string.IsNullOrWhiteSpace(existingValue)) _request.Headers[_headerName] = value; else _request.Headers[_headerName] = existingValue + "," + value; }
public void OnBody(HttpParser parser, ArraySegment<byte> data) { Debug.WriteLine("OnBody"); // XXX can we defer this check to the parser? if (data.Count > 0) { del.OnRequestBody(data); } }
public HttpRequestParser(Action<HttpRequest> onRequestBeginHandler, Action<ArraySegment<byte>> onRequestBodyReceivedHandler, Action onRequestEndHandler, Action<string> onFragmentReceivedHandler, Action<Exception> onParserException, bool secure) { _parser = new HttpParser(this); _secure = secure; _onRequestBeginHandler = onRequestBeginHandler; _onRequestBodyReceivedHandler = onRequestBodyReceivedHandler; _onRequestEndHandler = onRequestEndHandler; _onParserException = onParserException; }
public void OnQueryString(HttpParser parser, string queryString) { var kv = HttpUtility.ParseQueryString(queryString); foreach(var k in kv.AllKeys) { Console.WriteLine("{0}:{1}", k, kv[k]); data[k] = kv[k]; } }
public void OnHeaderName(HttpParser parser, string name) { if (headers == null) headers = new Dictionary<string, string>(StringComparer.InvariantCultureIgnoreCase); if (!string.IsNullOrEmpty(headerValue)) CommitHeader(); headerName = name; }
public async Task OnMessageBegin(HttpParser parser) { //Console.WriteLine("OnMessageBegin"); // TODO: this used to work, but i removed the StringBuffers. so work around maybe // defer creation of buffers until message is created so // NullRef will be thrown if OnMessageBegin is not called. headers = new Dictionary<string, string>(StringComparer.InvariantCultureIgnoreCase); body = new List<ArraySegment<byte>>(); }
public async Task<MiddlemanRequest> ParseAsync(InboundConnection conn, Stream stream) { var del = new ParseDelegate(); var parser = new HttpParser(del); int read; var readTotal = 0; var buffer = new byte[8192]; Log.Debug("{0}: RequestParser starting", conn.RemoteEndPoint); var requestString = ""; while (stream != null && (read = await stream.ReadAsync(buffer, 0, buffer.Length).ConfigureAwait(false)) > 0) { requestString += Encoding.ASCII.GetString(buffer.Where(x => x != 0).ToArray(), 0, read); readTotal += read; if (parser.Execute(new ArraySegment<byte>(buffer, 0, read)) != read) throw new FormatException("Parse error in request"); if (del.HeaderComplete) break; } conn.MustClose = del.Request.Headers.AllKeys.Any(h => h.Equals("Connection", StringComparison.InvariantCultureIgnoreCase) && del.Request.Headers[h].Equals("Close", StringComparison.InvariantCultureIgnoreCase)); Log.Debug("{0}: RequestParser read enough ({1} bytes)", conn.RemoteEndPoint, readTotal); Log.Info("ORIGINAL REQUEST: " + Environment.NewLine + requestString + Environment.NewLine); if (readTotal == 0) return null; if (!del.HeaderComplete) throw new FormatException("Parse error in request"); var request = del.Request; request.ProtocolVersion = new Version(parser.MajorVersion, parser.MinorVersion); conn.RequestVersion = request.ProtocolVersion; var cl = request.ContentLength; if (cl > 0 && stream != null) { request.RequestBody = del.RequestBodyStart.Count > 0 ? new MaxReadStream(new StartAvailableStream(del.RequestBodyStart, stream), cl) : new MaxReadStream(stream, cl); } return request; }
public void OnHeadersEnd(HttpParser parser) { string upgradeType; _headersComplete = true; _request.Version = new Version(parser.MajorVersion, parser.MinorVersion); _request.KeepAlive = parser.ShouldKeepAlive; _request.Upgrade = _request.Headers.TryGetValue("upgrade", out upgradeType); _request.UpgradeType = upgradeType; _request.Secure = _secure; if (_onRequestBeginHandler != null) _onRequestBeginHandler(_request); }
public async Task<SwitchboardRequest> ParseAsync(InboundConnection conn, Stream stream) { var del = new ParseDelegate(); var parser = new HttpParser(del); int read; int readTotal = 0; byte[] buffer = new byte[8192]; Debug.WriteLine(string.Format("{0}: RequestParser starting", conn.RemoteEndPoint)); while ((read = await stream.ReadAsync(buffer, 0, buffer.Length).ConfigureAwait(false)) > 0) { readTotal += read; if (parser.Execute(new ArraySegment<byte>(buffer, 0, read)) != read) throw new FormatException("Parse error in request"); if (del.headerComplete) break; } Debug.WriteLine(string.Format("{0}: RequestParser read enough ({1} bytes)", conn.RemoteEndPoint, readTotal)); if (readTotal == 0) return null; if (!del.headerComplete) throw new FormatException("Parse error in request"); var request = del.request; request.ProtocolVersion = new Version(parser.MajorVersion, parser.MinorVersion); int cl = request.ContentLength; if (cl > 0) { if (del.requestBodyStart.Count > 0) { request.RequestBody = new MaxReadStream(new StartAvailableStream(del.requestBodyStart, stream), cl); } else { request.RequestBody = new MaxReadStream(stream, cl); } } return request; }
public void RequestsWithDigits() { foreach (var request in TestRequest.Requests.Where(r => r.Name.StartsWith("digits in "))) { var handler = new Handler(); var parser = new HttpParser(handler); Console.WriteLine("----- Testing request: '" + request.Name + "' -----"); var parsed = parser.Execute(new ArraySegment<byte>(request.Raw)); if (parsed != request.Raw.Length) Assert.Fail("Error while parsing."); AssertRequest(new TestRequest[] { request }, handler.Requests.ToArray(), parser); } }
public void OnHeadersEnd(HttpParser parser) { Debug.WriteLine("OnHeadersEnd"); if (!string.IsNullOrEmpty(headerValue)) CommitHeader(); var request = new HttpRequestHeaders() { // TODO path, query, fragment? Method = method, Uri = requestUri, Headers = headers, Version = new Version(parser.MajorVersion, parser.MinorVersion) }; del.OnRequestBegan(request, parser.ShouldKeepAlive); }
static void AssertRequest(TestRequest[] expected, TestRequest[] actual, HttpParser machine) { for (int i = 0; i < expected.Length; i++) { Assert.IsTrue(i <= actual.Length - 1, "Expected more requests than received"); var expectedRequest = expected[i]; var actualRequest = actual[i]; //Console.WriteLine("Asserting request " + expectedRequest.Name); Assert.AreEqual(expectedRequest.Method, actualRequest.Method, "Unexpected method."); Assert.AreEqual(expectedRequest.RequestUri, actualRequest.RequestUri, "Unexpected request URI."); Assert.AreEqual(expectedRequest.VersionMajor, actualRequest.VersionMajor, "Unexpected major version."); Assert.AreEqual(expectedRequest.VersionMinor, actualRequest.VersionMinor, "Unexpected minor version."); Assert.AreEqual(expectedRequest.RequestPath, actualRequest.RequestPath, "Unexpected request path."); Assert.AreEqual(expectedRequest.QueryString, actualRequest.QueryString, "Unexpected query string."); Assert.AreEqual(expectedRequest.Fragment, actualRequest.Fragment, "Unexpected fragment."); //Assert.AreEqual(expected.RequestPath, test.RequestPath, "Unexpected path."); Assert.IsTrue(actualRequest.OnHeadersEndCalled, "OnHeadersEnd was not called."); Assert.AreEqual(expectedRequest.ShouldKeepAlive, actualRequest.ShouldKeepAlive, "Wrong value for ShouldKeepAlive"); foreach (var pair in expectedRequest.Headers) { Assert.IsTrue(actualRequest.Headers.ContainsKey(pair.Key), "Actual headers did not contain key '" + pair.Key + "'"); Assert.AreEqual(pair.Value, actualRequest.Headers[pair.Key], "Actual headers had wrong value for key '" + pair.Key + "'"); } foreach (var pair in actualRequest.Headers) { Assert.IsTrue(expectedRequest.Headers.ContainsKey(pair.Key), "Unexpected header named '" + pair.Key + "'"); } if (expectedRequest.Body != null) { var expectedBody = Encoding.UTF8.GetString(expectedRequest.Body); Assert.IsNotNull(actualRequest.Body, "Expected non-null request body"); var actualBody = Encoding.UTF8.GetString(actualRequest.Body); Assert.AreEqual(expectedBody, actualBody, "Body differs"); } else Assert.IsNull(actualRequest.Body); } }
public async Task OnMessageEnd(HttpParser parser) { //Console.WriteLine("OnMessageEnd"); Assert.AreEqual(shouldKeepAlive, parser.ShouldKeepAlive, "Differing values for parser.ShouldKeepAlive between OnHeadersEnd and OnMessageEnd"); TestRequest request = new TestRequest(); request.VersionMajor = versionMajor; request.VersionMinor = versionMinor; request.ShouldKeepAlive = shouldKeepAlive; request.Method = method; request.RequestUri = requestUri; request.RequestPath = path; request.QueryString = queryString; request.Fragment = fragment; request.Headers = headers; request.OnHeadersEndCalled = onHeadersEndCalled; // aggregate body chunks into one big chunk var length = body.Aggregate(0, (s, b) => s + b.Count); if (length > 0) { request.Body = new byte[length]; int where = 0; foreach (var buf in body) { Buffer.BlockCopy(buf.Array, buf.Offset, request.Body, where, buf.Count); where += buf.Count; } } // add it to the list of requests recieved. Requests.Add(request); // reset our internal state versionMajor = versionMinor = -1; method = requestUri = queryString = fragment = headerName = headerValue = null; headers = null; body = null; shouldKeepAlive = false; onHeadersEndCalled = false; }
public void SingleChunk() { // read each request as a single block and parse foreach (var request in TestRequest.Requests) { var handler = new Handler(); var parser = new HttpParser(handler); Console.WriteLine("----- Testing request: '" + request.Name + "' -----"); var parsed = parser.Execute(new ArraySegment<byte>(request.Raw)); if (parsed != request.Raw.Length) Assert.Fail("Error while parsing."); parser.Execute(default(ArraySegment<byte>)); AssertRequest(new TestRequest[] { request }, handler.Requests.ToArray(), parser); } }
public void OnMethod(HttpParser parser, string str) { //Console.WriteLine("OnMethod: '" + str + "'"); method = str; }
public void OnResponseCode(HttpMachine.HttpParser parser, int statusCode, string statusReason) { HttpResponse.StatusCode = statusCode; HttpResponse.ResponseReason = statusReason; }
public void OnHeaderValue(HttpParser parser, string str) { //Console.WriteLine("OnHeaderValue: '" + str + "'"); if (string.IsNullOrEmpty(headerName)) throw new Exception("Got header value without name."); headerValue = str; }
public void OnHeaderName(HttpParser parser, string str) { //Console.WriteLine("OnHeaderName: '" + str + "'"); if (!string.IsNullOrEmpty(headerValue)) CommitHeader(); headerName = str; }
public void OnHeadersEnd(HttpParser parser) { //Console.WriteLine("OnHeadersEnd"); onHeadersEndCalled = true; if (!string.IsNullOrEmpty(headerValue)) CommitHeader(); versionMajor = parser.MajorVersion; versionMinor = parser.MinorVersion; shouldKeepAlive = parser.ShouldKeepAlive; }
public void OnBody(HttpParser parser, ArraySegment<byte> data) { //var str = Encoding.ASCII.GetString(data.Array, data.Offset, data.Count); //Console.WriteLine("OnBody: '" + str + "'"); body.Add(data); }
public void OnFragment(HttpParser parser, string str) { //Console.WriteLine("OnFragment: '" + str + "'"); fragment = str; }
public void OnBody(HttpMachine.HttpParser parser, ArraySegment <byte> data) { HttpResponse.Body.Write(data.Array, 0, data.Array.Length); }
public void OnMessageEnd(HttpMachine.HttpParser parser) { HttpResponse.IsEndOfRequest = true; }
public void OnRequestUri(HttpParser parser, string str) { //Console.WriteLine("OnRequestUri: '" + str + "'"); requestUri = str; }
public void OnPath(HttpParser parser, string str) { //Console.WriteLine("OnPath: '" + str + "'"); path = str; }
public void OnMethod(HttpParser parser, string method) { this.request.method = method; }
public void OnQueryString(HttpParser parser, string str) { //Console.WriteLine("OnQueryString: '" + str + "'"); queryString = str; }
public void OnRequestUri(HttpParser parser, string requestUri) { this.request.uri = requestUri; }
public void OnResponseCode(HttpParser parser, int code, string reason) { statusCode = code; statusReason = reason; }
static void ThreeChunkScan(IEnumerable<TestRequest> requests) { // read each sequence of requests as three blocks, with the breaks in every possible combination. // one buffer to rule them all var raw = new byte[requests.Aggregate(0, (s, b) => s + b.Raw.Length)]; int where = 0; foreach (var r in requests) { Buffer.BlockCopy(r.Raw, 0, raw, where, r.Raw.Length); where += r.Raw.Length; } int totalOperations = (raw.Length - 1) * (raw.Length - 2) / 2; int operationsCompleted = 0; byte[] buffer1 = new byte[80 * 1024]; byte[] buffer2 = new byte[80 * 1024]; byte[] buffer3 = new byte[80 * 1024]; int buffer1Length = 0, buffer2Length = 0, buffer3Length = 0; Console.WriteLine("----- Testing requests: " + requests.Aggregate("", (s, r) => s + "; " + r.Name).TrimStart(';', ' ') + " (" + totalOperations + " ops) -----"); int lastI = 0; int lastJ = 0; try { for (int j = 2; j < raw.Length; j++) for (int i = 1; i < j; i++) { lastI = i; lastJ = j; //Console.WriteLine(); if (operationsCompleted % 1000 == 0) Console.WriteLine(" " + (100.0 * ((float)operationsCompleted / (float)totalOperations))); operationsCompleted++; //Console.WriteLine(operationsCompleted + " / " + totalOperations); var handler = new Handler(); var parser = new HttpParser(handler); buffer1Length = i; Buffer.BlockCopy(raw, 0, buffer1, 0, buffer1Length); buffer2Length = j - i; Buffer.BlockCopy(raw, i, buffer2, 0, buffer2Length); buffer3Length = raw.Length - j; Buffer.BlockCopy(raw, j, buffer3, 0, buffer3Length); //Console.WriteLine("Parsing buffer 1."); Assert.AreEqual(buffer1Length, parser.Execute(new ArraySegment<byte>(buffer1, 0, buffer1Length)), "Error parsing buffer 1."); //Console.WriteLine("Parsing buffer 2."); Assert.AreEqual(buffer2Length, parser.Execute(new ArraySegment<byte>(buffer2, 0, buffer2Length)), "Error parsing buffer 2."); //Console.WriteLine("Parsing buffer 3."); Assert.AreEqual(buffer3Length, parser.Execute(new ArraySegment<byte>(buffer3, 0, buffer3Length)), "Error parsing buffer 3."); //Console.WriteLine("Parsing EOF"); Assert.AreEqual(parser.Execute(default(ArraySegment<byte>)), 0, "Error parsing EOF chunk."); AssertRequest(requests.ToArray(), handler.Requests.ToArray(), parser); } } catch { Console.WriteLine("Problem while parsing chunks:"); Console.WriteLine("---"); Console.WriteLine(Encoding.UTF8.GetString(buffer1, 0, buffer1Length)); Console.WriteLine("---"); Console.WriteLine(Encoding.UTF8.GetString(buffer2, 0, buffer2Length)); Console.WriteLine("---"); Console.WriteLine(Encoding.UTF8.GetString(buffer3, 0, buffer3Length)); Console.WriteLine("---"); Console.WriteLine("Failed on i = " + lastI + " j = " + lastJ); throw; } }
public void OnQueryString(HttpParser parser, string queryString) { this.request.query = queryString; }
public void OnMessageBegin(HttpMachine.HttpParser parser) { }