public override Response Handle_PATCH(Request_With_Body Request) => Render(Request);
protected Request ReadClientRequest(Socket ClientSocket) { byte[] buf = new byte[1024 * 1024 * 512]; int total_read = 0; int read; int search_idx = 0; bool found_query = false; byte[] query_buf = null; int headers_start_pos = 0; string query_string = null; if (ClientSocket == null) { throw new ArgumentException("ClientSocket null"); } while (total_read < buf.Length && !found_query) { try { read = ClientSocket.Receive(buf, total_read, buf.Length - total_read, SocketFlags.None); } catch (Exception e) { ErrorLog($"Receive failed: {e.Message}"); ClientSocket.Close(); throw; } if (read < 0) { WriteResponse(ClientSocket, null, RenderServerError(StatusCode.BAD_REQUEST)); throw new Exception("ClientSocket.Receive failed"); } else { total_read += read; for (int i = search_idx; i < total_read; i++) { if (buf[i] == '\r') { if (total_read > i + 1) { if (buf[i + 1] == '\n') { query_buf = new byte[i]; Array.Copy(buf, query_buf, i); headers_start_pos = i + 2; found_query = true; break; } else { search_idx = i + 2; } } else { search_idx = i; } } } } } if (!found_query) { WriteResponse(ClientSocket, null, RenderServerError(StatusCode.BAD_REQUEST)); throw new Exception("Invalid HTTP query"); } else { var match = RequestRegex.Match(Encoding.ASCII.GetString(query_buf)); if (!match.Success) { WriteResponse(ClientSocket, null, RenderServerError(StatusCode.BAD_REQUEST)); throw new Exception("Invalid HTTP query"); } else { var method = match.Groups["method"].Value; query_string = match.Groups["query_string"].Value; if (!Enum.TryParse(method, out Method requested_method)) { WriteResponse(ClientSocket, null, RenderServerError(StatusCode.BAD_REQUEST)); throw new Exception("Invalid HTTP method"); } else if (!AcceptedMethods.Contains(requested_method)) { WriteResponse(ClientSocket, null, RenderServerError(StatusCode.BAD_REQUEST)); throw new Exception("Unsupported HTTP method"); } else { int unread_bytes = total_read - headers_start_pos; Array.Copy(buf, headers_start_pos, buf, 0, unread_bytes); bool found_headers_end = false; search_idx = 0; List <string> header_strs = new List <string>(); do { for (int i = search_idx; i + 3 < unread_bytes && !found_headers_end; i++) { if (buf[i] == '\r' && buf[i + 1] == '\n') { if (i > 0) { header_strs.Add(Encoding.ASCII.GetString(buf.Take(i).ToArray())); Array.Copy(buf, i + 2, buf, 0, unread_bytes - (i + 2)); unread_bytes -= (i + 2); search_idx = 0; i = 0; if (buf[i] == '\r' && buf[i + 1] == '\n') { found_headers_end = true; Array.Copy(buf, 2, buf, 0, unread_bytes - 2); unread_bytes -= 2; break; } } else if (buf[i + 2] == '\r' && buf[i + 3] == '\n') { found_headers_end = true; Array.Copy(buf, 2, buf, 0, unread_bytes - 2); unread_bytes -= 2; break; } } else { search_idx = i + 1; } } if (!found_headers_end) { if (unread_bytes >= buf.Length) { WriteResponse(ClientSocket, null, RenderServerError(StatusCode.BAD_REQUEST)); throw new Exception("Header buffer overflow"); } else { read = ClientSocket.Receive(buf, unread_bytes, buf.Length - unread_bytes, SocketFlags.None); if (read < 0) { WriteResponse(ClientSocket, null, RenderServerError(StatusCode.BAD_REQUEST)); throw new Exception("ClientSocket.Receive failed"); } } } } while (!found_headers_end); Dictionary <string, string> headers = new Dictionary <string, string>(); foreach (var header_str in header_strs) { match = HeaderRegex.Match(header_str); if (!match.Success) { WriteResponse(ClientSocket, null, RenderServerError(StatusCode.BAD_REQUEST)); throw new Exception($"Invalid header: \"{header_str}\""); } else if (headers.ContainsKey(match.Groups["name"].Value)) { WriteResponse(ClientSocket, null, RenderServerError(StatusCode.BAD_REQUEST)); throw new Exception($"duplicate header: \"{header_str}\""); } else { headers[match.Groups["name"].Value] = match.Groups["value"].Value; } } Request request; var metadata = new RequestMetadata() { ClientIP = (ClientSocket.RemoteEndPoint as IPEndPoint).Address, Query = query_string, Headers = headers, }; byte[] body = null; if (Request_Must_Have_Body(requested_method)) { if (!headers.ContainsKey("Content-Length")) { WriteResponse(ClientSocket, null, RenderServerError(StatusCode.BAD_REQUEST)); throw new Exception("Content-Length header missing"); } int content_length; if (!int.TryParse(headers["Content-Length"], out content_length)) { WriteResponse(ClientSocket, null, RenderServerError(StatusCode.BAD_REQUEST)); throw new Exception($"Invalid Content-Length: {metadata.Headers["Content-Length"]}"); } else { body = new byte[content_length]; Array.Copy(buf, body, unread_bytes); total_read = unread_bytes; while (total_read < content_length) { read = ClientSocket.Receive(body, total_read, content_length - total_read, SocketFlags.None); if (read < 0) { WriteResponse(ClientSocket, null, RenderServerError(StatusCode.BAD_REQUEST)); throw new Exception("ClientSocket.Receive failed"); } } } } if (body != null && Request_Must_Have_Body(requested_method)) { request = new Request_With_Body(requested_method, metadata, body); } else { request = new Request(requested_method, metadata); } AccessLog(request); return(request); } } } }
public virtual Response Handle_PATCH(Request_With_Body Request) => RenderServerError(StatusCode.NOT_IMPLEMENTED);
public override Response Handle_PUT(Request_With_Body Request) => Application.Route(Request);