/// <summary> /// 生成表单和文件 /// </summary> /// <param name="request"></param> /// <param name="buffer"></param> /// <param name="boundary">边界</param> private static void GenerateMultipartFormAndFiles(HttpRequest request, ReceiveBuffer buffer, string boundary) { var doubleCrlf = Encoding.ASCII.GetBytes("\r\n\r\n"); var boundaryBytes = Encoding.ASCII.GetBytes("\r\n--" + boundary); var maxPosition = buffer.Length - Encoding.ASCII.GetBytes("--\r\n").Length; var files = new List <HttpFile>(); var form = new HttpNameValueCollection(); buffer.Position = buffer.Position + boundaryBytes.Length; while (buffer.Position < maxPosition) { var headLength = buffer.IndexOf(doubleCrlf) + doubleCrlf.Length; if (headLength < doubleCrlf.Length) { break; } var head = buffer.ReadString(headLength, Encoding.UTF8); var bodyLength = buffer.IndexOf(boundaryBytes); if (bodyLength < 0) { break; } var mHead = new MultipartHead(head); if (mHead.IsFile == true) { var stream = buffer.ReadArray(bodyLength); var file = new HttpFile(mHead, stream); files.Add(file); } else { var value = HttpUtility.UrlDecode(buffer.ReadString(bodyLength, Encoding.UTF8)); form.Add(mHead.Name, value); } buffer.Position = buffer.Position + boundaryBytes.Length; } request.Form = form; request.Files = files.ToArray(); }
/// <summary> /// 生成表单和文件 /// </summary> /// <param name="request"></param> /// <param name="buffer"></param> /// <param name="boundary">边界</param> private static void GenerateMultipartFormAndFiles(HttpRequest request, ReceiveBuffer buffer, string boundary) { var doubleCrlf = Encoding.ASCII.GetBytes("\r\n\r\n"); var boundaryBytes = Encoding.ASCII.GetBytes("\r\n--" + boundary); var maxPosition = buffer.Length - Encoding.ASCII.GetBytes("--\r\n").Length; var files = new List<HttpFile>(); var form = new HttpNameValueCollection(); buffer.Position = buffer.Position + boundaryBytes.Length; while (buffer.Position < maxPosition) { var headLength = buffer.IndexOf(doubleCrlf) + doubleCrlf.Length; if (headLength < doubleCrlf.Length) { break; } var head = buffer.ReadString(headLength, Encoding.UTF8); var bodyLength = buffer.IndexOf(boundaryBytes); if (bodyLength < 0) { break; } var mHead = new MultipartHead(head); if (mHead.IsFile == true) { var stream = buffer.ReadArray(bodyLength); var file = new HttpFile(mHead, stream); files.Add(file); } else { var value = HttpUtility.UrlDecode(buffer.ReadString(bodyLength, Encoding.UTF8)); form.Add(mHead.Name, value); } buffer.Position = buffer.Position + boundaryBytes.Length; } request.Form = form; request.Files = files.ToArray(); }
/// <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="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; }