예제 #1
0
        /// <summary>
        /// 尝试当作http头解析,生成请求对象
        /// 如果不是http头则返回false
        /// </summary>
        /// <param name="context">上下文</param>
        /// <param name="request">请求对象</param>
        /// <param name="headerLength">请求头长度</param>
        /// <param name="contentLength">请求内容长度</param>
        /// <returns></returns>
        private static bool TryGetRequest(IContenxt context, out HttpRequest request, out int headerLength, out int contentLength)
        {
            request       = null;
            headerLength  = 0;
            contentLength = 0;
            var reader = context.StreamReader;

            // HTTP Method
            reader.Position = 0;
            var methodLength = reader.IndexOf(Space);

            if (methodLength < 0 || methodLength > MedthodMaxLength)
            {
                return(false);
            }
            var methodName = reader.ReadString(Encoding.ASCII, methodLength);

            if (MethodNames.Contains(methodName) == false)
            {
                return(false);
            }
            var httpMethod = (HttpMethod)Enum.Parse(typeof(HttpMethod), methodName, true);

            // HTTP Path
            reader.Position += 1;
            var pathLength = reader.IndexOf(Space);

            if (pathLength < 0)
            {
                return(false);
            }
            var path = reader.ReadString(Encoding.ASCII, pathLength);


            // HTTP Version
            reader.Position += 1;
            if (reader.StartWith(HttpVersion11) == false)
            {
                return(false);
            }
            reader.Position += HttpVersion11.Length;
            if (reader.StartWith(CRLF) == false)
            {
                return(false);
            }

            // HTTP Second line
            reader.Position += CRLF.Length;
            var endIndex = reader.IndexOf(DoubleCRLF);

            if (endIndex < 0)
            {
                return(false);
            }

            var httpHeader = new HttpHeader();

            headerLength = reader.Position + endIndex + DoubleCRLF.Length;


            while (reader.Position < headerLength - CRLF.Length)
            {
                var keyLength = reader.IndexOf(KvSpliter);
                if (keyLength <= 0)
                {
                    break;
                }
                var key = reader.ReadString(Encoding.ASCII, keyLength);

                reader.Position += KvSpliter.Length;
                var valueLength = reader.IndexOf(CRLF);
                if (valueLength < 0)
                {
                    break;
                }
                var value = reader.ReadString(Encoding.ASCII, valueLength);

                if (reader.StartWith(CRLF) == false)
                {
                    break;
                }
                reader.Position += CRLF.Length;
                httpHeader.Add(key, value);
            }

            if (httpMethod != HttpMethod.GET)
            {
                contentLength = httpHeader.TryGet <int>("Content-Length");
                if (reader.Length - headerLength < contentLength)
                {
                    return(true);// 数据未完整
                }
            }

            request = new HttpRequest
            {
                LocalEndPoint  = context.Session.LocalEndPoint,
                RemoteEndPoint = context.Session.RemoteEndPoint,
                HttpMethod     = httpMethod,
                Headers        = httpHeader
            };

            var scheme = context.Session.IsSecurity ? "https" : "http";
            var host   = httpHeader["Host"];

            if (string.IsNullOrEmpty(host) == true)
            {
                host = context.Session.LocalEndPoint.ToString();
            }
            request.Url   = new Uri(string.Format("{0}://{1}{2}", scheme, host, path));
            request.Path  = request.Url.AbsolutePath;
            request.Query = HttpNameValueCollection.Parse(request.Url.Query.TrimStart('?'));
            return(true);
        }
예제 #2
0
        /// <summary>
        /// 解析回复头信息
        /// </summary>
        /// <param name="streamReader">数据读取器</param>
        /// <returns></returns>
        public static HttpResponseParseResult Parse(ISessionStreamReader streamReader)
        {
            var result = new HttpResponseParseResult();

            streamReader.Position = 0;

            if (streamReader.StartWith(HttpVersion11) == false)
            {
                return(result);
            }

            var endIndex = streamReader.IndexOf(DoubleCRLF);

            if (endIndex < 0)
            {
                return(result);
            }

            streamReader.Position += HttpVersion11.Length + 1;
            var statusLength = streamReader.IndexOf(Space);

            if (statusLength < 0)
            {
                return(result);
            }
            var status = streamReader.ReadString(Encoding.ASCII, statusLength);

            streamReader.Position += 1;
            var descriptionLenth = streamReader.IndexOf(CRLF);

            if (descriptionLenth < 0)
            {
                return(result);
            }
            var description = streamReader.ReadString(Encoding.ASCII, descriptionLenth);

            streamReader.Position += CRLF.Length;
            var httpHeader   = new HttpHeader();
            var headerLength = endIndex + DoubleCRLF.Length;

            while (streamReader.Position < headerLength)
            {
                var keyLength = streamReader.IndexOf(KvSpliter);
                if (keyLength <= 0)
                {
                    break;
                }
                var key = streamReader.ReadString(Encoding.ASCII, keyLength);

                streamReader.Position += KvSpliter.Length;
                var valueLength = streamReader.IndexOf(CRLF);
                if (valueLength < 0)
                {
                    break;
                }
                var value = streamReader.ReadString(Encoding.ASCII, valueLength);

                if (streamReader.StartWith(CRLF) == false)
                {
                    break;
                }
                streamReader.Position += CRLF.Length;
                httpHeader.Add(key, value);
            }

            result.Description = description;
            result.Status      = int.Parse(status);
            result.IsHttp      = true;
            result.Header      = httpHeader;
            return(result);
        }
