void ParseRequest(byte[] buffer, int startBufferOffset, int posOfReqEnd) { _isWebSocket = false; _next.PrepareForRequest(); posOfReqEnd -= 2; _responseHeaders.Clear(); _webSocketReqCondition = WebSocketReqConditions.Start; if (_cancellation.IsCancellationRequested) { _cancellation = new CancellationTokenSource(); } _responseIsChunked = false; _responseContentLength = ulong.MaxValue; var pos = startBufferOffset; _isMethodHead = false; _requestMethod = ParseHttpMethod(buffer, ref pos); _requestScheme = _isSsl ? "https" : "http"; string reqHost; ParseHttpPath(buffer, ref pos, out _requestPath, out _requestQueryString, ref _requestScheme, out reqHost); ParseHttpProtocol(buffer, ref pos, out _requestProtocol); if (!SkipCrLf(buffer, ref pos)) { throw new Exception("Request line does not end with CRLF"); } _isKeepAlive = !_isHttp10; ShouldSend100Continue = false; RequestContentLength = 0; RequestIsChunked = false; if (!ParseHttpHeaders(buffer, pos, posOfReqEnd)) { throw new Exception("Request headers cannot be parsed"); } }
string ParseHttpMethod(byte[] buffer, ref int pos) { var p = pos; var start = p; switch (buffer[p]) { case (byte)'G': if (buffer[p + 1] == 'E' && buffer[p + 2] == 'T' && buffer[p + 3] == ' ') { pos = p + 4; _webSocketReqCondition |= WebSocketReqConditions.GetMethod; return("GET"); } break; case (byte)'P': if (buffer[p + 1] == 'O' && buffer[p + 2] == 'S' && buffer[p + 3] == 'T' && buffer[p + 4] == ' ') { pos = p + 5; return("POST"); } if (buffer[p + 1] == 'U' && buffer[p + 2] == 'T' && buffer[p + 3] == ' ') { pos = p + 4; return("PUT"); } break; case (byte)'H': if (buffer[p + 1] == 'E' && buffer[p + 2] == 'A' && buffer[p + 3] == 'D' && buffer[p + 4] == ' ') { pos = p + 5; _isMethodHead = true; return("HEAD"); } break; case (byte)'D': if (buffer[p + 1] == 'E' && buffer[p + 2] == 'L' && buffer[p + 3] == 'E' && buffer[p + 4] == 'T' && buffer[p + 5] == 'E' && buffer[p + 6] == ' ') { pos = p + 7; return("DELETE"); } break; case (byte)'T': if (buffer[p + 1] == 'R' && buffer[p + 2] == 'A' && buffer[p + 3] == 'C' && buffer[p + 4] == 'E' && buffer[p + 5] == ' ') { pos = p + 6; return("TRACE"); } break; case (byte)'O': if (buffer[p + 1] == 'P' && buffer[p + 2] == 'T' && buffer[p + 3] == 'I' && buffer[p + 4] == 'O' && buffer[p + 5] == 'N' && buffer[p + 6] == 'S' && buffer[p + 7] == ' ') { pos = p + 8; return("OPTIONS"); } break; case (byte)' ': { pos = p + 1; return(""); } case 13: { return(""); } } p++; while (true) { var b = buffer[p]; if (b == (byte)' ') { pos = p + 1; break; } if (b == 13) { pos = p; break; } p++; } return(StringFromLatin1(buffer, start, p)); }
void ProcessRequestHeader(string name, string value) { if (name.Equals("Connection", StringComparison.OrdinalIgnoreCase)) { if (_isHttp10) { if (value.Equals("Keep-Alive", StringComparison.OrdinalIgnoreCase)) { _isKeepAlive = true; } } else { if (value.Equals("Close", StringComparison.OrdinalIgnoreCase)) { _isKeepAlive = false; } else if (value.IndexOf("Upgrade", StringComparison.OrdinalIgnoreCase) >= 0) { _webSocketReqCondition |= WebSocketReqConditions.ConnectionUpgrade; } } } else if (name.Equals("Expect", StringComparison.OrdinalIgnoreCase)) { if (value.Equals("100-Continue", StringComparison.OrdinalIgnoreCase)) { ShouldSend100Continue = true; } } else if (name.Equals("Content-Length", StringComparison.OrdinalIgnoreCase)) { if (!ulong.TryParse(value, out RequestContentLength)) { throw new InvalidDataException(string.Format("Wrong request content length: {0}", value)); } } else if (name.Equals("Transfer-Encoding", StringComparison.OrdinalIgnoreCase)) { if (value.Equals("chunked", StringComparison.OrdinalIgnoreCase)) { RequestIsChunked = true; RequestContentLength = ulong.MaxValue; } } else if (name.Equals("Upgrade", StringComparison.OrdinalIgnoreCase)) { if (value.Equals("websocket", StringComparison.OrdinalIgnoreCase)) { _webSocketReqCondition |= WebSocketReqConditions.UpgradeWebSocket; } } else if (name.Equals("Sec-WebSocket-Version", StringComparison.OrdinalIgnoreCase)) { if (value == "13") { _webSocketReqCondition |= WebSocketReqConditions.Version13; } } else if (name.Equals("Sec-WebSocket-Key", StringComparison.OrdinalIgnoreCase)) { _webSocketReqCondition |= WebSocketReqConditions.ValidKey; _webSocketKey = value; } _next.AddRequestHeader(name, value); }
string ParseHttpMethod(byte[] buffer, ref int pos) { var p = pos; var start = p; switch (buffer[p]) { case (byte)'G': if (buffer[p + 1] == 'E' && buffer[p + 2] == 'T' && buffer[p + 3] == ' ') { pos = p + 4; _webSocketReqCondition |= WebSocketReqConditions.GetMethod; return "GET"; } break; case (byte)'P': if (buffer[p + 1] == 'O' && buffer[p + 2] == 'S' && buffer[p + 3] == 'T' && buffer[p + 4] == ' ') { pos = p + 5; return "POST"; } if (buffer[p + 1] == 'U' && buffer[p + 2] == 'T' && buffer[p + 3] == ' ') { pos = p + 4; return "PUT"; } break; case (byte)'H': if (buffer[p + 1] == 'E' && buffer[p + 2] == 'A' && buffer[p + 3] == 'D' && buffer[p + 4] == ' ') { pos = p + 5; _isMethodHead = true; return "HEAD"; } break; case (byte)'D': if (buffer[p + 1] == 'E' && buffer[p + 2] == 'L' && buffer[p + 3] == 'E' && buffer[p + 4] == 'T' && buffer[p + 5] == 'E' && buffer[p + 6] == ' ') { pos = p + 7; return "DELETE"; } break; case (byte)'T': if (buffer[p + 1] == 'R' && buffer[p + 2] == 'A' && buffer[p + 3] == 'C' && buffer[p + 4] == 'E' && buffer[p + 5] == ' ') { pos = p + 6; return "TRACE"; } break; case (byte)'O': if (buffer[p + 1] == 'P' && buffer[p + 2] == 'T' && buffer[p + 3] == 'I' && buffer[p + 4] == 'O' && buffer[p + 5] == 'N' && buffer[p + 6] == 'S' && buffer[p + 7] == ' ') { pos = p + 8; return "OPTIONS"; } break; case (byte)' ': { pos = p + 1; return ""; } case 13: { return ""; } } p++; while (true) { var b = buffer[p]; if (b == (byte)' ') { pos = p + 1; break; } if (b == 13) { pos = p; break; } p++; } return StringFromLatin1(buffer, start, p); }
void ParseRequest(byte[] buffer, int startBufferOffset, int posOfReqEnd) { _isWebSocket = false; _next.PrepareForRequest(); posOfReqEnd -= 2; _responseHeaders.Clear(); _webSocketReqCondition = WebSocketReqConditions.Start; if (_cancellation.IsCancellationRequested) _cancellation = new CancellationTokenSource(); _responseIsChunked = false; _responseContentLength = ulong.MaxValue; var pos = startBufferOffset; _isMethodHead = false; _requestMethod = ParseHttpMethod(buffer, ref pos); _requestScheme = _isSsl ? "https" : "http"; string reqHost; ParseHttpPath(buffer, ref pos, out _requestPath, out _requestQueryString, ref _requestScheme, out reqHost); ParseHttpProtocol(buffer, ref pos, out _requestProtocol); if (!SkipCrLf(buffer, ref pos)) throw new Exception("Request line does not end with CRLF"); _isKeepAlive = !_isHttp10; ShouldSend100Continue = false; RequestContentLength = 0; RequestIsChunked = false; if (!ParseHttpHeaders(buffer, pos, posOfReqEnd)) throw new Exception("Request headers cannot be parsed"); }
string ParseHttpMethod(byte[] buffer, ref int pos) { var p = pos; var start = p; switch (buffer[p]) { case (byte)'G': if (buffer[p + 1] == 'E' && buffer[p + 2] == 'T' && buffer[p + 3] == ' ') { pos = p + 4; _webSocketReqCondition |= WebSocketReqConditions.GetMethod; return "GET"; } break; case (byte)'P': if (buffer[p + 1] == 'O' && buffer[p + 2] == 'S' && buffer[p + 3] == 'T' && buffer[p + 4] == ' ') { pos = p + 5; return "POST"; } break; case (byte)' ': { pos = p + 1; return ""; } case 13: { return ""; } } p++; while (true) { var b = buffer[p]; if (b == (byte)' ') { pos = p + 1; break; } if (b == 13) { pos = p; break; } } return StringFromLatin1(buffer, start, p); }