protected bool TakeStartLine(SocketInput input) { var scan = input.ConsumingStart(); var consumed = scan; try { string method; var begin = scan; if (!begin.GetKnownMethod(ref scan, out method)) { if (scan.Seek(ref _vectorSpaces) == -1) { return(false); } method = begin.GetAsciiString(scan); scan.Take(); } begin = scan; var needDecode = false; var chFound = scan.Seek(ref _vectorSpaces, ref _vectorQuestionMarks, ref _vectorPercentages); if (chFound == '%') { needDecode = true; chFound = scan.Seek(ref _vectorSpaces, ref _vectorQuestionMarks); } var pathBegin = begin; var pathEnd = scan; var queryString = ""; if (chFound == '?') { begin = scan; if (scan.Seek(ref _vectorSpaces) != ' ') { return(false); } queryString = begin.GetAsciiString(scan); } scan.Take(); begin = scan; string httpVersion; if (!begin.GetKnownVersion(ref scan, out httpVersion)) { scan = begin; if (scan.Seek(ref _vectorCRs) == -1) { return(false); } httpVersion = begin.GetAsciiString(scan); scan.Take(); } if (scan.Take() != '\n') { return(false); } // URIs are always encoded/escaped to ASCII https://tools.ietf.org/html/rfc3986#page-11 // Multibyte Internationalized Resource Identifiers (IRIs) are first converted to utf8; // then encoded/escaped to ASCII https://www.ietf.org/rfc/rfc3987.txt "Mapping of IRIs to URIs" string requestUrlPath; if (needDecode) { // URI was encoded, unescape and then parse as utf8 pathEnd = UrlPathDecoder.Unescape(pathBegin, pathEnd); requestUrlPath = pathBegin.GetUtf8String(pathEnd); } else { // URI wasn't encoded, parse as ASCII requestUrlPath = pathBegin.GetAsciiString(pathEnd); } consumed = scan; Method = method; RequestUri = requestUrlPath; QueryString = queryString; HttpVersion = httpVersion; bool caseMatches; if (!string.IsNullOrEmpty(_pathBase) && (requestUrlPath.Length == _pathBase.Length || (requestUrlPath.Length > _pathBase.Length && requestUrlPath[_pathBase.Length] == '/')) && RequestUrlStartsWithPathBase(requestUrlPath, out caseMatches)) { PathBase = caseMatches ? _pathBase : requestUrlPath.Substring(0, _pathBase.Length); Path = requestUrlPath.Substring(_pathBase.Length); } else { Path = requestUrlPath; } return(true); } finally { input.ConsumingComplete(consumed, scan); } }
private bool TakeStartLine(SocketInput input) { var scan = input.ConsumingStart(); var consumed = scan; try { var begin = scan; if (scan.Seek(' ') == -1) { return(false); } var method = begin.GetString(scan); scan.Take(); begin = scan; var needDecode = false; var chFound = scan.Seek(' ', '?', '%'); if (chFound == '%') { needDecode = true; chFound = scan.Seek(' ', '?'); } var pathBegin = begin; var pathEnd = scan; var queryString = ""; if (chFound == '?') { begin = scan; if (scan.Seek(' ') != ' ') { return(false); } queryString = begin.GetString(scan); } scan.Take(); begin = scan; if (scan.Seek('\r') == -1) { return(false); } var httpVersion = begin.GetString(scan); scan.Take(); if (scan.Take() != '\n') { return(false); } if (needDecode) { pathEnd = UrlPathDecoder.Unescape(pathBegin, pathEnd); } var requestUrlPath = pathBegin.GetString(pathEnd); consumed = scan; Method = method; RequestUri = requestUrlPath; QueryString = queryString; HttpVersion = httpVersion; Path = RequestUri; return(true); } finally { input.ConsumingComplete(consumed, scan); } }