예제 #3
0
        /// <summary>
        /// 解析连接请求信息
        /// 如果数据未完整则返回null
        /// </summary>
        /// <param name="buffer">接收到的原始数量</param>
        /// <param name="localEndpoint">服务器的本地终结点</param>
        /// <param name="remoteEndpoint">远程端的IP和端口</param>
        /// <exception cref="HttpException"></exception>
        /// <returns></returns>
        public static HttpRequest Parse(ReceiveBuffer buffer, IPEndPoint localEndpoint, IPEndPoint remoteEndpoint)
        {
            buffer.Position = 0;
            var doubleCrlf  = Encoding.ASCII.GetBytes("\r\n\r\n");
            var headerIndex = buffer.IndexOf(doubleCrlf);

            if (headerIndex < 0)
            {
                return(null); // 数据未完整
            }

            var          headerLength = headerIndex + doubleCrlf.Length;
            var          headerString = buffer.ReadString(headerLength, Encoding.ASCII);
            const string pattern      = @"^(?<method>[^\s]+)\s(?<path>[^\s]+)\sHTTP\/1\.1\r\n" +
                                        @"((?<field_name>[^:\r\n]+):\s(?<field_value>[^\r\n]*)\r\n)+" +
                                        @"\r\n";

            var match = Regex.Match(headerString, pattern, RegexOptions.IgnoreCase);

            if (match.Success == false)
            {
                throw new HttpException(400, "请求中有语法问题,或不能满足请求");
            }

            var httpMethod    = GetHttpMethod(match.Groups["method"].Value);
            var httpHeader    = new HttpHeader(match.Groups["field_name"].Captures, match.Groups["field_value"].Captures);
            var contentLength = httpHeader.TryGet <int>("Content-Length");

            if (httpMethod == HttpMethod.POST && buffer.Length - headerLength < contentLength)
            {
                return(null); // 数据未完整
            }

            var request = new HttpRequest
            {
                LocalEndPoint  = localEndpoint,
                RemoteEndPoint = remoteEndpoint,
                HttpMethod     = httpMethod,
                Headers        = httpHeader
            };

            request.Url   = new Uri("http://localhost:" + localEndpoint.Port + match.Groups["path"].Value);
            request.Path  = request.Url.AbsolutePath;
            request.Query = new HttpNameValueCollection(HttpUtility.UrlDecode(request.Url.Query.TrimStart('?')));

            if (httpMethod == HttpMethod.GET)
            {
                request.InputStrem = new byte[0];
                request.Form       = new HttpNameValueCollection();
                request.Files      = new HttpFile[0];
            }
            else
            {
                request.InputStrem = buffer.ReadArray(contentLength);
                buffer.Position    = headerLength;
                HttpRequest.GeneratePostFormAndFiles(request, buffer);
            }

            buffer.Clear(headerLength + contentLength);
            return(request);
        }
