From 5d80e3e1d159b269e6ec0f9cd2701cd4911e579c Mon Sep 17 00:00:00 2001 From: Shani Elharrar Date: Tue, 31 Dec 2013 17:14:17 +0200 Subject: [PATCH 01/14] Added rest controllers --- uhttpsharp-demo/Program.cs | 3 ++- uhttpsharp-demo/packages.config | 1 + uhttpsharp-demo/uhttpsharp.Demo.csproj | 4 ++++ uhttpsharp/HttpResponse.cs | 20 +++++++++++++++----- uhttpsharp/packages.config | 1 + uhttpsharp/uhttpsharp.csproj | 6 ++++++ 6 files changed, 29 insertions(+), 6 deletions(-) diff --git a/uhttpsharp-demo/Program.cs b/uhttpsharp-demo/Program.cs index 3839ce1..fbcd6fb 100644 --- a/uhttpsharp-demo/Program.cs +++ b/uhttpsharp-demo/Program.cs @@ -34,7 +34,8 @@ private static void Main() httpServer.Use(new TimingHandler()); httpServer.Use(new HttpRouter().With(string.Empty, new IndexHandler()) - .With("about", new AboutHandler())); + .With("about", new AboutHandler()) + .With("strings", new RestHandler(new JsonRestControllerAdapter(new SomeRestControllerOfT())))); httpServer.Use(new FileHandler()); httpServer.Use(new ErrorHandler()); diff --git a/uhttpsharp-demo/packages.config b/uhttpsharp-demo/packages.config index 3a86f25..29a8e09 100644 --- a/uhttpsharp-demo/packages.config +++ b/uhttpsharp-demo/packages.config @@ -1,4 +1,5 @@  + \ No newline at end of file diff --git a/uhttpsharp-demo/uhttpsharp.Demo.csproj b/uhttpsharp-demo/uhttpsharp.Demo.csproj index 39a6674..6c5efbe 100644 --- a/uhttpsharp-demo/uhttpsharp.Demo.csproj +++ b/uhttpsharp-demo/uhttpsharp.Demo.csproj @@ -42,6 +42,9 @@ ..\packages\log4net.2.0.3\lib\net40-full\log4net.dll + + ..\packages\Newtonsoft.Json.5.0.8\lib\net45\Newtonsoft.Json.dll + @@ -60,6 +63,7 @@ + diff --git a/uhttpsharp/HttpResponse.cs b/uhttpsharp/HttpResponse.cs index 543727e..a70a221 100644 --- a/uhttpsharp/HttpResponse.cs +++ b/uhttpsharp/HttpResponse.cs @@ -19,10 +19,12 @@ using System; using System.Collections.Generic; using System.IO; +using System.Text; using System.Threading.Tasks; namespace uhttpsharp { + public sealed class HttpResponse { private static readonly Dictionary ResponseTexts = @@ -43,15 +45,22 @@ public sealed class HttpResponse public HttpResponseCode Code { get; private set; } private Stream ContentStream { get; set; } + public HttpResponse(HttpResponseCode code, Stream content) + : this(code, "text/html; charset=utf-8", content) + { + } + public HttpResponse(HttpResponseCode code, string content) : this(code, "text/html; charset=utf-8", StringToStream(content)) { } + public HttpResponse(string contentType, Stream contentStream) : this(HttpResponseCode.Ok, contentType, contentStream) { } - private HttpResponse(HttpResponseCode code, string contentType, Stream contentStream) + + public HttpResponse(HttpResponseCode code, string contentType, Stream contentStream) { Protocol = "HTTP/1.1"; ContentType = contentType; @@ -73,7 +82,7 @@ public static HttpResponse CreateWithMessage(HttpResponseCode code, string messa "{0}

{0}


{1}", message, body)); } - private static Stream StringToStream(string content) + private static MemoryStream StringToStream(string content) { var stream = new MemoryStream(); var writer = new StreamWriter(stream); @@ -89,12 +98,13 @@ public async Task WriteResponse(StreamWriter writer) await writer.WriteLineAsync(string.Format("Content-Type: {0}", ContentType)); await writer.WriteLineAsync(string.Format("Content-Length: {0}", ContentStream.Length)); await writer.WriteLineAsync(); - + + await writer.FlushAsync(); + ContentStream.Position = 0; await ContentStream.CopyToAsync(writer.BaseStream); - ContentStream.Close(); - await writer.FlushAsync(); + await writer.BaseStream.FlushAsync(); } } } \ No newline at end of file diff --git a/uhttpsharp/packages.config b/uhttpsharp/packages.config index 3a86f25..29a8e09 100644 --- a/uhttpsharp/packages.config +++ b/uhttpsharp/packages.config @@ -1,4 +1,5 @@  + \ No newline at end of file diff --git a/uhttpsharp/uhttpsharp.csproj b/uhttpsharp/uhttpsharp.csproj index 1a7bf02..d6527c0 100644 --- a/uhttpsharp/uhttpsharp.csproj +++ b/uhttpsharp/uhttpsharp.csproj @@ -39,6 +39,9 @@ ..\packages\log4net.2.0.3\lib\net40-full\log4net.dll + + ..\packages\Newtonsoft.Json.5.0.8\lib\net45\Newtonsoft.Json.dll + @@ -52,6 +55,9 @@ Properties\AssemblyCommon.cs
+ + + From 0a9ccd5aa8fa87113bdb76750dadb91e6444ec56 Mon Sep 17 00:00:00 2001 From: Shani Elharrar Date: Tue, 31 Dec 2013 17:15:03 +0200 Subject: [PATCH 02/14] Added rest controllers --- uhttpsharp/Handlers/IRestController.cs | 45 ++++++++ uhttpsharp/Handlers/IRestControllerOft.cs | 119 ++++++++++++++++++++++ uhttpsharp/Handlers/RestHandler.cs | 80 +++++++++++++++ 3 files changed, 244 insertions(+) create mode 100644 uhttpsharp/Handlers/IRestController.cs create mode 100644 uhttpsharp/Handlers/IRestControllerOft.cs create mode 100644 uhttpsharp/Handlers/RestHandler.cs diff --git a/uhttpsharp/Handlers/IRestController.cs b/uhttpsharp/Handlers/IRestController.cs new file mode 100644 index 0000000..62c69bd --- /dev/null +++ b/uhttpsharp/Handlers/IRestController.cs @@ -0,0 +1,45 @@ +using System.Collections.Generic; +using System.Threading.Tasks; + +namespace uhttpsharp.Handlers +{ + public interface IRestController + { + + /// + /// Returns a list of object that found in the collection + /// + /// + /// + Task Get(IHttpRequest request); + + /// + /// Returns an item from the collection + /// + /// + /// + Task GetItem(IHttpRequest request); + + /// + /// Creates a new entry in the collection - new uri is returned + /// + /// + /// + Task Create(IHttpRequest request); + + /// + /// Updates an entry in the collection + /// + /// + /// + Task Upsert(IHttpRequest request); + + /// + /// Removes an entry from the collection + /// + /// + /// + Task Delete(IHttpRequest request); + + } +} \ No newline at end of file diff --git a/uhttpsharp/Handlers/IRestControllerOft.cs b/uhttpsharp/Handlers/IRestControllerOft.cs new file mode 100644 index 0000000..12778e7 --- /dev/null +++ b/uhttpsharp/Handlers/IRestControllerOft.cs @@ -0,0 +1,119 @@ +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using Newtonsoft.Json; +using Newtonsoft.Json.Linq; + +namespace uhttpsharp.Handlers +{ + public interface IRestController + { + /// + /// Returns a list of object that found in the collection + /// + /// + /// + Task> Get(IHttpRequest request); + + /// + /// Returns an item from the collection + /// + /// + /// + Task GetItem(IHttpRequest request); + + /// + /// Creates a new entry in the collection - new uri is returned + /// + /// + /// + Task Create(IHttpRequest request); + + /// + /// Updates an entry in the collection + /// + /// + /// + Task Upsert(IHttpRequest request); + + /// + /// Removes an entry from the collection + /// + /// + /// + Task Delete(IHttpRequest request); + } + + public class JsonRestControllerAdapter : IRestController + { + private readonly IRestController _controller; + + public JsonRestControllerAdapter(IRestController controller) + { + _controller = controller; + } + + private Task CreateHttpRequest(T value) + { + if (EqualityComparer.Default.Equals(value,default(T))) + { + return GenerateNotFonudResponse(); + } + + return SerializeToHttpResponse(value); + } + private static Task GenerateNotFonudResponse() + { + return Task.FromResult(new HttpResponse(HttpResponseCode.NotFound, string.Empty)); + } + private Task CreateHttpRequest(IEnumerable value) + { + if (value == null) + { + return GenerateNotFonudResponse(); + } + + var values = value.ToList(); + + if (values.Count == 0) + { + return GenerateNotFonudResponse(); + } + + return SerializeToHttpResponse(values); + } + private static Task SerializeToHttpResponse(TObj value) + { + var memoryStream = new MemoryStream(); + var writer = new JsonTextWriter(new StreamWriter(memoryStream)); + var serializer = new JsonSerializer(); + serializer.Serialize(writer, value); + writer.Flush(); + return Task.FromResult(new HttpResponse(HttpResponseCode.Ok, "application/json; charset=utf-8", memoryStream)); + } + + public async Task Get(IHttpRequest request) + { + return await CreateHttpRequest(await _controller.Get(request)); + } + public async Task GetItem(IHttpRequest request) + { + return await CreateHttpRequest(await _controller.GetItem(request)); + } + public async Task Create(IHttpRequest request) + { + return await CreateHttpRequest(await _controller.Create(request)); + } + public async Task Upsert(IHttpRequest request) + { + return await CreateHttpRequest(await _controller.Upsert(request)); + } + public async Task Delete(IHttpRequest request) + { + return await CreateHttpRequest(await _controller.Delete(request)); + } + } +} diff --git a/uhttpsharp/Handlers/RestHandler.cs b/uhttpsharp/Handlers/RestHandler.cs new file mode 100644 index 0000000..6f339d8 --- /dev/null +++ b/uhttpsharp/Handlers/RestHandler.cs @@ -0,0 +1,80 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Net.Mime; +using System.Threading.Tasks; + +namespace uhttpsharp.Handlers +{ + public class RestHandler : IHttpRequestHandler + { + + private struct RestCall + { + private readonly HttpMethods _method; + private readonly bool _entryFull; + + public RestCall(HttpMethods method, bool entryFull) + { + _method = method; + _entryFull = entryFull; + } + + public static RestCall Create(HttpMethods method, bool entryFull) + { + return new RestCall(method, entryFull); + } + + private bool Equals(RestCall other) + { + return _method == other._method && _entryFull.Equals(other._entryFull); + } + public override bool Equals(object obj) + { + if (ReferenceEquals(null, obj)) return false; + return obj is RestCall && Equals((RestCall)obj); + } + public override int GetHashCode() + { + unchecked + { + return ((int)_method*397) ^ _entryFull.GetHashCode(); + } + } + } + + private static readonly IDictionary>> RestCallHandlers = new Dictionary>>(); + + static RestHandler() + { + RestCallHandlers.Add(RestCall.Create(HttpMethods.Get, false), (c, r) => c.Get(r)); + RestCallHandlers.Add(RestCall.Create(HttpMethods.Get, true), (c, r) => c.GetItem(r)); + RestCallHandlers.Add(RestCall.Create(HttpMethods.Post, false), (c, r) => c.Create(r)); + RestCallHandlers.Add(RestCall.Create(HttpMethods.Put, true), (c, r) => c.Upsert(r)); + RestCallHandlers.Add(RestCall.Create(HttpMethods.Delete, true), (c, r) => c.Delete(r)); + } + + private readonly IRestController _controller; + public RestHandler(IRestController controller) + { + _controller = controller; + } + + public async Task Handle(IHttpRequest httpRequest, Func> next) + { + var call = new RestCall(httpRequest.Method, httpRequest.RequestParameters.Length > 1); + + Func> handler; + if (RestCallHandlers.TryGetValue(call, out handler)) + { + var value = await handler(_controller, httpRequest); + return value; + } + + return await next(); + } + } + + + +} From 307d2aa6df6fd521730c264b9832866cc500e5e0 Mon Sep 17 00:00:00 2001 From: Shani Elharrar Date: Thu, 2 Jan 2014 10:55:23 +0200 Subject: [PATCH 03/14] Remainders from last commit. --- uhttpsharp-demo/SomeRestController.cs | 74 +++++++++++++++++++++++++++ 1 file changed, 74 insertions(+) create mode 100644 uhttpsharp-demo/SomeRestController.cs diff --git a/uhttpsharp-demo/SomeRestController.cs b/uhttpsharp-demo/SomeRestController.cs new file mode 100644 index 0000000..110156a --- /dev/null +++ b/uhttpsharp-demo/SomeRestController.cs @@ -0,0 +1,74 @@ +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using Newtonsoft.Json; +using Newtonsoft.Json.Bson; +using uhttpsharp; +using uhttpsharp.Handlers; + +namespace uhttpsharpdemo +{ + + class SomeRestControllerOfT : IRestController + { + public Task> Get(IHttpRequest request) + { + return Task.FromResult(new[] {"1", "2"}.AsEnumerable()); + } + public Task GetItem(IHttpRequest request) + { + throw new NotImplementedException(); + } + public Task Create(IHttpRequest request) + { + throw new NotImplementedException(); + } + public Task Upsert(IHttpRequest request) + { + throw new NotImplementedException(); + } + public Task Delete(IHttpRequest request) + { + throw new NotImplementedException(); + } + } + + class SomeRestController : IRestController + { + + IDictionary _strings = new Dictionary() { { 1 , "Hahaha"}}; + + public Task Get(uhttpsharp.IHttpRequest request) + { + var memoryStream = new MemoryStream(); + Newtonsoft.Json.JsonWriter writer = new JsonTextWriter(new StreamWriter( memoryStream)); + + JsonSerializer.Create().Serialize(writer, _strings); + writer.Flush(); + return Task.FromResult(new HttpResponse(HttpResponseCode.Ok, "application/json; charset=utf-8", memoryStream)); + } + + public Task GetItem(uhttpsharp.IHttpRequest request) + { + throw new NotImplementedException(); + } + + public Task Create(uhttpsharp.IHttpRequest request) + { + throw new NotImplementedException(); + } + + public Task Upsert(uhttpsharp.IHttpRequest request) + { + throw new NotImplementedException(); + } + + public Task Delete(uhttpsharp.IHttpRequest request) + { + throw new NotImplementedException(); + } + } +} From 1c86ab5cd6b9c455e719732d300f5869f91357f7 Mon Sep 17 00:00:00 2001 From: Shani Elharrar Date: Thu, 9 Jan 2014 09:43:05 +0200 Subject: [PATCH 04/14] Performance enhancements --- uhttpsharp/HttpClient.cs | 6 +++--- uhttpsharp/HttpRequest.cs | 4 ++-- uhttpsharp/HttpResponse.cs | 25 ++++++++++++++++--------- uhttpsharp/HttpServer.cs | 2 +- 4 files changed, 22 insertions(+), 15 deletions(-) diff --git a/uhttpsharp/HttpClient.cs b/uhttpsharp/HttpClient.cs index 2e4d51f..b69111b 100644 --- a/uhttpsharp/HttpClient.cs +++ b/uhttpsharp/HttpClient.cs @@ -58,7 +58,7 @@ private async void Process() { while (_client.Connected) { - var request = await _requestProvider.Provide(_inputStream); + var request = await _requestProvider.Provide(_inputStream).ConfigureAwait(false); if (request != null) { @@ -67,11 +67,11 @@ private async void Process() var getResponse = BuildHandlers(request)(); - var response = await getResponse; + var response = await getResponse.ConfigureAwait(false); if (response != null) { - await response.WriteResponse(_outputStream); + await response.WriteResponse(_outputStream).ConfigureAwait(false); if (response.CloseConnection) { _client.Close(); diff --git a/uhttpsharp/HttpRequest.cs b/uhttpsharp/HttpRequest.cs index b9c2764..da6df6d 100644 --- a/uhttpsharp/HttpRequest.cs +++ b/uhttpsharp/HttpRequest.cs @@ -130,7 +130,7 @@ public class HttpRequestProvider : IHttpRequestProvider public async Task Provide(StreamReader streamReader) { // parse the http request - var request = await streamReader.ReadLineAsync(); + var request = await streamReader.ReadLineAsync().ConfigureAwait(false); if (request == null) return null; @@ -150,7 +150,7 @@ public async Task Provide(StreamReader streamReader) // get the headers string line; - while ((line = await streamReader.ReadLineAsync()) != null) + while ((line = await streamReader.ReadLineAsync().ConfigureAwait(false)) != null) { if (line.Equals(string.Empty)) break; var headerKvp = SplitHeader(line); diff --git a/uhttpsharp/HttpResponse.cs b/uhttpsharp/HttpResponse.cs index a70a221..2aad377 100644 --- a/uhttpsharp/HttpResponse.cs +++ b/uhttpsharp/HttpResponse.cs @@ -92,19 +92,26 @@ private static MemoryStream StringToStream(string content) } public async Task WriteResponse(StreamWriter writer) { - await writer.WriteLineAsync(string.Format("{0} {1} {2}", Protocol, (int) Code, ResponseTexts[(int) Code])); - await writer.WriteLineAsync(string.Format("Date: {0}", DateTime.UtcNow.ToString("R"))); - await writer.WriteLineAsync(string.Format("Connection: {0}", CloseConnection ? "close" : "Keep-Alive")); - await writer.WriteLineAsync(string.Format("Content-Type: {0}", ContentType)); - await writer.WriteLineAsync(string.Format("Content-Length: {0}", ContentStream.Length)); - await writer.WriteLineAsync(); + using (var memoryStream = new MemoryStream()) + using (var tempWriter = new StreamWriter(memoryStream)) + { + WriteHeaders(tempWriter); - await writer.FlushAsync(); + await memoryStream.CopyToAsync(writer.BaseStream).ConfigureAwait(false); + } ContentStream.Position = 0; - await ContentStream.CopyToAsync(writer.BaseStream); + await ContentStream.CopyToAsync(writer.BaseStream).ConfigureAwait(false); + } - await writer.BaseStream.FlushAsync(); + private void WriteHeaders(StreamWriter tempWriter) + { + tempWriter.WriteLine("{0} {1} {2}", Protocol, (int)Code, ResponseTexts[(int)Code]); + tempWriter.WriteLine("Date: {0}", DateTime.UtcNow.ToString("R")); + tempWriter.WriteLine("Connection: {0}", CloseConnection ? "close" : "Keep-Alive"); + tempWriter.WriteLine("Content-Type: {0}", ContentType); + tempWriter.WriteLine("Content-Length: {0}", ContentStream.Length); + tempWriter.WriteLine(); } } } \ No newline at end of file diff --git a/uhttpsharp/HttpServer.cs b/uhttpsharp/HttpServer.cs index f8e2204..877e8c3 100644 --- a/uhttpsharp/HttpServer.cs +++ b/uhttpsharp/HttpServer.cs @@ -67,7 +67,7 @@ private async void Listen() while (_isActive) { - new HttpClient(await _listener.AcceptTcpClientAsync(), _handlers, _requestProvider); + new HttpClient(await _listener.AcceptTcpClientAsync().ConfigureAwait(false), _handlers, _requestProvider); } Logger.InfoFormat("Embedded uhttpserver stopped @ {0}:{1}", IPAddress.Loopback, _port); From c9c7a2740dc2b5136433873f7e6820a040893357 Mon Sep 17 00:00:00 2001 From: Shani Elharrar Date: Thu, 9 Jan 2014 09:43:58 +0200 Subject: [PATCH 05/14] Performance enhancements to Rest and file handler. --- uhttpsharp/Handlers/FileHandler.cs | 2 +- uhttpsharp/Handlers/IRestControllerOft.cs | 15 ++++++--------- uhttpsharp/Handlers/RestHandler.cs | 4 ++-- 3 files changed, 9 insertions(+), 12 deletions(-) diff --git a/uhttpsharp/Handlers/FileHandler.cs b/uhttpsharp/Handlers/FileHandler.cs index b3ed220..98e2140 100644 --- a/uhttpsharp/Handlers/FileHandler.cs +++ b/uhttpsharp/Handlers/FileHandler.cs @@ -59,7 +59,7 @@ public async Task Handle(IHttpRequest httpRequest, System.Func SerializeToHttpResponse(TObj value) public async Task Get(IHttpRequest request) { - return await CreateHttpRequest(await _controller.Get(request)); + return await CreateHttpRequest(await _controller.Get(request).ConfigureAwait(false)).ConfigureAwait(false); } public async Task GetItem(IHttpRequest request) { - return await CreateHttpRequest(await _controller.GetItem(request)); + return await CreateHttpRequest(await _controller.GetItem(request).ConfigureAwait(false)).ConfigureAwait(false); } public async Task Create(IHttpRequest request) { - return await CreateHttpRequest(await _controller.Create(request)); + return await CreateHttpRequest(await _controller.Create(request).ConfigureAwait(false)).ConfigureAwait(false); } public async Task Upsert(IHttpRequest request) { - return await CreateHttpRequest(await _controller.Upsert(request)); + return await CreateHttpRequest(await _controller.Upsert(request).ConfigureAwait(false)).ConfigureAwait(false); } public async Task Delete(IHttpRequest request) { - return await CreateHttpRequest(await _controller.Delete(request)); + return await CreateHttpRequest(await _controller.Delete(request).ConfigureAwait(false)).ConfigureAwait(false); } } } diff --git a/uhttpsharp/Handlers/RestHandler.cs b/uhttpsharp/Handlers/RestHandler.cs index 6f339d8..7a36f1f 100644 --- a/uhttpsharp/Handlers/RestHandler.cs +++ b/uhttpsharp/Handlers/RestHandler.cs @@ -67,11 +67,11 @@ public async Task Handle(IHttpRequest httpRequest, Func> handler; if (RestCallHandlers.TryGetValue(call, out handler)) { - var value = await handler(_controller, httpRequest); + var value = await handler(_controller, httpRequest).ConfigureAwait(false); return value; } - return await next(); + return await next().ConfigureAwait(false); } } From cb79fa4ec67550ee433ab1a072564abfc291dde7 Mon Sep 17 00:00:00 2001 From: Shani Elharrar Date: Tue, 31 Dec 2013 17:15:03 +0200 Subject: [PATCH 06/14] Added rest controllers --- uhttpsharp/Handlers/IRestController.cs | 45 ++++++++ uhttpsharp/Handlers/IRestControllerOft.cs | 119 ++++++++++++++++++++++ uhttpsharp/Handlers/RestHandler.cs | 80 +++++++++++++++ 3 files changed, 244 insertions(+) create mode 100644 uhttpsharp/Handlers/IRestController.cs create mode 100644 uhttpsharp/Handlers/IRestControllerOft.cs create mode 100644 uhttpsharp/Handlers/RestHandler.cs diff --git a/uhttpsharp/Handlers/IRestController.cs b/uhttpsharp/Handlers/IRestController.cs new file mode 100644 index 0000000..62c69bd --- /dev/null +++ b/uhttpsharp/Handlers/IRestController.cs @@ -0,0 +1,45 @@ +using System.Collections.Generic; +using System.Threading.Tasks; + +namespace uhttpsharp.Handlers +{ + public interface IRestController + { + + /// + /// Returns a list of object that found in the collection + /// + /// + /// + Task Get(IHttpRequest request); + + /// + /// Returns an item from the collection + /// + /// + /// + Task GetItem(IHttpRequest request); + + /// + /// Creates a new entry in the collection - new uri is returned + /// + /// + /// + Task Create(IHttpRequest request); + + /// + /// Updates an entry in the collection + /// + /// + /// + Task Upsert(IHttpRequest request); + + /// + /// Removes an entry from the collection + /// + /// + /// + Task Delete(IHttpRequest request); + + } +} \ No newline at end of file diff --git a/uhttpsharp/Handlers/IRestControllerOft.cs b/uhttpsharp/Handlers/IRestControllerOft.cs new file mode 100644 index 0000000..12778e7 --- /dev/null +++ b/uhttpsharp/Handlers/IRestControllerOft.cs @@ -0,0 +1,119 @@ +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using Newtonsoft.Json; +using Newtonsoft.Json.Linq; + +namespace uhttpsharp.Handlers +{ + public interface IRestController + { + /// + /// Returns a list of object that found in the collection + /// + /// + /// + Task> Get(IHttpRequest request); + + /// + /// Returns an item from the collection + /// + /// + /// + Task GetItem(IHttpRequest request); + + /// + /// Creates a new entry in the collection - new uri is returned + /// + /// + /// + Task Create(IHttpRequest request); + + /// + /// Updates an entry in the collection + /// + /// + /// + Task Upsert(IHttpRequest request); + + /// + /// Removes an entry from the collection + /// + /// + /// + Task Delete(IHttpRequest request); + } + + public class JsonRestControllerAdapter : IRestController + { + private readonly IRestController _controller; + + public JsonRestControllerAdapter(IRestController controller) + { + _controller = controller; + } + + private Task CreateHttpRequest(T value) + { + if (EqualityComparer.Default.Equals(value,default(T))) + { + return GenerateNotFonudResponse(); + } + + return SerializeToHttpResponse(value); + } + private static Task GenerateNotFonudResponse() + { + return Task.FromResult(new HttpResponse(HttpResponseCode.NotFound, string.Empty)); + } + private Task CreateHttpRequest(IEnumerable value) + { + if (value == null) + { + return GenerateNotFonudResponse(); + } + + var values = value.ToList(); + + if (values.Count == 0) + { + return GenerateNotFonudResponse(); + } + + return SerializeToHttpResponse(values); + } + private static Task SerializeToHttpResponse(TObj value) + { + var memoryStream = new MemoryStream(); + var writer = new JsonTextWriter(new StreamWriter(memoryStream)); + var serializer = new JsonSerializer(); + serializer.Serialize(writer, value); + writer.Flush(); + return Task.FromResult(new HttpResponse(HttpResponseCode.Ok, "application/json; charset=utf-8", memoryStream)); + } + + public async Task Get(IHttpRequest request) + { + return await CreateHttpRequest(await _controller.Get(request)); + } + public async Task GetItem(IHttpRequest request) + { + return await CreateHttpRequest(await _controller.GetItem(request)); + } + public async Task Create(IHttpRequest request) + { + return await CreateHttpRequest(await _controller.Create(request)); + } + public async Task Upsert(IHttpRequest request) + { + return await CreateHttpRequest(await _controller.Upsert(request)); + } + public async Task Delete(IHttpRequest request) + { + return await CreateHttpRequest(await _controller.Delete(request)); + } + } +} diff --git a/uhttpsharp/Handlers/RestHandler.cs b/uhttpsharp/Handlers/RestHandler.cs new file mode 100644 index 0000000..6f339d8 --- /dev/null +++ b/uhttpsharp/Handlers/RestHandler.cs @@ -0,0 +1,80 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Net.Mime; +using System.Threading.Tasks; + +namespace uhttpsharp.Handlers +{ + public class RestHandler : IHttpRequestHandler + { + + private struct RestCall + { + private readonly HttpMethods _method; + private readonly bool _entryFull; + + public RestCall(HttpMethods method, bool entryFull) + { + _method = method; + _entryFull = entryFull; + } + + public static RestCall Create(HttpMethods method, bool entryFull) + { + return new RestCall(method, entryFull); + } + + private bool Equals(RestCall other) + { + return _method == other._method && _entryFull.Equals(other._entryFull); + } + public override bool Equals(object obj) + { + if (ReferenceEquals(null, obj)) return false; + return obj is RestCall && Equals((RestCall)obj); + } + public override int GetHashCode() + { + unchecked + { + return ((int)_method*397) ^ _entryFull.GetHashCode(); + } + } + } + + private static readonly IDictionary>> RestCallHandlers = new Dictionary>>(); + + static RestHandler() + { + RestCallHandlers.Add(RestCall.Create(HttpMethods.Get, false), (c, r) => c.Get(r)); + RestCallHandlers.Add(RestCall.Create(HttpMethods.Get, true), (c, r) => c.GetItem(r)); + RestCallHandlers.Add(RestCall.Create(HttpMethods.Post, false), (c, r) => c.Create(r)); + RestCallHandlers.Add(RestCall.Create(HttpMethods.Put, true), (c, r) => c.Upsert(r)); + RestCallHandlers.Add(RestCall.Create(HttpMethods.Delete, true), (c, r) => c.Delete(r)); + } + + private readonly IRestController _controller; + public RestHandler(IRestController controller) + { + _controller = controller; + } + + public async Task Handle(IHttpRequest httpRequest, Func> next) + { + var call = new RestCall(httpRequest.Method, httpRequest.RequestParameters.Length > 1); + + Func> handler; + if (RestCallHandlers.TryGetValue(call, out handler)) + { + var value = await handler(_controller, httpRequest); + return value; + } + + return await next(); + } + } + + + +} From 5255aa47fd1c33d7a03cde51bfcfcae38298c4fc Mon Sep 17 00:00:00 2001 From: Shani Elharrar Date: Thu, 2 Jan 2014 10:55:23 +0200 Subject: [PATCH 07/14] Remainders from last commit. --- uhttpsharp-demo/SomeRestController.cs | 74 +++++++++++++++++++++++++++ 1 file changed, 74 insertions(+) create mode 100644 uhttpsharp-demo/SomeRestController.cs diff --git a/uhttpsharp-demo/SomeRestController.cs b/uhttpsharp-demo/SomeRestController.cs new file mode 100644 index 0000000..110156a --- /dev/null +++ b/uhttpsharp-demo/SomeRestController.cs @@ -0,0 +1,74 @@ +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using Newtonsoft.Json; +using Newtonsoft.Json.Bson; +using uhttpsharp; +using uhttpsharp.Handlers; + +namespace uhttpsharpdemo +{ + + class SomeRestControllerOfT : IRestController + { + public Task> Get(IHttpRequest request) + { + return Task.FromResult(new[] {"1", "2"}.AsEnumerable()); + } + public Task GetItem(IHttpRequest request) + { + throw new NotImplementedException(); + } + public Task Create(IHttpRequest request) + { + throw new NotImplementedException(); + } + public Task Upsert(IHttpRequest request) + { + throw new NotImplementedException(); + } + public Task Delete(IHttpRequest request) + { + throw new NotImplementedException(); + } + } + + class SomeRestController : IRestController + { + + IDictionary _strings = new Dictionary() { { 1 , "Hahaha"}}; + + public Task Get(uhttpsharp.IHttpRequest request) + { + var memoryStream = new MemoryStream(); + Newtonsoft.Json.JsonWriter writer = new JsonTextWriter(new StreamWriter( memoryStream)); + + JsonSerializer.Create().Serialize(writer, _strings); + writer.Flush(); + return Task.FromResult(new HttpResponse(HttpResponseCode.Ok, "application/json; charset=utf-8", memoryStream)); + } + + public Task GetItem(uhttpsharp.IHttpRequest request) + { + throw new NotImplementedException(); + } + + public Task Create(uhttpsharp.IHttpRequest request) + { + throw new NotImplementedException(); + } + + public Task Upsert(uhttpsharp.IHttpRequest request) + { + throw new NotImplementedException(); + } + + public Task Delete(uhttpsharp.IHttpRequest request) + { + throw new NotImplementedException(); + } + } +} From 75d644b8f4dfb935bfb164a9a2cd26ab0d14630d Mon Sep 17 00:00:00 2001 From: Shani Elharrar Date: Thu, 9 Jan 2014 09:43:05 +0200 Subject: [PATCH 08/14] Performance enhancements --- uhttpsharp/HttpServer.cs | 1 - 1 file changed, 1 deletion(-) diff --git a/uhttpsharp/HttpServer.cs b/uhttpsharp/HttpServer.cs index 635b15d..888b26e 100644 --- a/uhttpsharp/HttpServer.cs +++ b/uhttpsharp/HttpServer.cs @@ -78,7 +78,6 @@ private async void Listen(IHttpListener listener) { Logger.Warn("Error while getting client", e); } - } Logger.InfoFormat("Embedded uhttpserver stopped."); From f440ada57d3fd13d0ffc8596302073bce7e8110d Mon Sep 17 00:00:00 2001 From: Shani Elharrar Date: Thu, 9 Jan 2014 09:43:58 +0200 Subject: [PATCH 09/14] Performance enhancements to Rest and file handler. --- uhttpsharp/Handlers/FileHandler.cs | 1 - uhttpsharp/Handlers/IRestControllerOft.cs | 15 ++++++--------- uhttpsharp/Handlers/RestHandler.cs | 4 ++-- 3 files changed, 8 insertions(+), 12 deletions(-) diff --git a/uhttpsharp/Handlers/FileHandler.cs b/uhttpsharp/Handlers/FileHandler.cs index dca1253..ea73337 100644 --- a/uhttpsharp/Handlers/FileHandler.cs +++ b/uhttpsharp/Handlers/FileHandler.cs @@ -65,7 +65,6 @@ public async Task Handle(IHttpContext context, System.Func next) return; } - context.Response = new HttpResponse(GetContentType(path), File.OpenRead(path), context.Request.Headers.KeepAliveConnection()); } } diff --git a/uhttpsharp/Handlers/IRestControllerOft.cs b/uhttpsharp/Handlers/IRestControllerOft.cs index 12778e7..8dbe1cb 100644 --- a/uhttpsharp/Handlers/IRestControllerOft.cs +++ b/uhttpsharp/Handlers/IRestControllerOft.cs @@ -1,11 +1,8 @@ -using System; -using System.Collections.Generic; +using System.Collections.Generic; using System.IO; using System.Linq; -using System.Text; using System.Threading.Tasks; using Newtonsoft.Json; -using Newtonsoft.Json.Linq; namespace uhttpsharp.Handlers { @@ -97,23 +94,23 @@ private static Task SerializeToHttpResponse(TObj value) public async Task Get(IHttpRequest request) { - return await CreateHttpRequest(await _controller.Get(request)); + return await CreateHttpRequest(await _controller.Get(request).ConfigureAwait(false)).ConfigureAwait(false); } public async Task GetItem(IHttpRequest request) { - return await CreateHttpRequest(await _controller.GetItem(request)); + return await CreateHttpRequest(await _controller.GetItem(request).ConfigureAwait(false)).ConfigureAwait(false); } public async Task Create(IHttpRequest request) { - return await CreateHttpRequest(await _controller.Create(request)); + return await CreateHttpRequest(await _controller.Create(request).ConfigureAwait(false)).ConfigureAwait(false); } public async Task Upsert(IHttpRequest request) { - return await CreateHttpRequest(await _controller.Upsert(request)); + return await CreateHttpRequest(await _controller.Upsert(request).ConfigureAwait(false)).ConfigureAwait(false); } public async Task Delete(IHttpRequest request) { - return await CreateHttpRequest(await _controller.Delete(request)); + return await CreateHttpRequest(await _controller.Delete(request).ConfigureAwait(false)).ConfigureAwait(false); } } } diff --git a/uhttpsharp/Handlers/RestHandler.cs b/uhttpsharp/Handlers/RestHandler.cs index 6f339d8..7a36f1f 100644 --- a/uhttpsharp/Handlers/RestHandler.cs +++ b/uhttpsharp/Handlers/RestHandler.cs @@ -67,11 +67,11 @@ public async Task Handle(IHttpRequest httpRequest, Func> handler; if (RestCallHandlers.TryGetValue(call, out handler)) { - var value = await handler(_controller, httpRequest); + var value = await handler(_controller, httpRequest).ConfigureAwait(false); return value; } - return await next(); + return await next().ConfigureAwait(false); } } From 1586afe58ac33f2e5378586a75212d1d933b6ba0 Mon Sep 17 00:00:00 2001 From: Shani Elharrar Date: Tue, 21 Jan 2014 09:51:36 +0200 Subject: [PATCH 10/14] ignoring performance analysis using .gitignore --- .gitignore | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.gitignore b/.gitignore index 608a7b3..0dad694 100644 --- a/.gitignore +++ b/.gitignore @@ -4,3 +4,5 @@ /packages/* */bin/* */obj/* +*.psess +*.vsp \ No newline at end of file From 8e83bfc95853492759438f419b796c66a5386abc Mon Sep 17 00:00:00 2001 From: Shani Elharrar Date: Tue, 21 Jan 2014 09:53:00 +0200 Subject: [PATCH 11/14] Ignore bad http calls. --- uhttpsharp/HttpClient.cs | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/uhttpsharp/HttpClient.cs b/uhttpsharp/HttpClient.cs index 93eb25c..7e0b16a 100644 --- a/uhttpsharp/HttpClient.cs +++ b/uhttpsharp/HttpClient.cs @@ -101,6 +101,12 @@ private async void Process() { // Socket exceptions on read will be re-thrown as IOException by BufferedStream } + catch (Exception e) + { + // Hate people who make bad calls. + Logger.Warn(string.Format("Error while serving : {0} : {1}{2}", _remoteEndPoint, Environment.NewLine, e)); + _client.Close(); + } Logger.InfoFormat("Lost Client {0}", _remoteEndPoint); } From 6d22aaf6f871dac11e064ccbf8b124217bdfe7e0 Mon Sep 17 00:00:00 2001 From: Shani Elharrar Date: Tue, 21 Jan 2014 09:53:13 +0200 Subject: [PATCH 12/14] Simplified rest c ontrollers. --- uhttpsharp-demo/Program.cs | 3 +- uhttpsharp-demo/SomeRestController.cs | 29 +----- uhttpsharp-demo/uhttpsharp.Demo.csproj | 4 + uhttpsharp/Handlers/IRestController.cs | 16 ++- uhttpsharp/Handlers/IRestControllerOft.cs | 116 ---------------------- uhttpsharp/Handlers/RestHandler.cs | 26 ++--- uhttpsharp/uhttpsharp.csproj | 3 +- 7 files changed, 29 insertions(+), 168 deletions(-) delete mode 100644 uhttpsharp/Handlers/IRestControllerOft.cs diff --git a/uhttpsharp-demo/Program.cs b/uhttpsharp-demo/Program.cs index e9ed891..d8917f3 100644 --- a/uhttpsharp-demo/Program.cs +++ b/uhttpsharp-demo/Program.cs @@ -41,11 +41,12 @@ private static void Main() httpServer.Use(new TcpListenerAdapter(new TcpListener(IPAddress.Loopback, 80))); //httpServer.Use(new ListenerSslDecorator(new TcpListenerAdapter(new TcpListener(IPAddress.Loopback, 443)), serverCertificate)); + httpServer.Use(new ExceptionHandler()); httpServer.Use(new TimingHandler()); httpServer.Use(new HttpRouter().With(string.Empty, new IndexHandler()) .With("about", new AboutHandler()) - .With("strings", new RestHandler(new JsonRestControllerAdapter(new SomeRestControllerOfT())))); + .With("strings", new RestHandler(new StringsRestController(), new JsonResponseProvider()))); httpServer.Use(new FileHandler()); httpServer.Use(new ErrorHandler()); diff --git a/uhttpsharp-demo/SomeRestController.cs b/uhttpsharp-demo/SomeRestController.cs index 4a1d7a1..674c23d 100644 --- a/uhttpsharp-demo/SomeRestController.cs +++ b/uhttpsharp-demo/SomeRestController.cs @@ -1,42 +1,15 @@ using System; using System.Collections.Generic; using System.IO; -using System.Linq; using System.Text; using System.Threading.Tasks; using Newtonsoft.Json; using Newtonsoft.Json.Bson; using uhttpsharp; -using uhttpsharp.Handlers; namespace uhttpsharpdemo { - - class SomeRestControllerOfT : IRestController - { - public Task> Get(IHttpRequest request) - { - return Task.FromResult(new[] {"1", "2"}.AsEnumerable()); - } - public Task GetItem(IHttpRequest request) - { - throw new NotImplementedException(); - } - public Task Create(IHttpRequest request) - { - throw new NotImplementedException(); - } - public Task Upsert(IHttpRequest request) - { - throw new NotImplementedException(); - } - public Task Delete(IHttpRequest request) - { - throw new NotImplementedException(); - } - } - - class SomeRestController : IRestController + class SomeRestController { IDictionary _strings = new Dictionary() { { 1 , "Hahaha"}}; diff --git a/uhttpsharp-demo/uhttpsharp.Demo.csproj b/uhttpsharp-demo/uhttpsharp.Demo.csproj index 6c5efbe..42eb3dc 100644 --- a/uhttpsharp-demo/uhttpsharp.Demo.csproj +++ b/uhttpsharp-demo/uhttpsharp.Demo.csproj @@ -47,6 +47,7 @@
+ @@ -59,11 +60,14 @@ + + + diff --git a/uhttpsharp/Handlers/IRestController.cs b/uhttpsharp/Handlers/IRestController.cs index 62c69bd..ff5ad90 100644 --- a/uhttpsharp/Handlers/IRestController.cs +++ b/uhttpsharp/Handlers/IRestController.cs @@ -3,43 +3,41 @@ namespace uhttpsharp.Handlers { - public interface IRestController + public interface IRestController { - /// /// Returns a list of object that found in the collection /// /// /// - Task Get(IHttpRequest request); + Task> Get(IHttpRequest request); /// /// Returns an item from the collection /// /// /// - Task GetItem(IHttpRequest request); + Task GetItem(IHttpRequest request); /// /// Creates a new entry in the collection - new uri is returned /// /// /// - Task Create(IHttpRequest request); + Task Create(IHttpRequest request); /// /// Updates an entry in the collection /// /// /// - Task Upsert(IHttpRequest request); + Task Upsert(IHttpRequest request); /// /// Removes an entry from the collection /// /// /// - Task Delete(IHttpRequest request); - + Task Delete(IHttpRequest request); } -} \ No newline at end of file +} diff --git a/uhttpsharp/Handlers/IRestControllerOft.cs b/uhttpsharp/Handlers/IRestControllerOft.cs deleted file mode 100644 index 469ab38..0000000 --- a/uhttpsharp/Handlers/IRestControllerOft.cs +++ /dev/null @@ -1,116 +0,0 @@ -using System.Collections.Generic; -using System.IO; -using System.Linq; -using System.Threading.Tasks; -using Newtonsoft.Json; - -namespace uhttpsharp.Handlers -{ - public interface IRestController - { - /// - /// Returns a list of object that found in the collection - /// - /// - /// - Task> Get(IHttpRequest request); - - /// - /// Returns an item from the collection - /// - /// - /// - Task GetItem(IHttpRequest request); - - /// - /// Creates a new entry in the collection - new uri is returned - /// - /// - /// - Task Create(IHttpRequest request); - - /// - /// Updates an entry in the collection - /// - /// - /// - Task Upsert(IHttpRequest request); - - /// - /// Removes an entry from the collection - /// - /// - /// - Task Delete(IHttpRequest request); - } - - public class JsonRestControllerAdapter : IRestController - { - private readonly IRestController _controller; - - public JsonRestControllerAdapter(IRestController controller) - { - _controller = controller; - } - - private Task CreateHttpRequest(T value) - { - if (EqualityComparer.Default.Equals(value,default(T))) - { - return GenerateNotFonudResponse(); - } - - return SerializeToHttpResponse(value); - } - private static Task GenerateNotFonudResponse() - { - return Task.FromResult(new HttpResponse(HttpResponseCode.NotFound, string.Empty, false)); - } - private Task CreateHttpRequest(IEnumerable value) - { - if (value == null) - { - return GenerateNotFonudResponse(); - } - - var values = value.ToList(); - - if (values.Count == 0) - { - return GenerateNotFonudResponse(); - } - - return SerializeToHttpResponse(values); - } - private static Task SerializeToHttpResponse(TObj value) - { - var memoryStream = new MemoryStream(); - var writer = new JsonTextWriter(new StreamWriter(memoryStream)); - var serializer = new JsonSerializer(); - serializer.Serialize(writer, value); - writer.Flush(); - return Task.FromResult(new HttpResponse(HttpResponseCode.Ok, "application/json; charset=utf-8", memoryStream, true)); - } - - public async Task Get(IHttpRequest request) - { - return await CreateHttpRequest(await _controller.Get(request).ConfigureAwait(false)).ConfigureAwait(false); - } - public async Task GetItem(IHttpRequest request) - { - return await CreateHttpRequest(await _controller.GetItem(request).ConfigureAwait(false)).ConfigureAwait(false); - } - public async Task Create(IHttpRequest request) - { - return await CreateHttpRequest(await _controller.Create(request).ConfigureAwait(false)).ConfigureAwait(false); - } - public async Task Upsert(IHttpRequest request) - { - return await CreateHttpRequest(await _controller.Upsert(request).ConfigureAwait(false)).ConfigureAwait(false); - } - public async Task Delete(IHttpRequest request) - { - return await CreateHttpRequest(await _controller.Delete(request).ConfigureAwait(false)).ConfigureAwait(false); - } - } -} diff --git a/uhttpsharp/Handlers/RestHandler.cs b/uhttpsharp/Handlers/RestHandler.cs index 57ffce8..b25a665 100644 --- a/uhttpsharp/Handlers/RestHandler.cs +++ b/uhttpsharp/Handlers/RestHandler.cs @@ -1,12 +1,10 @@ using System; using System.Collections.Generic; -using System.Linq; -using System.Net.Mime; using System.Threading.Tasks; namespace uhttpsharp.Handlers { - public class RestHandler : IHttpRequestHandler + public class RestHandler : IHttpRequestHandler { private struct RestCall @@ -43,21 +41,23 @@ public override int GetHashCode() } } - private static readonly IDictionary>> RestCallHandlers = new Dictionary>>(); + private static readonly IDictionary, IHttpRequest, Task>> RestCallHandlers = new Dictionary, IHttpRequest, Task>>(); static RestHandler() { - RestCallHandlers.Add(RestCall.Create(HttpMethods.Get, false), (c, r) => c.Get(r)); - RestCallHandlers.Add(RestCall.Create(HttpMethods.Get, true), (c, r) => c.GetItem(r)); - RestCallHandlers.Add(RestCall.Create(HttpMethods.Post, false), (c, r) => c.Create(r)); - RestCallHandlers.Add(RestCall.Create(HttpMethods.Put, true), (c, r) => c.Upsert(r)); - RestCallHandlers.Add(RestCall.Create(HttpMethods.Delete, true), (c, r) => c.Delete(r)); + RestCallHandlers.Add(RestCall.Create(HttpMethods.Get, false), async (c, r) => (object) (await c.Get(r))); + RestCallHandlers.Add(RestCall.Create(HttpMethods.Get, true), async (c, r) => (object) (await c.GetItem(r))); + RestCallHandlers.Add(RestCall.Create(HttpMethods.Post, false), async (c, r) => (object) (await c.Create(r))); + RestCallHandlers.Add(RestCall.Create(HttpMethods.Put, true), async (c, r) => (object) (await c.Upsert(r))); + RestCallHandlers.Add(RestCall.Create(HttpMethods.Delete, true), async (c, r) => (object) (await c.Delete(r))); } - private readonly IRestController _controller; - public RestHandler(IRestController controller) + private readonly IRestController _controller; + private readonly IResponseProvider _responseProvider; + public RestHandler(IRestController controller, IResponseProvider responseProvider) { _controller = controller; + _responseProvider = responseProvider; } public async Task Handle(IHttpContext httpContext, Func next) @@ -66,11 +66,11 @@ public async Task Handle(IHttpContext httpContext, Func next) var call = new RestCall(httpRequest.Method, httpRequest.RequestParameters.Length > 1); - Func> handler; + Func, IHttpRequest, Task> handler; if (RestCallHandlers.TryGetValue(call, out handler)) { var value = await handler(_controller, httpRequest).ConfigureAwait(false); - httpContext.Response = value; + httpContext.Response = await _responseProvider.Provide(value); return; } diff --git a/uhttpsharp/uhttpsharp.csproj b/uhttpsharp/uhttpsharp.csproj index cffeb46..610d9e7 100644 --- a/uhttpsharp/uhttpsharp.csproj +++ b/uhttpsharp/uhttpsharp.csproj @@ -57,8 +57,9 @@ + - + From d3c03bace77e1e2c38f207ac97ae5b3b039e88bb Mon Sep 17 00:00:00 2001 From: Shani Elharrar Date: Tue, 21 Jan 2014 09:53:44 +0200 Subject: [PATCH 13/14] Remainders from last check-in. --- uhttpsharp-demo/Handlers/ExceptionHandler.cs | 25 ++++++++ uhttpsharp-demo/HttpException.cs | 24 ++++++++ uhttpsharp-demo/StringsRestController.cs | 64 ++++++++++++++++++++ uhttpsharp/Handlers/IResponseProvider.cs | 11 ++++ uhttpsharp/Handlers/JsonResponseProvider.cs | 19 ++++++ 5 files changed, 143 insertions(+) create mode 100644 uhttpsharp-demo/Handlers/ExceptionHandler.cs create mode 100644 uhttpsharp-demo/HttpException.cs create mode 100644 uhttpsharp-demo/StringsRestController.cs create mode 100644 uhttpsharp/Handlers/IResponseProvider.cs create mode 100644 uhttpsharp/Handlers/JsonResponseProvider.cs diff --git a/uhttpsharp-demo/Handlers/ExceptionHandler.cs b/uhttpsharp-demo/Handlers/ExceptionHandler.cs new file mode 100644 index 0000000..2391bce --- /dev/null +++ b/uhttpsharp-demo/Handlers/ExceptionHandler.cs @@ -0,0 +1,25 @@ +using System; +using System.Threading.Tasks; +using uhttpsharp; + +namespace uhttpsharpdemo.Handlers +{ + public class ExceptionHandler : IHttpRequestHandler + { + public async Task Handle(IHttpContext context, Func next) + { + try + { + await next(); + } + catch (HttpException e) + { + context.Response = new HttpResponse(e.ResponseCode, "Error while handling your request. " + e.Message, false); + } + catch (Exception e) + { + context.Response = new HttpResponse(HttpResponseCode.InternalServerError, "Error while handling your request. " + e, false); + } + } + } +} \ No newline at end of file diff --git a/uhttpsharp-demo/HttpException.cs b/uhttpsharp-demo/HttpException.cs new file mode 100644 index 0000000..0fb955a --- /dev/null +++ b/uhttpsharp-demo/HttpException.cs @@ -0,0 +1,24 @@ +using System; +using uhttpsharp; + +namespace uhttpsharpdemo +{ + public class HttpException : Exception + { + private readonly HttpResponseCode _responseCode; + + public HttpResponseCode ResponseCode + { + get { return _responseCode; } + } + + public HttpException(HttpResponseCode responseCode) + { + _responseCode = responseCode; + } + public HttpException(HttpResponseCode responseCode, string message) : base(message) + { + _responseCode = responseCode; + } + } +} diff --git a/uhttpsharp-demo/StringsRestController.cs b/uhttpsharp-demo/StringsRestController.cs new file mode 100644 index 0000000..1d15cb5 --- /dev/null +++ b/uhttpsharp-demo/StringsRestController.cs @@ -0,0 +1,64 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Threading.Tasks; +using System.Web; +using uhttpsharp; +using uhttpsharp.Handlers; + +namespace uhttpsharpdemo +{ + class StringsRestController : IRestController + { + private readonly ICollection _collection = new HashSet(); + + public Task> Get(IHttpRequest request) + { + return Task.FromResult>(_collection); + } + public Task GetItem(IHttpRequest request) + { + var id = GetId(request); + + if (_collection.Contains(id)) + { + return Task.FromResult(id); + } + + throw GetNotFoundException(); + } + private static string GetId(IHttpRequest request) + { + var id = request.RequestParameters[1]; + + return id; + } + public Task Create(IHttpRequest request) + { + var id = GetId(request); + + _collection.Add(id); + + return Task.FromResult(id); + } + public Task Upsert(IHttpRequest request) + { + return Create(request); + } + public Task Delete(IHttpRequest request) + { + var id = GetId(request); + + if (_collection.Remove(id)) + { + return Task.FromResult(id); + } + + throw GetNotFoundException(); + } + private static Exception GetNotFoundException() + { + return new HttpException(HttpResponseCode.NotFound, "The resource you've looked for is not found"); + } + } +} \ No newline at end of file diff --git a/uhttpsharp/Handlers/IResponseProvider.cs b/uhttpsharp/Handlers/IResponseProvider.cs new file mode 100644 index 0000000..215c458 --- /dev/null +++ b/uhttpsharp/Handlers/IResponseProvider.cs @@ -0,0 +1,11 @@ +using System.Threading.Tasks; + +namespace uhttpsharp.Handlers +{ + public interface IResponseProvider + { + + Task Provide(object value); + + } +} \ No newline at end of file diff --git a/uhttpsharp/Handlers/JsonResponseProvider.cs b/uhttpsharp/Handlers/JsonResponseProvider.cs new file mode 100644 index 0000000..475b3c0 --- /dev/null +++ b/uhttpsharp/Handlers/JsonResponseProvider.cs @@ -0,0 +1,19 @@ +using System.IO; +using System.Threading.Tasks; +using Newtonsoft.Json; + +namespace uhttpsharp.Handlers +{ + public class JsonResponseProvider : IResponseProvider + { + public Task Provide(object value) + { + var memoryStream = new MemoryStream(); + var writer = new JsonTextWriter(new StreamWriter(memoryStream)); + var serializer = new JsonSerializer(); + serializer.Serialize(writer, value); + writer.Flush(); + return Task.FromResult(new HttpResponse(HttpResponseCode.Ok, "application/json; charset=utf-8", memoryStream, true)); + } + } +} \ No newline at end of file From 6a83fd7a515d20de8acca1ff5f2fb4b77edb4760 Mon Sep 17 00:00:00 2001 From: Shani Elharrar Date: Tue, 21 Jan 2014 09:54:18 +0200 Subject: [PATCH 14/14] Modified Readme. --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 2d725ae..cdc84e3 100644 --- a/README.md +++ b/README.md @@ -53,7 +53,7 @@ Usage : More modifications will be made to make it more "user friendly" out of the box : -* [RESTful](http://en.wikipedia.org/wiki/Representational_state_transfer) controllers +* ~~[RESTful](http://en.wikipedia.org/wiki/Representational_state_transfer) controllers~~ (Done) * Caching support * NuGet package * ~~Ssl Support~~ (Done!)