Commit 23119af4 authored by Shani Elharrar's avatar Shani Elharrar

Merge pull request #6 from shanielh/RawPost

Lazy parsing of post body, Expose raw post body in the request. 
parents 1dc869a7 97154d8d
 
Microsoft Visual Studio Solution File, Format Version 12.00 Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio 2013 # Visual Studio 2012
VisualStudioVersion = 12.0.21005.1
MinimumVisualStudioVersion = 10.0.40219.1
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "uhttpsharp.Demo", "uhttpsharp-demo\uhttpsharp.Demo.csproj", "{55C5E8D2-F55E-4B9F-B96F-FCE201739D07}" Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "uhttpsharp.Demo", "uhttpsharp-demo\uhttpsharp.Demo.csproj", "{55C5E8D2-F55E-4B9F-B96F-FCE201739D07}"
EndProject EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "uhttpsharp", "uhttpsharp\uhttpsharp.csproj", "{3D681959-4DA3-4A71-A68B-704D6411D5EA}" Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "uhttpsharp", "uhttpsharp\uhttpsharp.csproj", "{3D681959-4DA3-4A71-A68B-704D6411D5EA}"
...@@ -32,16 +30,6 @@ Global ...@@ -32,16 +30,6 @@ Global
Release|x86 = Release|x86 Release|x86 = Release|x86
EndGlobalSection EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution GlobalSection(ProjectConfigurationPlatforms) = postSolution
{55C5E8D2-F55E-4B9F-B96F-FCE201739D07}.Debug|Any CPU.ActiveCfg = Debug|x86
{55C5E8D2-F55E-4B9F-B96F-FCE201739D07}.Debug|Mixed Platforms.ActiveCfg = Debug|x86
{55C5E8D2-F55E-4B9F-B96F-FCE201739D07}.Debug|Mixed Platforms.Build.0 = Debug|x86
{55C5E8D2-F55E-4B9F-B96F-FCE201739D07}.Debug|x86.ActiveCfg = Debug|x86
{55C5E8D2-F55E-4B9F-B96F-FCE201739D07}.Debug|x86.Build.0 = Debug|x86
{55C5E8D2-F55E-4B9F-B96F-FCE201739D07}.Release|Any CPU.ActiveCfg = Release|x86
{55C5E8D2-F55E-4B9F-B96F-FCE201739D07}.Release|Mixed Platforms.ActiveCfg = Release|x86
{55C5E8D2-F55E-4B9F-B96F-FCE201739D07}.Release|Mixed Platforms.Build.0 = Release|x86
{55C5E8D2-F55E-4B9F-B96F-FCE201739D07}.Release|x86.ActiveCfg = Release|x86
{55C5E8D2-F55E-4B9F-B96F-FCE201739D07}.Release|x86.Build.0 = Release|x86
{3D681959-4DA3-4A71-A68B-704D6411D5EA}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {3D681959-4DA3-4A71-A68B-704D6411D5EA}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{3D681959-4DA3-4A71-A68B-704D6411D5EA}.Debug|Any CPU.Build.0 = Debug|Any CPU {3D681959-4DA3-4A71-A68B-704D6411D5EA}.Debug|Any CPU.Build.0 = Debug|Any CPU
{3D681959-4DA3-4A71-A68B-704D6411D5EA}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU {3D681959-4DA3-4A71-A68B-704D6411D5EA}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU
...@@ -62,6 +50,22 @@ Global ...@@ -62,6 +50,22 @@ Global
{41C9BDAC-21BE-4C50-933D-9E047F767E63}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU {41C9BDAC-21BE-4C50-933D-9E047F767E63}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU
{41C9BDAC-21BE-4C50-933D-9E047F767E63}.Release|Mixed Platforms.Build.0 = Release|Any CPU {41C9BDAC-21BE-4C50-933D-9E047F767E63}.Release|Mixed Platforms.Build.0 = Release|Any CPU
{41C9BDAC-21BE-4C50-933D-9E047F767E63}.Release|x86.ActiveCfg = Release|Any CPU {41C9BDAC-21BE-4C50-933D-9E047F767E63}.Release|x86.ActiveCfg = Release|Any CPU
{55C5E8D2-F55E-4B9F-B96F-FCE201739D07}.Debug|Any CPU.ActiveCfg = Debug|x86
{55C5E8D2-F55E-4B9F-B96F-FCE201739D07}.Debug|Any CPU.Build.0 = Debug|x86
{55C5E8D2-F55E-4B9F-B96F-FCE201739D07}.Debug|Mixed Platforms.ActiveCfg = Debug|x86
{55C5E8D2-F55E-4B9F-B96F-FCE201739D07}.Debug|Mixed Platforms.Build.0 = Debug|x86
{55C5E8D2-F55E-4B9F-B96F-FCE201739D07}.Debug|x86.ActiveCfg = Debug|x86
{55C5E8D2-F55E-4B9F-B96F-FCE201739D07}.Debug|x86.Build.0 = Debug|x86
{55C5E8D2-F55E-4B9F-B96F-FCE201739D07}.Release|Any CPU.ActiveCfg = Release|x86
{55C5E8D2-F55E-4B9F-B96F-FCE201739D07}.Release|Mixed Platforms.ActiveCfg = Release|x86
{55C5E8D2-F55E-4B9F-B96F-FCE201739D07}.Release|Mixed Platforms.Build.0 = Release|x86
{55C5E8D2-F55E-4B9F-B96F-FCE201739D07}.Release|x86.ActiveCfg = Release|x86
{55C5E8D2-F55E-4B9F-B96F-FCE201739D07}.Release|x86.Build.0 = Release|x86
EndGlobalSection
GlobalSection(NestedProjects) = preSolution
EndGlobalSection
GlobalSection(MonoDevelopProperties) = preSolution
StartupItem = uhttpsharp-demo\uhttpsharp.Demo.csproj
EndGlobalSection EndGlobalSection
GlobalSection(SolutionProperties) = preSolution GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE HideSolutionNode = FALSE
......
...@@ -5,9 +5,99 @@ using System.Diagnostics; ...@@ -5,9 +5,99 @@ using System.Diagnostics;
using System.IO; using System.IO;
using System.Text; using System.Text;
using System.Threading.Tasks; using System.Threading.Tasks;
using System.Security.AccessControl;
namespace uhttpsharp.Headers namespace uhttpsharp.Headers
{ {
internal class EmptyHttpPost : IHttpPost
{
private static readonly byte[] _emptyBytes = new byte[0];
public static readonly IHttpPost Empty = new EmptyHttpPost();
private EmptyHttpPost()
{
}
#region IHttpPost implementation
public byte[] Raw
{
get
{
return _emptyBytes;
}
}
public IHttpHeaders Parsed
{
get
{
return EmptyHttpHeaders.Empty;
}
}
#endregion
}
internal class HttpPost : IHttpPost
{
public static async Task<IHttpPost> Create(StreamReader reader, int postContentLength)
{
char[] rawEncoded = new char[postContentLength];
int readBytes = await reader.ReadAsync(rawEncoded, 0, rawEncoded.Length);
byte[] raw = Encoding.UTF8.GetBytes(rawEncoded, 0, readBytes);
return new HttpPost(raw, readBytes);
}
private readonly int _readBytes;
private readonly byte[] _raw;
private readonly Lazy<IHttpHeaders> _parsed;
public HttpPost(byte[] raw, int readBytes)
{
_raw = raw;
_readBytes = readBytes;
_parsed = new Lazy<IHttpHeaders>(Parse);
}
private IHttpHeaders Parse()
{
string body = Encoding.UTF8.GetString(_raw, 0, _readBytes);
var parsed = new QueryStringHttpHeaders(body);
return parsed;
}
#region IHttpPost implementation
public byte[] Raw
{
get
{
return _raw;
}
}
public IHttpHeaders Parsed
{
get
{
return _parsed.Value;
}
}
#endregion
}
[DebuggerDisplay("{Count} Headers")] [DebuggerDisplay("{Count} Headers")]
[DebuggerTypeProxy(typeof(HttpHeadersDebuggerProxy))] [DebuggerTypeProxy(typeof(HttpHeadersDebuggerProxy))]
internal class HttpHeaders : IHttpHeaders internal class HttpHeaders : IHttpHeaders
...@@ -38,16 +128,6 @@ namespace uhttpsharp.Headers ...@@ -38,16 +128,6 @@ namespace uhttpsharp.Headers
return GetEnumerator(); return GetEnumerator();
} }
public static async Task<IHttpHeaders> FromPost(StreamReader reader, int postContentLength)
{
byte[] buffer = new byte[postContentLength];
var readBytes = await reader.BaseStream.ReadAsync(buffer, 0, postContentLength);
string body = Encoding.UTF8.GetString(buffer, 0, readBytes);
return new QueryStringHttpHeaders(body);
}
internal int Count internal int Count
{ {
......
...@@ -22,8 +22,12 @@ namespace uhttpsharp.Headers ...@@ -22,8 +22,12 @@ namespace uhttpsharp.Headers
for (int i = 0; i < splittedKeyValues.Length; i += 2) for (int i = 0; i < splittedKeyValues.Length; i += 2)
{ {
var key = Uri.UnescapeDataString(splittedKeyValues[i]); var key = Uri.UnescapeDataString(splittedKeyValues[i]);
var value = Uri.UnescapeDataString(splittedKeyValues[i + 1]).Replace('+', ' '); string value = null;
if (splittedKeyValues.Length > i + 1)
{
value = Uri.UnescapeDataString(splittedKeyValues[i + 1]).Replace('+', ' ');
}
values[key] = value; values[key] = value;
} }
......
...@@ -33,9 +33,9 @@ namespace uhttpsharp ...@@ -33,9 +33,9 @@ namespace uhttpsharp
private readonly Uri _uri; private readonly Uri _uri;
private readonly string[] _requestParameters; private readonly string[] _requestParameters;
private readonly IHttpHeaders _queryString; private readonly IHttpHeaders _queryString;
private readonly IHttpHeaders _post; private readonly IHttpPost _post;
public HttpRequest(IHttpHeaders headers, HttpMethods method, string protocol, Uri uri, string[] requestParameters, IHttpHeaders queryString, IHttpHeaders post) public HttpRequest(IHttpHeaders headers, HttpMethods method, string protocol, Uri uri, string[] requestParameters, IHttpHeaders queryString, IHttpPost post)
{ {
_headers = headers; _headers = headers;
_method = method; _method = method;
...@@ -71,7 +71,7 @@ namespace uhttpsharp ...@@ -71,7 +71,7 @@ namespace uhttpsharp
get { return _requestParameters; } get { return _requestParameters; }
} }
public IHttpHeaders Post public IHttpPost Post
{ {
get { return _post; } get { return _post; }
} }
...@@ -108,10 +108,18 @@ namespace uhttpsharp ...@@ -108,10 +108,18 @@ namespace uhttpsharp
string[] RequestParameters { get; } string[] RequestParameters { get; }
IHttpHeaders Post { get; } IHttpPost Post {get;}
IHttpHeaders QueryString { get; } IHttpHeaders QueryString { get; }
}
public interface IHttpPost
{
byte[] Raw {get;}
IHttpHeaders Parsed {get;}
} }
......
...@@ -43,7 +43,7 @@ namespace uhttpsharp.RequestProviders ...@@ -43,7 +43,7 @@ namespace uhttpsharp.RequestProviders
} }
IHttpHeaders headers = new HttpHeaders(headersRaw); IHttpHeaders headers = new HttpHeaders(headersRaw);
IHttpHeaders post = await GetPostData(streamReader, headers); IHttpPost post = await GetPostData(streamReader, headers);
return new HttpRequest(headers, httpMethod, httpProtocol, uri, return new HttpRequest(headers, httpMethod, httpProtocol, uri,
uri.OriginalString.Split(Separators, StringSplitOptions.RemoveEmptyEntries), queryString, post); uri.OriginalString.Split(Separators, StringSplitOptions.RemoveEmptyEntries), queryString, post);
...@@ -64,17 +64,17 @@ namespace uhttpsharp.RequestProviders ...@@ -64,17 +64,17 @@ namespace uhttpsharp.RequestProviders
return queryString; return queryString;
} }
private static async Task<IHttpHeaders> GetPostData(StreamReader streamReader, IHttpHeaders headers) private static async Task<IHttpPost> GetPostData(StreamReader streamReader, IHttpHeaders headers)
{ {
int postContentLength; int postContentLength;
IHttpHeaders post; IHttpPost post;
if (headers.TryGetByName("content-length", out postContentLength)) if (headers.TryGetByName("content-length", out postContentLength))
{ {
post = await HttpHeaders.FromPost(streamReader, postContentLength); post = await HttpPost.Create(streamReader, postContentLength);
} }
else else
{ {
post = EmptyHttpHeaders.Empty; post = EmptyHttpPost.Empty;
} }
return post; return post;
} }
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment