Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Browse files

initial commit.

  • Loading branch information...
commit b7676e3a32301223affe2f998318db43984eca0a 0 parents
Benjamin van der Veen authored
5 .gitignore
@@ -0,0 +1,5 @@
+*.csproj.user
+*.suo
+bin
+obj
+packages
19 LICENSE
@@ -0,0 +1,19 @@
+HttpMachine - Copyright (c) 2011 Benjamin van der Veen
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+THE SOFTWARE.
1  README
@@ -0,0 +1 @@
+An HTTP Parser for C#. Generated by [Ragel](http://www.complang.org/ragel/).
336 SharpHttp.Tests/HttpMachineTests.cs
@@ -0,0 +1,336 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using HttpSharp;
+using NUnit.Framework;
+
+namespace SharpHttp.Tests
+{
+ class TestRequest
+ {
+ public string Name;
+ public byte[] Raw;
+ public string Method;
+ public string RequestUri;
+ public string RequestPath;
+ public string QueryString;
+ public string Fragment;
+ public int VersionMajor;
+ public int VersionMinor;
+ public Dictionary<string, string> Headers;
+ public byte[] Body;
+
+ public static TestRequest[] Requests = new TestRequest[] {
+ // TODO
+ // leading \r\n, ? in query, requests from common clients
+
+ new TestRequest() {
+ Name = "No headers, no body",
+ Raw = Encoding.ASCII.GetBytes("GET /foo HTTP/1.1\r\n\r\n"),
+ Method = "GET",
+ RequestUri = "/foo",
+ RequestPath = "/foo",
+ QueryString = "",
+ Fragment = "",
+ VersionMajor = 1,
+ VersionMinor = 1,
+ Headers = new Dictionary<string,string>() {
+ },
+ Body = null
+ },
+ new TestRequest() {
+ Name = "no body",
+ Raw = Encoding.ASCII.GetBytes("GET /foo HTTP/1.1\r\nFoo: Bar\r\n\r\n"),
+ Method = "GET",
+ RequestUri = "/foo",
+ RequestPath = "/foo",
+ QueryString = "",
+ Fragment = "",
+ VersionMajor = 1,
+ VersionMinor = 1,
+ Headers = new Dictionary<string,string>() {
+ { "Foo", "Bar" }
+ },
+ Body = null
+ },
+ new TestRequest() {
+ Name = "query string",
+ Raw = Encoding.ASCII.GetBytes("GET /foo?asdf=jklol HTTP/1.1\r\nFoo: Bar\r\nBaz-arse: Quux\r\n\r\n"),
+ Method = "GET",
+ RequestUri = "/foo?asdf=jklol",
+ RequestPath = "/foo",
+ QueryString = "asdf=jklol",
+ Fragment = "",
+ VersionMajor = 1,
+ VersionMinor = 1,
+ Headers = new Dictionary<string,string>() {
+ { "Foo", "Bar" },
+ { "Baz-arse", "Quux" }
+ },
+ Body = null
+ },
+ new TestRequest() {
+ Name = "fragment",
+ Raw = Encoding.ASCII.GetBytes("POST /foo?asdf=jklol#poopz HTTP/1.1\r\nFoo: Bar\r\nBaz: Quux\r\n\r\n"),
+ Method = "POST",
+ RequestUri = "/foo?asdf=jklol#poopz",
+ RequestPath = "/foo",
+ QueryString = "asdf=jklol",
+ Fragment = "poopz",
+ VersionMajor = 1,
+ VersionMinor = 1,
+ Headers = new Dictionary<string,string>() {
+ { "Foo", "Bar" },
+ { "Baz", "Quux" }
+ },
+ Body = null
+ }
+ };
+ }
+
+
+ public class Handler : IHttpRequestParser
+ {
+ StringBuilder method, requestUri, queryString, fragment, headerName, headerValue, versionMajor, versionMinor;
+ Dictionary<string, string> headers;
+
+ public string Method
+ {
+ get { return method.ToString(); }
+ }
+
+ public string RequestUri
+ {
+ get { return requestUri.ToString(); }
+ }
+
+ public int VersionMajor
+ {
+ get { return int.Parse(versionMajor.ToString()); }
+ }
+
+ public int VersionMinor
+ {
+ get { return int.Parse(versionMinor.ToString()); }
+ }
+
+ public string QueryString
+ {
+ get { return queryString.ToString(); }
+ }
+ public string Fragment
+ {
+ get { return fragment.ToString(); }
+ }
+
+ public Dictionary<string, string> Headers
+ {
+ get { return headers; }
+ }
+
+ public Handler()
+ {
+ method = new StringBuilder();
+ requestUri = new StringBuilder();
+ queryString = new StringBuilder();
+ fragment = new StringBuilder();
+ headerName = new StringBuilder();
+ headerValue = new StringBuilder();
+ versionMajor = new StringBuilder(1);
+ versionMinor = new StringBuilder(1);
+ headers = new Dictionary<string, string>();
+ }
+
+ public void OnMethod(ArraySegment<byte> data)
+ {
+ var str = Encoding.ASCII.GetString(data.Array, data.Offset, data.Count);
+ ///Console.WriteLine("OnMethod: '" + str + "'");
+ method.Append(str);
+ }
+
+ public void OnRequestUri(ArraySegment<byte> data)
+ {
+ var str = Encoding.ASCII.GetString(data.Array, data.Offset, data.Count);
+ //Console.WriteLine("OnRequestUri: '" + str + "'");
+ requestUri.Append(str);
+ }
+
+ public void OnQueryString(ArraySegment<byte> data)
+ {
+ var str = Encoding.ASCII.GetString(data.Array, data.Offset, data.Count);
+ //Console.WriteLine("OnQueryString: '" + str + "'");
+ queryString.Append(str);
+ }
+
+ public void OnFragment(ArraySegment<byte> data)
+ {
+ var str = Encoding.ASCII.GetString(data.Array, data.Offset, data.Count);
+ //Console.WriteLine("OnFragment: '" + str + "'");
+ fragment.Append(str);
+ }
+
+ public void OnHeaderName(ArraySegment<byte> data)
+ {
+ var str = Encoding.ASCII.GetString(data.Array, data.Offset, data.Count);
+ //Console.WriteLine("OnHeaderName: '" + str + "'");
+
+ if (headerValue.Length != 0)
+ CommitHeader();
+
+ headerName.Append(str);
+ }
+
+ public void OnHeaderValue(ArraySegment<byte> data)
+ {
+ var str = Encoding.ASCII.GetString(data.Array, data.Offset, data.Count);
+ //Console.WriteLine("OnHeaderValue: '" + str + "'");
+
+ if (headerName.Length == 0)
+ throw new Exception("Got header value without name.");
+
+ headerValue.Append(str);
+ }
+
+ public void OnVersionMajor(ArraySegment<byte> data)
+ {
+ var str = Encoding.ASCII.GetString(data.Array, data.Offset, data.Count);
+ //Console.WriteLine("OnVersionMajor: '" + str + "'");
+ versionMajor.Append(str);
+ }
+
+ public void OnVersionMinor(ArraySegment<byte> data)
+ {
+ var str = Encoding.ASCII.GetString(data.Array, data.Offset, data.Count);
+ //Console.WriteLine("OnVersionMinor: '" + str + "'");
+ versionMinor.Append(str);
+ }
+
+ public void OnHeadersComplete()
+ {
+ //Console.WriteLine("OnHeadersComplete");
+ if (headerValue.Length != 0)
+ CommitHeader();
+ }
+
+ void CommitHeader()
+ {
+ //Console.WriteLine("Committing header '" + headerName.ToString() + "' : '" + headerValue.ToString() + "'");
+ headers[headerName.ToString()] = headerValue.ToString();
+ headerName.Length = headerValue.Length = 0;
+ }
+ }
+
+ public class HttpMachineTests
+ {
+
+ void AssertRequest(TestRequest expected, Handler test)
+ {
+ Assert.AreEqual(expected.Method, test.Method, "Unexpected method.");
+ Assert.AreEqual(expected.RequestUri, test.RequestUri, "Unexpected request URI.");
+ Assert.AreEqual(expected.VersionMajor, test.VersionMajor, "Unexpected major version.");
+ Assert.AreEqual(expected.VersionMinor, test.VersionMinor, "Unexpected minor version.");
+ Assert.AreEqual(expected.QueryString, test.QueryString, "Unexpected query string.");
+ Assert.AreEqual(expected.Fragment, test.Fragment, "Unexpected fragment.");
+ //Assert.AreEqual(expected.RequestPath, test.RequestPath, "Unexpected path.");
+
+ foreach (var pair in expected.Headers)
+ {
+ Assert.IsTrue(test.Headers.ContainsKey(pair.Key), "Tested headers did not contain key '" + pair.Key + "'");
+ Assert.AreEqual(pair.Value, test.Headers[pair.Key], "Tested headers had wrong value for key '" + pair.Key + "'");
+ }
+
+ foreach (var pair in test.Headers)
+ {
+ Assert.IsTrue(expected.Headers.ContainsKey(pair.Key), "Unexpected header named '" + pair.Key + "'");
+ }
+ }
+
+
+ [Test]
+ public void SingleChunk()
+ {
+ // read each request as a single block and parse
+ // read each request as three blocks, with the breaks in every possible combination
+
+ foreach (var request in TestRequest.Requests)
+ {
+ var handler = new Handler();
+ var parser = new HttpMachine(handler);
+ Console.WriteLine("----- Testing request: '" + request.Name + "' -----");
+
+ parser.Execute(new ArraySegment<byte>(request.Raw));
+ AssertRequest(request, handler);
+ }
+ }
+
+ [Test]
+ public void ThreeChunkScan()
+ {
+ foreach (var request in TestRequest.Requests)
+ {
+ var raw = request.Raw;
+ 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];
+
+ Console.WriteLine("total ops: " + totalOperations);
+ for (int j = 2; j < raw.Length; j++)
+ for (int i = 1; i < j; i++)
+ {
+ if (operationsCompleted % 100 == 0)
+ Console.WriteLine(" " + (100.0 * ((float)operationsCompleted / (float)totalOperations)));
+
+ operationsCompleted++;
+ //Console.WriteLine("----- Testing request: '" + request.Name + "' (" + operationsCompleted + ") -----");
+
+
+
+
+ var handler = new Handler();
+ var parser = new HttpMachine(handler);
+
+ //Console.WriteLine("--- Parsing Chunk 1 --- ");
+ var buffer1Length = i;
+ Buffer.BlockCopy(raw, 0, buffer1, 0, buffer1Length);
+ //Console.WriteLine(Encoding.ASCII.GetString(buffer1, 0, buffer1Length));
+ //Console.WriteLine("---");
+
+ parser.Execute(new ArraySegment<byte>(buffer1, 0, buffer1Length));
+
+ //Console.WriteLine("--- Parsing Chunk 2 --- ");
+ var buffer2Length = j - i;
+ //Console.WriteLine("j - i = " + (j - i));
+ Buffer.BlockCopy(raw, i, buffer2, 0, buffer2Length);
+ //Console.WriteLine(Encoding.ASCII.GetString(buffer2, 0, buffer2Length));
+ //Console.WriteLine("---");
+
+ parser.Execute(new ArraySegment<byte>(buffer2, 0, buffer2Length));
+
+ //Console.WriteLine("--- Parsing Chunk 3 --- ");
+ var buffer3Length = raw.Length - j;
+ Buffer.BlockCopy(raw, j, buffer3, 0, buffer3Length);
+ //Console.WriteLine(Encoding.ASCII.GetString(buffer3, 0, buffer3Length));
+ //Console.WriteLine("---");
+
+ parser.Execute(new ArraySegment<byte>(buffer3, 0, buffer3Length));
+
+ AssertRequest(request, handler);
+
+ }
+ }
+ }
+
+ // TODO
+ // extract content-length/parse body
+ // keepalive
+ // decode chunked encoding
+ // error conditions/fuzz
+ [Test]
+ public void Upgrade()
+ {
+ }
+ }
+}
36 SharpHttp.Tests/Properties/AssemblyInfo.cs
@@ -0,0 +1,36 @@
+using System.Reflection;
+using System.Runtime.CompilerServices;
+using System.Runtime.InteropServices;
+
+// General Information about an assembly is controlled through the following
+// set of attributes. Change these attribute values to modify the information
+// associated with an assembly.
+[assembly: AssemblyTitle("SharpHttp.Tests")]
+[assembly: AssemblyDescription("")]
+[assembly: AssemblyConfiguration("")]
+[assembly: AssemblyCompany("Microsoft")]
+[assembly: AssemblyProduct("SharpHttp.Tests")]
+[assembly: AssemblyCopyright("Copyright © Microsoft 2011")]
+[assembly: AssemblyTrademark("")]
+[assembly: AssemblyCulture("")]
+
+// Setting ComVisible to false makes the types in this assembly not visible
+// to COM components. If you need to access a type in this assembly from
+// COM, set the ComVisible attribute to true on that type.
+[assembly: ComVisible(false)]
+
+// The following GUID is for the ID of the typelib if this project is exposed to COM
+[assembly: Guid("fd79c085-96b6-4f1f-b70c-f83cb5cd9224")]
+
+// Version information for an assembly consists of the following four values:
+//
+// Major Version
+// Minor Version
+// Build Number
+// Revision
+//
+// You can specify all the values or you can default the Build and Revision Numbers
+// by using the '*' as shown below:
+// [assembly: AssemblyVersion("1.0.*")]
+[assembly: AssemblyVersion("1.0.0.0")]
+[assembly: AssemblyFileVersion("1.0.0.0")]
69 SharpHttp.Tests/SharpHttp.Tests.csproj
@@ -0,0 +1,69 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="4.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <PropertyGroup>
+ <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
+ <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
+ <ProductVersion>8.0.30703</ProductVersion>
+ <SchemaVersion>2.0</SchemaVersion>
+ <ProjectGuid>{75BEA10B-761A-474F-9522-57E8974B52D6}</ProjectGuid>
+ <OutputType>Library</OutputType>
+ <AppDesignerFolder>Properties</AppDesignerFolder>
+ <RootNamespace>SharpHttp.Tests</RootNamespace>
+ <AssemblyName>SharpHttp.Tests</AssemblyName>
+ <TargetFrameworkVersion>v4.0</TargetFrameworkVersion>
+ <FileAlignment>512</FileAlignment>
+ </PropertyGroup>
+ <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
+ <DebugSymbols>true</DebugSymbols>
+ <DebugType>full</DebugType>
+ <Optimize>false</Optimize>
+ <OutputPath>bin\Debug\</OutputPath>
+ <DefineConstants>DEBUG;TRACE</DefineConstants>
+ <ErrorReport>prompt</ErrorReport>
+ <WarningLevel>4</WarningLevel>
+ </PropertyGroup>
+ <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
+ <DebugType>pdbonly</DebugType>
+ <Optimize>true</Optimize>
+ <OutputPath>bin\Release\</OutputPath>
+ <DefineConstants>TRACE</DefineConstants>
+ <ErrorReport>prompt</ErrorReport>
+ <WarningLevel>4</WarningLevel>
+ </PropertyGroup>
+ <ItemGroup>
+ <Reference Include="nunit.framework, Version=2.5.7.10213, Culture=neutral, PublicKeyToken=96d09a1eb7f44a77, processorArchitecture=MSIL">
+ <SpecificVersion>False</SpecificVersion>
+ <HintPath>..\packages\NUnit.2.5.7.10213\lib\nunit.framework.dll</HintPath>
+ </Reference>
+ <Reference Include="nunit.mocks, Version=2.5.7.10213, Culture=neutral, PublicKeyToken=96d09a1eb7f44a77, processorArchitecture=MSIL">
+ <SpecificVersion>False</SpecificVersion>
+ <HintPath>..\packages\NUnit.2.5.7.10213\lib\nunit.mocks.dll</HintPath>
+ </Reference>
+ <Reference Include="pnunit.framework">
+ <HintPath>..\packages\NUnit.2.5.7.10213\lib\pnunit.framework.dll</HintPath>
+ </Reference>
+ <Reference Include="System" />
+ <Reference Include="System.Core" />
+ </ItemGroup>
+ <ItemGroup>
+ <Compile Include="HttpMachineTests.cs" />
+ <Compile Include="Properties\AssemblyInfo.cs" />
+ </ItemGroup>
+ <ItemGroup>
+ <None Include="packages.config" />
+ </ItemGroup>
+ <ItemGroup>
+ <ProjectReference Include="..\SharpHttp\SharpHttp.csproj">
+ <Project>{76FB25C5-15B1-4541-8D19-D78790257C95}</Project>
+ <Name>SharpHttp</Name>
+ </ProjectReference>
+ </ItemGroup>
+ <Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
+ <!-- To modify your build process, add your task inside one of the targets below and uncomment it.
+ Other similar extension points exist, see Microsoft.Common.targets.
+ <Target Name="BeforeBuild">
+ </Target>
+ <Target Name="AfterBuild">
+ </Target>
+ -->
+</Project>
4 SharpHttp.Tests/packages.config
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<packages>
+ <package id="NUnit" version="2.5.7.10213" />
+</packages>
26 SharpHttp.sln
@@ -0,0 +1,26 @@
+
+Microsoft Visual Studio Solution File, Format Version 11.00
+# Visual Studio 2010
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SharpHttp", "SharpHttp\SharpHttp.csproj", "{76FB25C5-15B1-4541-8D19-D78790257C95}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SharpHttp.Tests", "SharpHttp.Tests\SharpHttp.Tests.csproj", "{75BEA10B-761A-474F-9522-57E8974B52D6}"
+EndProject
+Global
+ GlobalSection(SolutionConfigurationPlatforms) = preSolution
+ Debug|Any CPU = Debug|Any CPU
+ Release|Any CPU = Release|Any CPU
+ EndGlobalSection
+ GlobalSection(ProjectConfigurationPlatforms) = postSolution
+ {76FB25C5-15B1-4541-8D19-D78790257C95}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {76FB25C5-15B1-4541-8D19-D78790257C95}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {76FB25C5-15B1-4541-8D19-D78790257C95}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {76FB25C5-15B1-4541-8D19-D78790257C95}.Release|Any CPU.Build.0 = Release|Any CPU
+ {75BEA10B-761A-474F-9522-57E8974B52D6}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {75BEA10B-761A-474F-9522-57E8974B52D6}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {75BEA10B-761A-474F-9522-57E8974B52D6}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {75BEA10B-761A-474F-9522-57E8974B52D6}.Release|Any CPU.Build.0 = Release|Any CPU
+ EndGlobalSection
+ GlobalSection(SolutionProperties) = preSolution
+ HideSolutionNode = FALSE
+ EndGlobalSection
+EndGlobal
473 SharpHttp/HttpMachine.cs
@@ -0,0 +1,473 @@
+
+#line 1 "HttpMachine.cs.rl"
+using System;
+
+namespace HttpSharp
+{
+ public interface IHttpRequestParser
+ {
+ void OnMethod(ArraySegment<byte> data);
+ void OnRequestUri(ArraySegment<byte> data);
+ void OnQueryString(ArraySegment<byte> data);
+ void OnFragment(ArraySegment<byte> data);
+ void OnVersionMajor(ArraySegment<byte> data);
+ void OnVersionMinor(ArraySegment<byte> data);
+ void OnHeaderName(ArraySegment<byte> data);
+ void OnHeaderValue(ArraySegment<byte> data);
+ void OnHeadersComplete();
+ }
+
+ public class HttpMachine
+ {
+ int cs;
+ int mark;
+ int qsMark;
+ int fragMark;
+ IHttpRequestParser parser;
+
+
+#line 148 "HttpMachine.cs.rl"
+
+
+
+#line 34 "HttpMachine.cs"
+static readonly sbyte[] _http_parser_actions = new sbyte [] {
+ 0, 1, 0, 1, 1, 1, 2, 1,
+ 3, 1, 4, 1, 5, 1, 6, 1,
+ 7, 1, 8, 1, 10, 1, 11, 1,
+ 12, 1, 13, 1, 14, 1, 15, 1,
+ 16, 1, 17, 1, 18, 1, 19, 1,
+ 20, 2, 7, 4, 2, 7, 5, 2,
+ 9, 4, 2, 9, 5
+};
+
+static readonly byte[] _http_parser_key_offsets = new byte [] {
+ 0, 0, 4, 9, 12, 15, 16, 17,
+ 18, 19, 20, 22, 25, 27, 30, 31,
+ 47, 48, 64, 66, 67, 68, 69, 71,
+ 73, 78, 83, 88, 93, 98, 103, 108,
+ 113, 118, 123, 128, 133, 138, 143, 148,
+ 153, 158, 163, 168, 173, 178, 183, 184
+};
+
+static readonly char[] _http_parser_trans_keys = new char [] {
+ '\u0041', '\u005a', '\u0061', '\u007a', '\u0020', '\u0041', '\u005a', '\u0061',
+ '\u007a', '\u0020', '\u0023', '\u003f', '\u0020', '\u0023', '\u003f', '\u0048',
+ '\u0054', '\u0054', '\u0050', '\u002f', '\u0030', '\u0039', '\u002e', '\u0030',
+ '\u0039', '\u0030', '\u0039', '\u000d', '\u0030', '\u0039', '\u000a', '\u000d',
+ '\u0021', '\u007c', '\u007e', '\u0023', '\u0027', '\u002a', '\u002b', '\u002d',
+ '\u002e', '\u0030', '\u0039', '\u0041', '\u005a', '\u005e', '\u007a', '\u000a',
+ '\u0021', '\u003a', '\u007c', '\u007e', '\u0023', '\u0027', '\u002a', '\u002b',
+ '\u002d', '\u002e', '\u0030', '\u0039', '\u0041', '\u005a', '\u005e', '\u007a',
+ '\u0009', '\u0020', '\u000d', '\u0020', '\u0020', '\u0020', '\u0023', '\u0020',
+ '\u0023', '\u0020', '\u0041', '\u005a', '\u0061', '\u007a', '\u0020', '\u0041',
+ '\u005a', '\u0061', '\u007a', '\u0020', '\u0041', '\u005a', '\u0061', '\u007a',
+ '\u0020', '\u0041', '\u005a', '\u0061', '\u007a', '\u0020', '\u0041', '\u005a',
+ '\u0061', '\u007a', '\u0020', '\u0041', '\u005a', '\u0061', '\u007a', '\u0020',
+ '\u0041', '\u005a', '\u0061', '\u007a', '\u0020', '\u0041', '\u005a', '\u0061',
+ '\u007a', '\u0020', '\u0041', '\u005a', '\u0061', '\u007a', '\u0020', '\u0041',
+ '\u005a', '\u0061', '\u007a', '\u0020', '\u0041', '\u005a', '\u0061', '\u007a',
+ '\u0020', '\u0041', '\u005a', '\u0061', '\u007a', '\u0020', '\u0041', '\u005a',
+ '\u0061', '\u007a', '\u0020', '\u0041', '\u005a', '\u0061', '\u007a', '\u0020',
+ '\u0041', '\u005a', '\u0061', '\u007a', '\u0020', '\u0041', '\u005a', '\u0061',
+ '\u007a', '\u0020', '\u0041', '\u005a', '\u0061', '\u007a', '\u0020', '\u0041',
+ '\u005a', '\u0061', '\u007a', '\u0020', '\u0041', '\u005a', '\u0061', '\u007a',
+ '\u0020', '\u0041', '\u005a', '\u0061', '\u007a', '\u0020', '\u0041', '\u005a',
+ '\u0061', '\u007a', '\u0020', '\u0041', '\u005a', '\u0061', '\u007a', '\u0020',
+ (char) 0
+};
+
+static readonly sbyte[] _http_parser_single_lengths = new sbyte [] {
+ 0, 0, 1, 3, 3, 1, 1, 1,
+ 1, 1, 0, 1, 0, 1, 1, 4,
+ 1, 4, 2, 1, 1, 1, 2, 2,
+ 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 0
+};
+
+static readonly sbyte[] _http_parser_range_lengths = new sbyte [] {
+ 0, 2, 2, 0, 0, 0, 0, 0,
+ 0, 0, 1, 1, 1, 1, 0, 6,
+ 0, 6, 0, 0, 0, 0, 0, 0,
+ 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 0, 0
+};
+
+static readonly byte[] _http_parser_index_offsets = new byte [] {
+ 0, 0, 3, 7, 11, 15, 17, 19,
+ 21, 23, 25, 27, 30, 32, 35, 37,
+ 48, 50, 61, 64, 66, 68, 70, 73,
+ 76, 80, 84, 88, 92, 96, 100, 104,
+ 108, 112, 116, 120, 124, 128, 132, 136,
+ 140, 144, 148, 152, 156, 160, 164, 166
+};
+
+static readonly sbyte[] _http_parser_indicies = new sbyte [] {
+ 0, 0, 1, 2, 3, 3, 1, 1,
+ 1, 1, 4, 6, 7, 8, 5, 9,
+ 1, 10, 1, 11, 1, 12, 1, 13,
+ 1, 14, 1, 15, 16, 1, 17, 1,
+ 18, 19, 1, 20, 1, 21, 22, 22,
+ 22, 22, 22, 22, 22, 22, 22, 1,
+ 23, 1, 24, 25, 24, 24, 24, 24,
+ 24, 24, 24, 24, 1, 27, 27, 26,
+ 29, 28, 6, 30, 32, 31, 6, 7,
+ 33, 35, 36, 34, 2, 37, 37, 1,
+ 2, 38, 38, 1, 2, 39, 39, 1,
+ 2, 40, 40, 1, 2, 41, 41, 1,
+ 2, 42, 42, 1, 2, 43, 43, 1,
+ 2, 44, 44, 1, 2, 45, 45, 1,
+ 2, 46, 46, 1, 2, 47, 47, 1,
+ 2, 48, 48, 1, 2, 49, 49, 1,
+ 2, 50, 50, 1, 2, 51, 51, 1,
+ 2, 52, 52, 1, 2, 53, 53, 1,
+ 2, 54, 54, 1, 2, 55, 55, 1,
+ 2, 56, 56, 1, 2, 57, 57, 1,
+ 2, 58, 58, 1, 2, 1, 1, 0
+};
+
+static readonly sbyte[] _http_parser_trans_targs = new sbyte [] {
+ 2, 0, 3, 24, 4, 4, 5, 20,
+ 22, 6, 7, 8, 9, 10, 11, 12,
+ 11, 13, 14, 13, 15, 16, 17, 47,
+ 17, 18, 19, 18, 19, 14, 21, 21,
+ 5, 23, 23, 5, 20, 25, 26, 27,
+ 28, 29, 30, 31, 32, 33, 34, 35,
+ 36, 37, 38, 39, 40, 41, 42, 43,
+ 44, 45, 46
+};
+
+static readonly sbyte[] _http_parser_trans_actions = new sbyte [] {
+ 1, 0, 5, 0, 7, 0, 11, 0,
+ 0, 0, 0, 0, 0, 0, 19, 23,
+ 0, 25, 29, 0, 0, 0, 31, 0,
+ 0, 33, 35, 0, 0, 37, 17, 0,
+ 50, 13, 0, 44, 15, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0
+};
+
+static readonly sbyte[] _http_parser_eof_actions = new sbyte [] {
+ 0, 0, 3, 0, 9, 0, 0, 0,
+ 0, 0, 0, 21, 0, 27, 0, 0,
+ 0, 33, 0, 37, 9, 47, 9, 41,
+ 3, 3, 3, 3, 3, 3, 3, 3,
+ 3, 3, 3, 3, 3, 3, 3, 3,
+ 3, 3, 3, 3, 3, 3, 3, 39
+};
+
+const int http_parser_start = 1;
+const int http_parser_first_final = 47;
+const int http_parser_error = 0;
+
+const int http_parser_en_main = 1;
+
+
+#line 151 "HttpMachine.cs.rl"
+
+ public HttpMachine(IHttpRequestParser parser)
+ {
+ this.parser = parser;
+
+#line 176 "HttpMachine.cs"
+ {
+ cs = http_parser_start;
+ }
+
+#line 156 "HttpMachine.cs.rl"
+ }
+
+ public int Execute(ArraySegment<byte> buf)
+ {
+ byte[] data = buf.Array;
+ int p = buf.Offset;
+ int pe = buf.Offset + buf.Count;
+ //int eof = pe == 0 ? 0 : -1;
+ int eof = pe;
+ mark = 0;
+ qsMark = 0;
+ fragMark = 0;
+
+
+#line 196 "HttpMachine.cs"
+ {
+ sbyte _klen;
+ byte _trans;
+ sbyte _acts;
+ sbyte _nacts;
+ byte _keys;
+
+ if ( p == pe )
+ goto _test_eof;
+ if ( cs == 0 )
+ goto _out;
+_resume:
+ _keys = _http_parser_key_offsets[cs];
+ _trans = (byte)_http_parser_index_offsets[cs];
+
+ _klen = _http_parser_single_lengths[cs];
+ if ( _klen > 0 ) {
+ short _lower = _keys;
+ short _mid;
+ short _upper = (short) (_keys + _klen - 1);
+ while (true) {
+ if ( _upper < _lower )
+ break;
+
+ _mid = (short) (_lower + ((_upper-_lower) >> 1));
+ if ( data[p] < _http_parser_trans_keys[_mid] )
+ _upper = (short) (_mid - 1);
+ else if ( data[p] > _http_parser_trans_keys[_mid] )
+ _lower = (short) (_mid + 1);
+ else {
+ _trans += (byte) (_mid - _keys);
+ goto _match;
+ }
+ }
+ _keys += (byte) _klen;
+ _trans += (byte) _klen;
+ }
+
+ _klen = _http_parser_range_lengths[cs];
+ if ( _klen > 0 ) {
+ short _lower = _keys;
+ short _mid;
+ short _upper = (short) (_keys + (_klen<<1) - 2);
+ while (true) {
+ if ( _upper < _lower )
+ break;
+
+ _mid = (short) (_lower + (((_upper-_lower) >> 1) & ~1));
+ if ( data[p] < _http_parser_trans_keys[_mid] )
+ _upper = (short) (_mid - 2);
+ else if ( data[p] > _http_parser_trans_keys[_mid+1] )
+ _lower = (short) (_mid + 2);
+ else {
+ _trans += (byte)((_mid - _keys)>>1);
+ goto _match;
+ }
+ }
+ _trans += (byte) _klen;
+ }
+
+_match:
+ _trans = (byte)_http_parser_indicies[_trans];
+ cs = _http_parser_trans_targs[_trans];
+
+ if ( _http_parser_trans_actions[_trans] == 0 )
+ goto _again;
+
+ _acts = _http_parser_trans_actions[_trans];
+ _nacts = _http_parser_actions[_acts++];
+ while ( _nacts-- > 0 )
+ {
+ switch ( _http_parser_actions[_acts++] )
+ {
+ case 0:
+#line 44 "HttpMachine.cs.rl"
+ {
+ mark = p;
+ }
+ break;
+ case 2:
+#line 53 "HttpMachine.cs.rl"
+ {
+ //Console.WriteLine("leave_method fpc " + fpc + " mark " + mark);
+ parser.OnMethod(new ArraySegment<byte>(data, mark, p - mark));
+ }
+ break;
+ case 3:
+#line 58 "HttpMachine.cs.rl"
+ {
+ //Console.WriteLine("enter_request_uri fpc " + fpc);
+ mark = p;
+ }
+ break;
+ case 5:
+#line 68 "HttpMachine.cs.rl"
+ {
+ //Console.WriteLine("leave_request_uri fpc " + fpc + " mark " + mark);
+ parser.OnRequestUri(new ArraySegment<byte>(data, mark, p - mark));
+ }
+ break;
+ case 6:
+#line 73 "HttpMachine.cs.rl"
+ {
+ //Console.WriteLine("enter_query_string fpc " + fpc);
+ qsMark = p;
+ }
+ break;
+ case 7:
+#line 78 "HttpMachine.cs.rl"
+ {
+ //Console.WriteLine("leave_query_string fpc " + fpc + " qsMark " + qsMark);
+ parser.OnQueryString(new ArraySegment<byte>(data, qsMark, p - qsMark));
+ }
+ break;
+ case 8:
+#line 82 "HttpMachine.cs.rl"
+ {
+ //Console.WriteLine("enter_fragment fpc " + fpc);
+ fragMark = p;
+ }
+ break;
+ case 9:
+#line 87 "HttpMachine.cs.rl"
+ {
+ //Console.WriteLine("leave_fragment fpc " + fpc + " fragMark " + fragMark);
+ parser.OnFragment(new ArraySegment<byte>(data, fragMark, p - fragMark));
+ }
+ break;
+ case 10:
+#line 92 "HttpMachine.cs.rl"
+ {
+ //Console.WriteLine("enter_version_major fpc " + fpc);
+ mark = p;
+ }
+ break;
+ case 12:
+#line 102 "HttpMachine.cs.rl"
+ {
+ //Console.WriteLine("leave_version_major fpc " + fpc + " mark " + mark);
+ parser.OnVersionMajor(new ArraySegment<byte>(data, mark, p - mark));
+ }
+ break;
+ case 13:
+#line 107 "HttpMachine.cs.rl"
+ {
+ //Console.WriteLine("enter_request_uri fpc " + fpc);
+ mark = p;
+ }
+ break;
+ case 15:
+#line 117 "HttpMachine.cs.rl"
+ {
+ //Console.WriteLine("leave_version_minor fpc " + fpc + " mark " + mark);
+ parser.OnVersionMinor(new ArraySegment<byte>(data, mark, p - mark));
+ }
+ break;
+ case 16:
+#line 122 "HttpMachine.cs.rl"
+ {
+ //Console.WriteLine("enter_header_name fpc " + fpc + " fc " + (char)fc);
+ mark = p;
+ }
+ break;
+ case 17:
+#line 127 "HttpMachine.cs.rl"
+ {
+ //Console.WriteLine("leave_header_name fpc " + fpc + " fc " + (char)fc);
+ parser.OnHeaderName(new ArraySegment<byte>(data, mark, p - mark));
+ }
+ break;
+ case 18:
+#line 132 "HttpMachine.cs.rl"
+ {
+ //Console.WriteLine("enter_header_value fpc " + fpc + " fc " + (char)fc);
+ mark = p;
+ }
+ break;
+ case 19:
+#line 137 "HttpMachine.cs.rl"
+ {
+ //Console.WriteLine("leave_header_value fpc " + fpc + " fc " + (char)fc);
+ parser.OnHeaderValue(new ArraySegment<byte>(data, mark, p - mark));
+ }
+ break;
+#line 381 "HttpMachine.cs"
+ default: break;
+ }
+ }
+
+_again:
+ if ( cs == 0 )
+ goto _out;
+ if ( ++p != pe )
+ goto _resume;
+ _test_eof: {}
+ if ( p == eof )
+ {
+ sbyte __acts = _http_parser_eof_actions[cs];
+ sbyte __nacts = _http_parser_actions[__acts++];
+ while ( __nacts-- > 0 ) {
+ switch ( _http_parser_actions[__acts++] ) {
+ case 1:
+#line 48 "HttpMachine.cs.rl"
+ {
+ //Console.WriteLine("eof_leave_method fpc " + fpc + " mark " + mark);
+ parser.OnMethod(new ArraySegment<byte>(data, mark, p - mark));
+ }
+ break;
+ case 4:
+#line 63 "HttpMachine.cs.rl"
+ {
+ //Console.WriteLine("eof_leave_request_uri!! fpc " + fpc + " mark " + mark);
+ parser.OnRequestUri(new ArraySegment<byte>(data, mark, p - mark));
+ }
+ break;
+ case 7:
+#line 78 "HttpMachine.cs.rl"
+ {
+ //Console.WriteLine("leave_query_string fpc " + fpc + " qsMark " + qsMark);
+ parser.OnQueryString(new ArraySegment<byte>(data, qsMark, p - qsMark));
+ }
+ break;
+ case 9:
+#line 87 "HttpMachine.cs.rl"
+ {
+ //Console.WriteLine("leave_fragment fpc " + fpc + " fragMark " + fragMark);
+ parser.OnFragment(new ArraySegment<byte>(data, fragMark, p - fragMark));
+ }
+ break;
+ case 11:
+#line 97 "HttpMachine.cs.rl"
+ {
+ //Console.WriteLine("eof_leave_version_major fpc " + fpc + " mark " + mark);
+ parser.OnVersionMajor(new ArraySegment<byte>(data, mark, p - mark));
+ }
+ break;
+ case 14:
+#line 112 "HttpMachine.cs.rl"
+ {
+ //Console.WriteLine("eof_leave_version_minor!! fpc " + fpc + " mark " + mark);
+ parser.OnVersionMinor(new ArraySegment<byte>(data, mark, p - mark));
+ }
+ break;
+ case 17:
+#line 127 "HttpMachine.cs.rl"
+ {
+ //Console.WriteLine("leave_header_name fpc " + fpc + " fc " + (char)fc);
+ parser.OnHeaderName(new ArraySegment<byte>(data, mark, p - mark));
+ }
+ break;
+ case 19:
+#line 137 "HttpMachine.cs.rl"
+ {
+ //Console.WriteLine("leave_header_value fpc " + fpc + " fc " + (char)fc);
+ parser.OnHeaderValue(new ArraySegment<byte>(data, mark, p - mark));
+ }
+ break;
+ case 20:
+#line 142 "HttpMachine.cs.rl"
+ {
+ parser.OnHeadersComplete();
+ }
+ break;
+#line 460 "HttpMachine.cs"
+ default: break;
+ }
+ }
+ }
+
+ _out: {}
+ }
+
+#line 170 "HttpMachine.cs.rl"
+
+ return p - buf.Offset;
+ }
+ }
+}
174 SharpHttp/HttpMachine.cs.rl
@@ -0,0 +1,174 @@
+using System;
+
+namespace HttpSharp
+{
+ public interface IHttpRequestParser
+ {
+ void OnMethod(ArraySegment<byte> data);
+ void OnRequestUri(ArraySegment<byte> data);
+ void OnQueryString(ArraySegment<byte> data);
+ void OnFragment(ArraySegment<byte> data);
+ void OnVersionMajor(ArraySegment<byte> data);
+ void OnVersionMinor(ArraySegment<byte> data);
+ void OnHeaderName(ArraySegment<byte> data);
+ void OnHeaderValue(ArraySegment<byte> data);
+ void OnHeadersComplete();
+ }
+
+ public class HttpMachine
+ {
+ int cs;
+ int mark;
+ int qsMark;
+ int fragMark;
+ IHttpRequestParser parser;
+
+ %%{
+
+ # define actions
+ machine http_parser;
+
+ action matched_absolute_uri {
+ Console.WriteLine("matched absolute_uri");
+ }
+ action matched_abs_path {
+ Console.WriteLine("matched abs_path");
+ }
+ action matched_authority {
+ Console.WriteLine("matched authority");
+ }
+ action matched_first_space {
+ Console.WriteLine("matched first space");
+ }
+
+ action enter_method {
+ mark = fpc;
+ }
+
+ action eof_leave_method {
+ //Console.WriteLine("eof_leave_method fpc " + fpc + " mark " + mark);
+ parser.OnMethod(new ArraySegment<byte>(data, mark, fpc - mark));
+ }
+
+ action leave_method {
+ //Console.WriteLine("leave_method fpc " + fpc + " mark " + mark);
+ parser.OnMethod(new ArraySegment<byte>(data, mark, fpc - mark));
+ }
+
+ action enter_request_uri {
+ //Console.WriteLine("enter_request_uri fpc " + fpc);
+ mark = fpc;
+ }
+
+ action eof_leave_request_uri {
+ //Console.WriteLine("eof_leave_request_uri!! fpc " + fpc + " mark " + mark);
+ parser.OnRequestUri(new ArraySegment<byte>(data, mark, fpc - mark));
+ }
+
+ action leave_request_uri {
+ //Console.WriteLine("leave_request_uri fpc " + fpc + " mark " + mark);
+ parser.OnRequestUri(new ArraySegment<byte>(data, mark, fpc - mark));
+ }
+
+ action enter_query_string {
+ //Console.WriteLine("enter_query_string fpc " + fpc);
+ qsMark = fpc;
+ }
+
+ action leave_query_string {
+ //Console.WriteLine("leave_query_string fpc " + fpc + " qsMark " + qsMark);
+ parser.OnQueryString(new ArraySegment<byte>(data, qsMark, fpc - qsMark));
+ }
+ action enter_fragment {
+ //Console.WriteLine("enter_fragment fpc " + fpc);
+ fragMark = fpc;
+ }
+
+ action leave_fragment {
+ //Console.WriteLine("leave_fragment fpc " + fpc + " fragMark " + fragMark);
+ parser.OnFragment(new ArraySegment<byte>(data, fragMark, fpc - fragMark));
+ }
+
+ action enter_version_major {
+ //Console.WriteLine("enter_version_major fpc " + fpc);
+ mark = fpc;
+ }
+
+ action eof_leave_version_major {
+ //Console.WriteLine("eof_leave_version_major fpc " + fpc + " mark " + mark);
+ parser.OnVersionMajor(new ArraySegment<byte>(data, mark, fpc - mark));
+ }
+
+ action leave_version_major {
+ //Console.WriteLine("leave_version_major fpc " + fpc + " mark " + mark);
+ parser.OnVersionMajor(new ArraySegment<byte>(data, mark, fpc - mark));
+ }
+
+ action enter_version_minor {
+ //Console.WriteLine("enter_request_uri fpc " + fpc);
+ mark = fpc;
+ }
+
+ action eof_leave_version_minor {
+ //Console.WriteLine("eof_leave_version_minor!! fpc " + fpc + " mark " + mark);
+ parser.OnVersionMinor(new ArraySegment<byte>(data, mark, fpc - mark));
+ }
+
+ action leave_version_minor {
+ //Console.WriteLine("leave_version_minor fpc " + fpc + " mark " + mark);
+ parser.OnVersionMinor(new ArraySegment<byte>(data, mark, fpc - mark));
+ }
+
+ action enter_header_name {
+ //Console.WriteLine("enter_header_name fpc " + fpc + " fc " + (char)fc);
+ mark = fpc;
+ }
+
+ action leave_header_name {
+ //Console.WriteLine("leave_header_name fpc " + fpc + " fc " + (char)fc);
+ parser.OnHeaderName(new ArraySegment<byte>(data, mark, fpc - mark));
+ }
+
+ action enter_header_value {
+ //Console.WriteLine("enter_header_value fpc " + fpc + " fc " + (char)fc);
+ mark = fpc;
+ }
+
+ action leave_header_value {
+ //Console.WriteLine("leave_header_value fpc " + fpc + " fc " + (char)fc);
+ parser.OnHeaderValue(new ArraySegment<byte>(data, mark, fpc - mark));
+ }
+
+ action leave_headers {
+ parser.OnHeadersComplete();
+ }
+
+ include http "http.rl";
+
+ }%%
+
+ %% write data;
+
+ public HttpMachine(IHttpRequestParser parser)
+ {
+ this.parser = parser;
+ %% write init;
+ }
+
+ public int Execute(ArraySegment<byte> buf)
+ {
+ byte[] data = buf.Array;
+ int p = buf.Offset;
+ int pe = buf.Offset + buf.Count;
+ //int eof = pe == 0 ? 0 : -1;
+ int eof = pe;
+ mark = 0;
+ qsMark = 0;
+ fragMark = 0;
+
+ %% write exec;
+
+ return p - buf.Offset;
+ }
+ }
+}
36 SharpHttp/Properties/AssemblyInfo.cs
@@ -0,0 +1,36 @@
+using System.Reflection;
+using System.Runtime.CompilerServices;
+using System.Runtime.InteropServices;
+
+// General Information about an assembly is controlled through the following
+// set of attributes. Change these attribute values to modify the information
+// associated with an assembly.
+[assembly: AssemblyTitle("SharpHttp")]
+[assembly: AssemblyDescription("")]
+[assembly: AssemblyConfiguration("")]
+[assembly: AssemblyCompany("Microsoft")]
+[assembly: AssemblyProduct("SharpHttp")]
+[assembly: AssemblyCopyright("Copyright © Microsoft 2011")]
+[assembly: AssemblyTrademark("")]
+[assembly: AssemblyCulture("")]
+
+// Setting ComVisible to false makes the types in this assembly not visible
+// to COM components. If you need to access a type in this assembly from
+// COM, set the ComVisible attribute to true on that type.
+[assembly: ComVisible(false)]
+
+// The following GUID is for the ID of the typelib if this project is exposed to COM
+[assembly: Guid("5d982d49-f256-4abf-89dc-c76d31add193")]
+
+// Version information for an assembly consists of the following four values:
+//
+// Major Version
+// Minor Version
+// Build Number
+// Revision
+//
+// You can specify all the values or you can default the Build and Revision Numbers
+// by using the '*' as shown below:
+// [assembly: AssemblyVersion("1.0.*")]
+[assembly: AssemblyVersion("1.0.0.0")]
+[assembly: AssemblyFileVersion("1.0.0.0")]
59 SharpHttp/SharpHttp.csproj
@@ -0,0 +1,59 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="4.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <PropertyGroup>
+ <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
+ <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
+ <ProductVersion>8.0.30703</ProductVersion>
+ <SchemaVersion>2.0</SchemaVersion>
+ <ProjectGuid>{76FB25C5-15B1-4541-8D19-D78790257C95}</ProjectGuid>
+ <OutputType>Library</OutputType>
+ <AppDesignerFolder>Properties</AppDesignerFolder>
+ <RootNamespace>SharpHttp</RootNamespace>
+ <AssemblyName>SharpHttp</AssemblyName>
+ <TargetFrameworkVersion>v4.0</TargetFrameworkVersion>
+ <FileAlignment>512</FileAlignment>
+ </PropertyGroup>
+ <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
+ <DebugSymbols>true</DebugSymbols>
+ <DebugType>full</DebugType>
+ <Optimize>false</Optimize>
+ <OutputPath>bin\Debug\</OutputPath>
+ <DefineConstants>DEBUG;TRACE</DefineConstants>
+ <ErrorReport>prompt</ErrorReport>
+ <WarningLevel>4</WarningLevel>
+ </PropertyGroup>
+ <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
+ <DebugType>pdbonly</DebugType>
+ <Optimize>true</Optimize>
+ <OutputPath>bin\Release\</OutputPath>
+ <DefineConstants>TRACE</DefineConstants>
+ <ErrorReport>prompt</ErrorReport>
+ <WarningLevel>4</WarningLevel>
+ </PropertyGroup>
+ <ItemGroup>
+ <Reference Include="System" />
+ <Reference Include="System.Core" />
+ <Reference Include="System.Xml.Linq" />
+ <Reference Include="System.Data.DataSetExtensions" />
+ <Reference Include="Microsoft.CSharp" />
+ <Reference Include="System.Data" />
+ <Reference Include="System.Xml" />
+ </ItemGroup>
+ <ItemGroup>
+ <Compile Include="HttpMachine.cs" />
+ <Compile Include="Properties\AssemblyInfo.cs" />
+ </ItemGroup>
+ <ItemGroup>
+ <None Include="http.rl" />
+ <None Include="HttpMachine.cs.rl" />
+ <None Include="uri.rl" />
+ </ItemGroup>
+ <Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
+ <!-- To modify your build process, add your task inside one of the targets below and uncomment it.
+ Other similar extension points exist, see Microsoft.Common.targets.
+ <Target Name="BeforeBuild">
+ </Target>
+ <Target Name="AfterBuild">
+ </Target>
+ -->
+</Project>
33 SharpHttp/http.rl
@@ -0,0 +1,33 @@
+%%{
+
+machine http;
+
+include uri "uri.rl";
+
+http_crlf = "\r\n";
+http_cntrl = (cntrl | 127);
+http_separators = "(" | ")" | "<" | ">" | "@" | "," | ";" | ":" | "\\" | "\"" | "/" | "[" | "]" | "?" | "=" | "{" | "}" | " " | "\t";
+http_token = (ascii -- (http_cntrl | http_separators))+;
+
+
+# accept any method name less than 24 chars
+http_request_method = alpha {1,24};
+#http_request_uri = ("*" | absolute_uri >matched_absolute_uri | abs_path >matched_abs_path | authority >matched_authority);
+http_request_uri = "*" | ((any -- (" " | "#" | "?" | http_crlf))+ ("?" ((any -- (" " | "#" | http_crlf))+ >enter_query_string %/leave_query_string %leave_query_string)?)? ("#" ((any -- (" " | http_crlf))+ >enter_fragment %/leave_fragment %leave_fragment)?)?);
+
+http_version = "HTTP/" (digit+ >enter_version_major %/eof_leave_version_major %leave_version_major) "." (digit+ >enter_version_minor %/eof_leave_version_minor %leave_version_minor);
+http_request_line = (http_request_method >enter_method %/eof_leave_method %leave_method) " " (http_request_uri >enter_request_uri %/eof_leave_request_uri %leave_request_uri) " " http_version http_crlf;
+
+http_header_name = http_token;
+
+# not getting fancy with header values, just reading everything until CRLF and calling it good.
+# thus we don't support line folding. fuck that noise.
+http_header_value = any+;
+
+http_header = http_header_name >enter_header_name %/leave_header_name %leave_header_name ((":" (" " | "\t")*) ) <: http_header_value >enter_header_value %/leave_header_value %leave_header_value :> http_crlf;
+
+http_request = http_request_line (http_header)* http_crlf %leave_headers;
+
+main := http_request;
+
+}%%
51 SharpHttp/uri.rl
@@ -0,0 +1,51 @@
+%%{
+
+machine uri;
+
+scheme = alpha (alpha | digit | "+" | "-" | ".")+;
+
+escaped = "%" xdigit xdigit;
+mark = "-" | "_" | "." | "!" | "~" | "*" | "'" | "(" | ")";
+reserved = ";" | "/" | "?" | ":" | "@" | "&" | "=" | "+" | "$" | ",";
+unreserved = alpha | mark;
+pchar = unreserved | escaped | ":" | "@" | "&" | "=" | "+" | "$" | ",";
+uric = reserved | unreserved | escaped;
+uric_no_slash = unreserved | escaped | ";" | "?" | ":" | "@" | "&" | "=" | "+" | "$" | ",";
+rel_segment = (unreserved | escaped | ";" | "@" | "&" | "=" | "+" | "$" | ",")+;
+reg_name = (unreserved | escaped | "$" | "," | ";" | ":" | "@" | "&" | "=" | "+" )+;
+userinfo = (unreserved | escaped | ";" | ":" | "&" | "=" | "+" | "$" | "," )*;
+
+param = pchar*;
+segment = pchar* (";" param)*;
+path_segments = segment ("/" segment)*;
+abs_path = "/" path_segments;
+
+rel_path = rel_segment abs_path?;
+
+query = uric*;
+fragment = uric*;
+
+ipv4address = digit{1,3} "." digit{1,3} "." digit{1,3} "." digit{1,3};
+toplabel = alpha | alpha (alnum | "-")* alnum;
+domainlabel = alnum | (alnum (alnum | "-")* alnum);
+hostname = (domainlabel ".") toplabel "."?;
+
+# might be better to condense host to (alnum | "." | "-")*;
+host = hostname | ipv4address;
+port = digit*;
+
+hostport = host (":" port);
+server = ((userinfo "@")? hostport)?;
+authority = server | reg_name;
+net_path = "//" authority abs_path?;
+
+opaque_part = uric_no_slash uric*;
+hier_part = (net_path | abs_path) ("?" query)?;
+
+
+absolute_uri = scheme ":" (hier_part | opaque_part);
+relative_uri = (abs_path | rel_path) ("?" query)?;
+
+uri_reference = (absolute_uri | relative_uri)? ("#" fragment)?;
+
+}%%
Please sign in to comment.
Something went wrong with that request. Please try again.