public async Task<HttpResponse> Handle(HttpRequest request) { var url = request.Path; var httpMethod = request.Method; foreach (var route in RoutingMethods) { var requestPath = url.AbsolutePath; var routingMethod = ((HttpRequestMethod)route.GetCustomAttribute(typeof(HttpRequestMethod)))?.Method ?? HttpMethod.Get; var routingPath = RESTPath.Combine(Prefix, ((Route)route.GetCustomAttribute(typeof(Route))).Path); bool sameMethod = String.Equals(routingMethod.Method, httpMethod.Method); bool matchingUrl = routingPath.Matches(requestPath); if(sameMethod && matchingUrl) { var method = route; var parameters = ExtractParameters(method, routingPath, request); if (method.GetCustomAttribute(typeof(AsyncStateMachineAttribute)) != null) return await (Task<HttpResponse>)method.Invoke(this, parameters.ToArray()); else return (HttpResponse)method.Invoke(this, parameters.ToArray()); } } return NotFound($"Couldn't find a fitting method on the on matched controller '{ GetType().Name }' for path '{ url }'"); }
public static HttpRequest Read(StreamSocket socket) { HttpRequest request = new HttpRequest(); using (var input = socket.InputStream) { using (var reader = new StreamReader(input.AsStreamForRead())) { var requestHeader = reader.ReadLine(); var headerSegments = requestHeader.Split(' '); request.Method = new HttpMethod(headerSegments[0]); request.Path = new Uri(headerSegments[1], UriKind.RelativeOrAbsolute); request.Version = GetHttpVersion(headerSegments[2]); if (request.Version.Equals(HttpVersion.Http10)) request.Headers.Add("Host", $"{socket.Information.LocalAddress}:{socket.Information.LocalPort}"); ParseRequest(reader, request); if (!request.Path.IsAbsoluteUri) request.Path = new UriBuilder("http", socket.Information.LocalAddress.ToString(), int.Parse(socket.Information.LocalPort), request.Path.OriginalString).Uri; } } return request; }
private List<object> ExtractParameters(MethodInfo method, RESTPath path, HttpRequest request) { var parameters = new List<object>(); var methodParams = method.GetParameters(); var requestSegments = request.Path.AbsolutePath.Split(new char[] { '/' }, StringSplitOptions.RemoveEmptyEntries); foreach(var param in methodParams) { if (param.GetCustomAttribute(typeof(Body)) != null) parameters.Add(request.Content); else parameters.Add( requestSegments[path.Parameters.Single(p => p.Value.Equals(param.Name)).Key]); } return parameters; }
private static void ParseRequest(StreamReader reader, HttpRequest request) { bool finishedParsingHeaders = false; while(true) { string line = ""; if (!finishedParsingHeaders) line = reader.ReadLine(); else { int contentLength = request.Headers.ContainsKey("Content-Length") ? int.Parse(request.Headers["Content-Length"]) : 0; if (contentLength > 0) { char[] byteContent = new char[contentLength]; reader.ReadBlock(byteContent, 0, contentLength); line = Encoding.UTF8.GetString(Encoding.UTF8.GetBytes(byteContent)); request.Content = line; } break; } if (String.IsNullOrWhiteSpace(line)) { finishedParsingHeaders = true; } else { if (!finishedParsingHeaders) { var splitHeader = line.Split(new char[] { ':' }, 2); request.Headers.Add(splitHeader[0].Trim(), splitHeader[1].Trim()); } } } }