/// <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); }
/// <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); }
/// <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); }
/// <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); }