internal static bool TryParseRequestLine(ReadOnlySpan <byte> buffer, out HttpRequestLine requestLine, out int totalParsedBytes) { requestLine = new HttpRequestLine(); totalParsedBytes = 0; var reader = new HttpRequestReader(); reader.Buffer = buffer; requestLine.Method = reader.ReadMethod(); if (requestLine.Method == HttpMethod.Unknown) { return(false); } requestLine.RequestUri = reader.ReadRequestUri().Bytes.ToArray(); if (requestLine.RequestUri.Length == 0) { return(false); } reader.Buffer = reader.Buffer.Slice(1); requestLine.Version = reader.ReadHttpVersion(); if (requestLine.Version == HttpVersion.Unknown) { return(false); } totalParsedBytes = buffer.Length - reader.Buffer.Length; return(true); }
static public void TestParseHttpRequestLine() { // Test a well-formatted HTTP/1.1 request line var rq1 = "GET / HTTP/1.1"; var rq1_nl = rq1 + "\r\n"; HttpRequestLine hrl1 = TcpCommon.ParseHttpRequestLine(rq1_nl); Assert.AreEqual(rq1, hrl1.RequestLine); Assert.AreEqual("GET", hrl1.Method); Assert.AreEqual("/", hrl1.URI); Assert.AreEqual("1.1", hrl1.ProtocolVersion); // Test a well-formatted HTTP/1.0 request line var rq2 = "HEAD http://www.idm.fr/index.html HTTP/1.0\r\n"; HttpRequestLine hrl2 = TcpCommon.ParseHttpRequestLine(rq2); Assert.AreEqual("HEAD", hrl2.Method); Assert.AreEqual("http://www.idm.fr/index.html", hrl2.URI); Assert.AreEqual("1.0", hrl2.ProtocolVersion); // Test a wonky-but-still-acceptable request line var rq3 = "OPTIONS /freezepop HTTP/1.2 \n"; HttpRequestLine hrl3 = TcpCommon.ParseHttpRequestLine(rq3); Assert.AreEqual("OPTIONS", hrl3.Method); Assert.AreEqual("/freezepop", hrl3.URI); Assert.AreEqual("1.2", hrl3.ProtocolVersion); }
internal static int TryParseRequestLine(ReadOnlySpan <byte> buffer, out HttpRequestLine requestLine) { requestLine = new HttpRequestLine(); var reader = new HttpRequestReader(); reader.Buffer = buffer; requestLine.Method = reader.ReadMethod(); if (requestLine.Method == HttpMethod.Unknown) { return(0); } requestLine.RequestUri = reader.ReadRequestUri().Bytes.ToArray(); if (requestLine.RequestUri.Length == 0) { return(0); } reader.Buffer = reader.Buffer.Slice(1); requestLine.Version = reader.ReadHttpVersion(); if (requestLine.Version == HttpVersion.Unknown) { return(0); } return(buffer.Length - reader.Buffer.Length); }
public static HttpRequest FromString(string value) { var result = new HttpRequest(); result.Line = HttpRequestLine.FromString(result.Load(value)); return(result); }
public void Parse_BufferIsInvalid_ThrowsBadHttpDataException(string input) { // Arrange var buffer = input.ToAsciiBytes(); // Act & Assert Assert.Throws <BadHttpDataException>(() => HttpRequestLine.Parse(buffer, 3)); }
public void OriginTest() { const string source = "CONNECT www.example.com:80 HTTP/1.1\r\n"; HttpRequestLine.TryParse(source, out var line); line.Source.Is(line.Source); line.GetOrigin().IsNot(line.GetOrigin()); }
public void Parse_StartIsOutOfRange_ThrowsArgumentOutOfRangeException(int start) { // Arrange // Act & Assert var ex = Assert.Throws <ArgumentOutOfRangeException>(() => HttpRequestLine.Parse(new byte[10], start)); Assert.That(ex.ParamName, Is.EqualTo("start")); }
public void Parse_BufferIsNull_ThrowsArgumentNullException(int start) { // Arrange // Act & Assert var ex = Assert.Throws <ArgumentNullException>(() => HttpRequestLine.Parse(null, 5)); Assert.That(ex.ParamName, Is.EqualTo("buffer")); }
public void BrokenRequestLineTest() { const string source = "hogeeeee\r\n"; var isSucceeded = HttpRequestLine.TryParse(source, out var line); isSucceeded.IsFalse(); line.Source.Is(source); line.ToString().Is(source); }
public TRequestId GetRequestId(HttpRequestLine requestLine) { for (int i = 0; i < _count; i++) { if (requestLine.RequestUri.Span.SequenceEqual(_uris[i]) && requestLine.Method == _verbs[i]) { return(_requestIds[i]); } } return(default);
static void WriteResponseForGetTime(BufferFormatter formatter, HttpRequestLine request) { // TODO: this needs to not allocate var body = string.Format(@"<html><head><title>Time</title></head><body>{0}</body></html>", DateTime.UtcNow.ToString("O")); WriteCommonHeaders(formatter, "1.1", "200", "Ok", keepAlive: false); // TOOD: this needs to not allocate formatter.WriteHttpHeader(new Utf8String("Content-Length"), new Utf8String(body.Length.ToString())); formatter.EndHttpHeaderSection(); formatter.WriteHttpBody(new Utf8String(body)); }
public void Constructor_HeadersIsNull_ThrowsArgumentNullException() { // Arrange var line = new HttpRequestLine(HttpMethod.Get, "/"); // Act & Assert var ex = Assert.Throws <ArgumentNullException>(() => new HttpRequestMetadata(line, null)); Assert.That(ex.ParamName, Is.EqualTo("headers")); }
/// <summary> /// スタートラインを解釈 /// </summary> /// <param name="startLine"></param> protected override void ParseStartLine(string startLine) { var isParseSucceeded = HttpRequestLine.TryParse(startLine, out var requestLine); this.RequestLine = requestLine; if (!isParseSucceeded) { Debug.WriteLine($"###start###{startLine}###end###"); throw new BadRequestException("Invalid Request Line", this.GetRequest()); } }
static void WriteResponseForGetTime(BufferFormatter formatter, HttpRequestLine request) { // TODO: this needs to not allocate var body = string.Format(@"<html><head><title>Time</title></head><body>{0}</body></html>", DateTime.UtcNow.ToString("O")); WriteCommonHeaders(formatter, "1.1", "200", "Ok", keepAlive: false); // TOOD: this needs to not allocate formatter.WriteHttpHeader(new Utf8String("Content-Length"), new Utf8String(body.Length.ToString())); formatter.EndHttpHeaderSection(); formatter.WriteHttpBody(new Utf8String(body)); }
public void OriginFormTest() { const string source = "GET /where?q=now HTTP/1.1\r\n"; HttpRequestLine.TryParse(source, out var line); line.Method.Is(HttpMethod.Get); line.HttpVersion.Is(HttpVersion.Version11); line.RequestTargetForm.Is(RequestTargetForm.OriginForm); line.RequestTarget.Is("/where?q=now"); line.ToString().Is(source); }
public void AbsoluteFormTest() { const string source = "GET http://www.example.org/pub/WWW/TheProject.html HTTP/1.1\r\n"; HttpRequestLine.TryParse(source, out var line); line.Method.Is(HttpMethod.Get); line.HttpVersion.Is(HttpVersion.Version11); line.RequestTargetForm.Is(RequestTargetForm.AbsoluteForm); line.RequestTarget.Is("http://www.example.org/pub/WWW/TheProject.html"); line.ToString().Is(source); }
public void AuthorityForm() { const string source = "CONNECT www.example.com:80 HTTP/1.1\r\n"; HttpRequestLine.TryParse(source, out var line); line.Method.Is(new HttpMethod("CONNECT")); line.HttpVersion.Is(HttpVersion.Version11); line.RequestTargetForm.Is(RequestTargetForm.AuthorityForm); line.RequestTarget.Is("www.example.com:80"); line.ToString().Is(source); }
protected override void OnReceiveRequest(HttpRequestLine e) { #if DEBUG Console.ForegroundColor = ConsoleColor.DarkBlue; Console.WriteLine(System.Threading.Thread.CurrentThread.ManagedThreadId + " -> " + RequestLine + (RequestHeaders.Referer != null ? ", Referer: " + RequestHeaders.Referer : "") ); Console.ForegroundColor = ConsoleColor.Gray; #endif requestUri = RequestLine.Uri; // NOTE: used by ReceiveResponse if (blacklistHosts.Contains(requestUri?.Host)) { SocketBP.CloseSocket(); } var method = e.Method.ToUpper(); if (method != "CONNECT") { timer = new System.Threading.Timer(new System.Threading.TimerCallback(OnExpire), null, 300 * 1000, System.Threading.Timeout.Infinite); } if ((method == "POST" || method == "PUT" || method == "PATCH")) { if (skipHosts.Contains(e.Uri.Host)) { return; } // Typical requests endpoint: //http://summonerswar-gb.qpyou.cn/api/gateway_c2.php if (e.Uri.AbsoluteUri.Contains("summonerswar") && e.Uri.AbsoluteUri.Contains("/api/gateway")) { string bodyString = Encoding.ASCII.GetString(SocketBP.Buffer, 0, Array.IndexOf(SocketBP.Buffer, (byte)0)); bodyString = bodyString.Substring(bodyString.IndexOf("\r\n\r\n")); // TODO: FIXME: this needs to match first \r?\n\r?\n decRequest = decryptRequest(bodyString, e.Uri.AbsolutePath.Contains("_c2.php") ? 2 : 1); try { req = JsonConvert.DeserializeObject <JObject>(decRequest); if (!Directory.Exists("Json")) { Directory.CreateDirectory("Json"); } File.WriteAllText($"Json\\{req["command"]}" + #if DEBUG $"_{DateTime.Now.ToString("yyyyMMddHHmmssfff")}" + #endif ".req.json", JsonConvert.SerializeObject(req, Formatting.Indented)); Console.ForegroundColor = ConsoleColor.DarkGray; Console.WriteLine($">{req["command"]}"); Console.ForegroundColor = ConsoleColor.Gray; } catch { }; } } }
public void AsteriskFormTest() { const string source = "OPTIONS * HTTP/1.1\r\n"; HttpRequestLine.TryParse(source, out var line); line.Method.Is(HttpMethod.Options); line.HttpVersion.Is(HttpVersion.Version11); line.RequestTargetForm.Is(RequestTargetForm.AsteriskForm); line.RequestTarget.Is("*"); line.ToString().Is(source); }
protected override HttpServerBuffer CreateResponse(HttpRequestLine requestLine, Span <byte> headerAndBody) { var api = Apis.Map(requestLine); switch (api) { case Api.GetTime: return(CreateResponseForGetTime()); default: return(CreateResponseFor404(requestLine, headerAndBody)); } }
static HttpServerBuffer CreateResponseForGetTime(HttpRequestLine request) { var body = string.Format(@"<html><head><title>Time</title></head><body>{0}</body></html>", DateTime.UtcNow.ToString("O")); var formatter = new BufferFormatter(1024, FormattingData.InvariantUtf8); WriteCommonHeaders(formatter, "1.1", "200", "Ok", request.IsKeepAlive()); formatter.WriteHttpHeader(new Utf8String("Content-Length"), new Utf8String(body.Length.ToString())); formatter.EndHttpHeaderSection(); formatter.WriteHttpBody(new Utf8String(body)); return(new HttpServerBuffer(formatter.Buffer, formatter.CommitedByteCount, BufferPool.Shared)); }
protected override void OnReceiveRequest(HttpRequestLine req) { _requestUri = req.Uri; /*var method = req.Method.ToUpper(); * if ((method == "POST" || method == "PUT" || method == "PATCH") && req.Uri.AbsoluteUri.Contains("api/gateway_c2")) * { * var content = Encoding.ASCII.GetString(SocketBP.Buffer, 0, Array.IndexOf(SocketBP.Buffer, (byte)0)); * content = content.Substring(content.IndexOf("\r\n\r\n", StringComparison.Ordinal)); * * JObject json = JObject.Parse(Proxy.DecryptRequest(content)); * Debug.WriteLine(json["command"]); * }*/ }
public void Parse_ValidArguments_CreatesLine(string input, string expectedMethod, string expectedUri, string expectedVersion) { // Arrange var buffer = input.ToAsciiBytes(); // Act var line = HttpRequestLine.Parse(buffer, 3); // Assert Assert.That(line, Is.Not.Null); Assert.That(line.Method.ToString(), Is.EqualTo(expectedMethod)); Assert.That(line.RequestUri, Is.EqualTo(expectedUri)); Assert.That(line.Version, Is.EqualTo(expectedVersion)); }
public void OriginTest() { const string lineSource = "GET / HTTP/1.1\r\n"; HttpRequestLine.TryParse(lineSource, out var line); var headers = HttpHeaders.Empty; headers.Host.Value = "example.com"; var request = new HttpRequest(line, headers, new byte[0], HttpHeaders.Empty); // Request 系は BadRequest への対処として Source プロパティを持つ request.Source.Is(request.Source); request.GetOrigin().IsNot(request.GetOrigin()); }
public void Constructor_3ArgumentsValid_RunsOk(string method, string uri, string version) { // Arrange // Act var line = new HttpRequestLine(new HttpMethod(method), uri, version); // Assert Assert.That(line.Method.ToString(), Is.EqualTo(method)); Assert.That(line.RequestUri, Is.EqualTo(uri)); Assert.That(line.Version, Is.EqualTo(version)); Assert.That(line.ToString(), Is.EqualTo($"{method} {uri} {version}\r\n")); Assert.That(line.ByteCount, Is.EqualTo($"{method} {uri} {version}\r\n".Length)); Assert.That(line.ToArray(), Is.EquivalentTo($"{method} {uri} {version}\r\n".ToAsciiBytes())); }
public void GetOriginTest() { const string lineSource = "GET / HTTP/1.1\r\n"; HttpRequestLine.TryParse(lineSource, out var line); HttpHeaders.TryParse("Host: example.com\r\n", out var headers); headers.Host.Value = "example2.com"; var request = new HttpRequest(line, headers, new byte[0], HttpHeaders.Empty); request.GetOrigin().ToString().Is( @"GET / HTTP/1.1 Host: example.com "); }
public void ChangeRequestTargetTest() { const string lineSource = "GET /hoge?fuga=piyo HTTP/1.1\r\n"; HttpRequestLine.TryParse(lineSource, out var line); HttpHeaders.TryParse("Host: example.com\r\n", out var headers); var request = new HttpRequest(line, headers, new byte[0], HttpHeaders.Empty); request.RequestTargetUri.ToString().Is("http://example.com/hoge?fuga=piyo"); request.RequestLine.RequestTargetForm.Is(RequestTargetForm.OriginForm); request.ChangeRequestTarget("http://absolute.example.com/hoge?fuga=piyo"); request.RequestTargetUri.ToString().Is("http://absolute.example.com/hoge?fuga=piyo"); request.RequestLine.RequestTargetForm.Is(RequestTargetForm.AbsoluteForm); }
public void Constructor_ValidArguments_RunsOk() { // Arrange var line = new HttpRequestLine(HttpMethod.Get, "/"); var headersArray = new[] { new HttpHeader("Accept", "text/html, application/xhtml+xml, image/jxr, */*"), new HttpHeader("Accept-Language", "ru-RU"), new HttpHeader("User-Agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/58.0.3029.110 Safari/537.36 Edge/16.16299"), new HttpHeader("Accept-Encoding", "gzip, deflate"), new HttpHeader("Host", "allitebooks.com"), new HttpHeader("Connection", "Keep-Alive"), }; var headers = new HttpHeaderCollection(headersArray); // Act var requestMetadata = new HttpRequestMetadata(line, headers); // Assert Assert.That(requestMetadata.Line.Method.ToString(), Is.EqualTo("GET")); Assert.That(requestMetadata.Line.RequestUri, Is.EqualTo("/")); Assert.That(requestMetadata.Line.Version, Is.EqualTo("HTTP/1.1")); Assert.That(requestMetadata.Headers.Count(), Is.EqualTo(6)); Assert.That(requestMetadata.Headers.ElementAt(0), Is.SameAs(headersArray[0])); Assert.That(requestMetadata.Headers.ElementAt(1), Is.SameAs(headersArray[1])); Assert.That(requestMetadata.Headers.ElementAt(2), Is.SameAs(headersArray[2])); Assert.That(requestMetadata.Headers.ElementAt(3), Is.SameAs(headersArray[3])); Assert.That(requestMetadata.Headers.ElementAt(4), Is.SameAs(headersArray[4])); Assert.That(requestMetadata.Headers.ElementAt(5), Is.SameAs(headersArray[5])); var expectedString = @"GET / HTTP/1.1 Accept: text/html, application/xhtml+xml, image/jxr, */* Accept-Language: ru-RU User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/58.0.3029.110 Safari/537.36 Edge/16.16299 Accept-Encoding: gzip, deflate Host: allitebooks.com Connection: Keep-Alive "; var toString = requestMetadata.ToString(); Assert.That(toString, Is.EqualTo(expectedString)); var bytes = requestMetadata.Serialize(); Assert.That(bytes, Is.EquivalentTo(expectedString.ToAsciiBytes())); }
public void HeadersAsByteTest() { const string lineSource = "GET / HTTP/1.1\r\n"; HttpRequestLine.TryParse(lineSource, out var line); var headers = HttpHeaders.Empty; headers.Host.Value = "example.com"; var request = new HttpRequest(line, headers, new byte[0], HttpHeaders.Empty); request.HeadersAsByte().Is(Encoding.ASCII.GetBytes( @"GET / HTTP/1.1 Host: example.com ")); }
/// <summary> /// HTTPリクエスト文字列からHTTPRequestオブジェクトを構築します /// </summary> /// <param name="requests">行毎に区切られたHTTPリクエストの文字列表現</param> public HttpRequest(HttpRequestLine reqLine, IEnumerable <string> requests) { Method = reqLine.Method; Protocol = reqLine.Protocol; PathAndQuery = reqLine.PathAndQuery; var headers = new RequestHeaders(); foreach (var req in requests) { Match match = null; if ((match = OtherHeaderRegex.Match(req)).Success) { headers.Add(match.Groups[1].Value, match.Groups[2].Value.Trim()); } } Headers = headers; }
public void CreateOptionsInstanceTest() { const string lineSource = "OPTIONS * HTTP/1.1\r\n"; HttpRequestLine.TryParse(lineSource, out var line); var headers = HttpHeaders.Empty; headers.Host.Value = "example.com"; var request = new HttpRequest(line, headers, new byte[0], HttpHeaders.Empty); request.ToString().Is( @"OPTIONS * HTTP/1.1 Host: example.com "); request.RequestTargetUri.ToString().Is("*"); request.RequestLine.RequestTargetForm.Is(RequestTargetForm.AsteriskForm); }
HttpRequestLine ReadRequestLine() { var str = ReadLine(_strm); var strArray = str.Split(new char[] { ' ' }, StringSplitOptions.RemoveEmptyEntries); if (strArray.Length == 3) { var line = new HttpRequestLine( strArray[0].Trim(), strArray[1].Trim(), new Version(strArray[2].Trim().Replace("HTTP/", ""))); return line; } else return null; }
protected virtual void WriteResponseFor404(BufferFormatter formatter, HttpRequestLine requestLine) // Not Found { Log.LogMessage(Log.Level.Warning, "Request {0}, Response: 404 Not Found", requestLine); WriteCommonHeaders(formatter, "1.1", "404", "Not Found", false); formatter.Append(HttpNewline); }
private TestRequest(HttpRequestLine requestLine) { _requestLine = requestLine; }