예제 #4
0
        /// <summary>
        /// 解析连接请求信息
        /// 如果数据未完整则返回null
        /// </summary>
        /// <param name="context">上下文</param>
        /// <param name="request">http请求</param>
        /// <exception cref="HttpException"></exception>
        /// <returns></returns>
        public static bool Parse(IContenxt context, out HttpRequest request)
        {
            var headerLength = 0;

            request = null;

            if (Protocol.IsHttp(context.Buffer, out headerLength) == false)
            {
                return(false);
            }

            if (headerLength <= 0)
            {
                return(true);
            }

            context.Buffer.Position = 0;
            var          headerString = context.Buffer.ReadString(headerLength, Encoding.ASCII);
            const string pattern      = @"^(?<method>[^\s]+)\s(?<path>[^\s]+)\sHTTP\/1\.1\r\n" +
                                        @"((?<field_name>[^:\r\n]+):\s(?<field_value>[^\r\n]*)\r\n)+" +
                                        @"\r\n";

            var match = Regex.Match(headerString, pattern, RegexOptions.IgnoreCase);

            if (match.Success == false)
            {
                return(false);
            }

            var httpMethod    = GetHttpMethod(match.Groups["method"].Value);
            var httpHeader    = HttpHeader.Parse(match.Groups["field_name"].Captures, match.Groups["field_value"].Captures);
            var contentLength = httpHeader.TryGet <int>("Content-Length");

            if (httpMethod == HttpMethod.POST && context.Buffer.Length - headerLength < contentLength)
            {
                return(true); // 数据未完整
            }

            request = new HttpRequest
            {
                LocalEndPoint  = context.Session.LocalEndPoint,
                RemoteEndPoint = context.Session.RemoteEndPoint,
                HttpMethod     = httpMethod,
                Headers        = httpHeader
            };

            var scheme = context.Session.IsSecurity ? "https" : "http";
            var url    = string.Format("{0}://localhost:{1}{2}", scheme, context.Session.LocalEndPoint.Port, match.Groups["path"].Value);

            request.Url   = new Uri(url);
            request.Path  = request.Url.AbsolutePath;
            request.Query = HttpNameValueCollection.Parse(request.Url.Query.TrimStart('?'), false);

            if (httpMethod == HttpMethod.GET)
            {
                request.Body  = new byte[0];
                request.Form  = new HttpNameValueCollection();
                request.Files = new HttpFile[0];
            }
            else
            {
                request.Body            = context.Buffer.ReadArray(contentLength);
                context.Buffer.Position = headerLength;
                HttpRequest.GeneratePostFormAndFiles(request, context.Buffer);
            }

            context.Buffer.Clear(headerLength + contentLength);
            return(true);
        }
        /// <summary>
        /// 解析连接请求信息
        /// </summary>
        /// <param name="context">上下文</param>
        /// <exception cref="HttpException"></exception>
        /// <returns></returns>
        public static HttpParseResult Parse(IContenxt context)
        {
            var headerLength = 0;
            var result       = new HttpParseResult();

            context.StreamReader.Position = 0;

            result.IsHttp = HttpRequestParser.IsHttp(context.StreamReader, out headerLength);
            if (result.IsHttp == false || headerLength <= 0)
            {
                return(result);
            }

            var          headerString = context.StreamReader.ReadString(Encoding.ASCII, headerLength);
            const string pattern      = @"^(?<method>[^\s]+)\s(?<path>[^\s]+)\sHTTP\/1\.1\r\n" +
                                        @"((?<field_name>[^:\r\n]+):\s(?<field_value>[^\r\n]*)\r\n)+" +
                                        @"\r\n";

            var match = Regex.Match(headerString, pattern, RegexOptions.IgnoreCase);

            result.IsHttp = match.Success;
            if (result.IsHttp == false)
            {
                return(result);
            }

            var httpMethod    = HttpRequestParser.CastHttpMethod(match.Groups["method"].Value);
            var httpHeader    = HttpHeader.Parse(match.Groups["field_name"].Captures, match.Groups["field_value"].Captures);
            var contentLength = httpHeader.TryGet <int>("Content-Length");

            if (httpMethod == HttpMethod.POST && context.StreamReader.Length - headerLength < contentLength)
            {
                return(result);// 数据未完整
            }

            var request = new HttpRequest
            {
                LocalEndPoint  = context.Session.LocalEndPoint,
                RemoteEndPoint = context.Session.RemoteEndPoint,
                HttpMethod     = httpMethod,
                Headers        = httpHeader
            };

            var scheme = context.Session.IsSecurity ? "https" : "http";
            var host   = httpHeader["Host"];

            if (string.IsNullOrEmpty(host) == true)
            {
                host = context.Session.LocalEndPoint.ToString();
            }
            var url = string.Format("{0}://{1}{2}", scheme, host, match.Groups["path"].Value);

            request.Url   = new Uri(url);
            request.Path  = request.Url.AbsolutePath;
            request.Query = HttpNameValueCollection.Parse(request.Url.Query.TrimStart('?'));

            switch (httpMethod)
            {
            case HttpMethod.GET:
                request.Body  = new byte[0];
                request.Form  = new HttpNameValueCollection();
                request.Files = new HttpFile[0];
                break;

            default:
                request.Body = context.StreamReader.ReadArray(contentLength);
                context.StreamReader.Position = headerLength;
                HttpRequestParser.GeneratePostFormAndFiles(request, context.StreamReader);
                break;
            }

            result.Request       = request;
            result.PackageLength = headerLength + contentLength;
            return(result);
        }