コード例 #1
0
ファイル: HTTPServer.cs プロジェクト: yaegaki/Mochi
        private async Task ServeAsync(Socket socket, NetworkStream ns, CancellationToken cancellationToken)
        {
            var buffer = new byte[1024];
            var sr     = new NetworkStreamReader(ns, buffer);

            // RequestLine: ex) GET / HTTP/1.1
            var requestLine = await sr.ReadLineAsync(cancellationToken);

            var(isValid, method, path, version) = ParseRequestLine(requestLine);
            if (!isValid)
            {
                throw new InvalidReceiveDataException($"Invalid RequestLine: '{requestLine}'");
            }

            // Console.WriteLine($"Method:'{method}' Path:'{path}' Version:'{version}'");
            var headers = new Dictionary <string, string>();

            while (true)
            {
                var line = await sr.ReadLineAsync(cancellationToken);

                if (line.Length == 0)
                {
                    break;
                }

                string name, value;
                (isValid, name, value) = ParseHeader(line);
                if (!isValid)
                {
                    throw new InvalidReceiveDataException($"Invalid Header: '{line}'");
                }
                if (headers.ContainsKey(name))
                {
                    throw new InvalidReceiveDataException($"Duplicate Header: '{name}'");
                }

                headers.Add(name, value);
                //  Console.WriteLine($"Header:{name}, {value}");
            }

            HTTPMethod _method;

            switch (method)
            {
            case "GET":
                _method = HTTPMethod.Get;
                break;

            case "POST":
                _method = HTTPMethod.Post;
                break;

            default:
                throw new NotImplementedException($"NotImplementedMethod : '{method}'");
            }

            byte[] body = Array.Empty <byte>();
            if (_method == HTTPMethod.Post && headers.TryGetValue(KnwonHeaders.ContentLength, out string contentLengthStr))
            {
                int contentLength;
                if (!int.TryParse(contentLengthStr, out contentLength) || contentLength < 0)
                {
                    throw new InvalidReceiveDataException($"Invalid Content-Length: {contentLengthStr}");
                }

                if (contentLength > 2 * 1024 * 1024)
                {
                    throw new InvalidReceiveDataException($"Too large Content-Length: {contentLengthStr}");
                }

                // Console.WriteLine($"Content-Length:{contentLength}");
                if (contentLength > 0)
                {
                    var bodyBuffer = new byte[contentLength];
                    await sr.ReadBlockAsync(bodyBuffer, 0, contentLength, cancellationToken);

                    body = bodyBuffer;
                }
            }

            var writeBuffer = new byte[1024];
            var context     = new Context(
                socket,
                new Request(path, headers, body),
                new ResponseWriter(sr, new NetworkStreamWriter(ns, writeBuffer)),
                cancellationToken
                );

            var handleFunc = this.router.Find(_method, path);

            if (handleFunc == null)
            {
                await context.Response.WriteStatusCodeAsync(404, cancellationToken);

                await context.Response.WriteAsync("Not found.", cancellationToken);
            }
            else
            {
                await handleFunc(context);
            }

            await context.Response.FinishAsync(cancellationToken);
        }
コード例 #2
0
 public ResponseWriter(NetworkStreamReader sr, NetworkStreamWriter sw)
 {
     this.sr = sr;
     this.sw = sw;
 }