Ejemplo n.º 1
0
 public override Response Handle_PATCH(Request_With_Body Request) => Render(Request);
Ejemplo n.º 2
0
        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);
                    }
                }
            }
        }
Ejemplo n.º 3
0
 public virtual Response Handle_PATCH(Request_With_Body Request) => RenderServerError(StatusCode.NOT_IMPLEMENTED);
Ejemplo n.º 4
0
 public override Response Handle_PUT(Request_With_Body Request) => Application.Route(Request);