// constructors internal FileWebResponse(FileWebRequest request, Uri uri, FileAccess access, bool asyncHint) { GlobalLog.Enter("FileWebResponse::FileWebResponse", "uri="+uri+", access="+access+", asyncHint="+asyncHint); try { m_fileAccess = access; if (access == FileAccess.Write) { m_stream = Stream.Null; } else { // // apparently, specifying async when the stream will be read // synchronously, or vice versa, can lead to a 10x perf hit. // While we don't know how the app will read the stream, we // use the hint from whether the app called BeginGetResponse // or GetResponse to supply the async flag to the stream ctor // m_stream = new FileWebStream(request, uri.LocalPath, FileMode.Open, FileAccess.Read, FileShare.Read, DefaultFileStreamBufferSize, asyncHint ); m_contentLength = m_stream.Length; } m_headers = new WebHeaderCollection(WebHeaderCollectionType.FileWebResponse); m_headers.AddInternal(HttpKnownHeaderNames.ContentLength, m_contentLength.ToString(NumberFormatInfo.InvariantInfo)); m_headers.AddInternal(HttpKnownHeaderNames.ContentType, DefaultFileContentType); m_uri = uri; } catch (Exception e) { Exception ex = new WebException(e.Message, e, WebExceptionStatus.ConnectFailure, null); GlobalLog.LeaveException("FileWebResponse::FileWebResponse", ex); throw ex; } catch { Exception ex = new WebException(string.Empty, new Exception(SR.GetString(SR.net_nonClsCompliantException)), WebExceptionStatus.ConnectFailure, null); GlobalLog.LeaveException("FileWebResponse::FileWebResponse", ex); throw ex; } GlobalLog.Leave("FileWebResponse::FileWebResponse"); }
// Server API internal static WebHeaderCollection GetHeaders(byte[] memoryBlob, IntPtr originalAddress) { GlobalLog.Enter("HttpApi::GetHeaders()"); // Return value. WebHeaderCollection headerCollection = new WebHeaderCollection(WebHeaderCollectionType.HttpListenerRequest); fixed (byte* pMemoryBlob = memoryBlob) { HTTP_REQUEST* request = (HTTP_REQUEST*) pMemoryBlob; long fixup = pMemoryBlob - (byte*) originalAddress; int index; // unknown headers if (request->Headers.UnknownHeaderCount != 0) { HTTP_UNKNOWN_HEADER* pUnknownHeader = (HTTP_UNKNOWN_HEADER*) (fixup + (byte*) request->Headers.pUnknownHeaders); for (index = 0; index < request->Headers.UnknownHeaderCount; index++) { // For unknown headers, when header value is empty, RawValueLength will be 0 and // pRawValue will be null. if (pUnknownHeader->pName != null && pUnknownHeader->NameLength > 0) { string headerName = new string(pUnknownHeader->pName + fixup, 0, pUnknownHeader->NameLength); string headerValue; if (pUnknownHeader->pRawValue != null && pUnknownHeader->RawValueLength > 0) { headerValue = new string(pUnknownHeader->pRawValue + fixup, 0, pUnknownHeader->RawValueLength); } else { headerValue = string.Empty; } headerCollection.AddInternal(headerName, headerValue); } pUnknownHeader++; } } // known headers HTTP_KNOWN_HEADER* pKnownHeader = &request->Headers.KnownHeaders; for (index = 0; index < HttpHeaderRequestMaximum; index++) { // For known headers, when header value is empty, RawValueLength will be 0 and // pRawValue will point to empty string ("\0") if (pKnownHeader->pRawValue != null) { string headerValue = new string(pKnownHeader->pRawValue + fixup, 0, pKnownHeader->RawValueLength); headerCollection.AddInternal(HTTP_REQUEST_HEADER_ID.ToString(index), headerValue); } pKnownHeader++; } } GlobalLog.Leave("HttpApi::GetHeaders()"); return headerCollection; }
/// <summary> /// Parses request from client. /// Fills /// - HTTP Verb. /// - HTTP version. /// - Content Length. /// - Fills generic value name pair in WEB header collection. /// </summary> internal void ParseHTTPRequest() { // This is the request line. m_RequestString = m_clientStream.Read_HTTP_Line(HttpWebRequest.maxHTTPLineLength).Trim(); // Split request line into 3 strings - VERB, URL and HTTP version. char[] delimiter = { ' ' }; string[] requestStr = m_RequestString.Split(delimiter); // requestStr should consist of 3 parts. if (requestStr.Length < 3) { throw new ProtocolViolationException("Invalid HTTP request String: " + m_RequestString); } // We have at least 3 strings. Fills the proper fields m_requestVerb = requestStr[0]; m_rawURL = requestStr[1]; // Process third string. It should be either http/1.1 or http/1.0 string httpVerLowerCase = requestStr[2].ToLower(); if (httpVerLowerCase.Equals("http/1.1")) { m_requestHttpVer = HttpVersion.Version11; } else if (httpVerLowerCase.Equals("http/1.0")) { m_requestHttpVer = HttpVersion.Version10; } else { throw new ProtocolViolationException("Unsupported HTTP version: " + requestStr[2]); } // Now it is list of HTTP headers: string line; int headersLen = m_maxResponseHeadersLen; while ((line = m_clientStream.Read_HTTP_Header(HttpWebRequest.maxHTTPLineLength)).Length > 0) { // line.Length is used for the header. Substruct it. headersLen -= line.Length; // If total length used for header is exceeded, we break if (headersLen < 0) { throw new ProtocolViolationException("Http Headers exceeding: " + m_maxResponseHeadersLen); } int sepIdx = line.IndexOf(':'); if (sepIdx == -1) { throw new ProtocolViolationException("Invalid HTTP Header: " + line); } string headerName = line.Substring(0, sepIdx).Trim(); string headerValue = line.Substring(sepIdx + 1).Trim(); string matchableHeaderName = headerName.ToLower(); // Adds new header to collection. m_httpRequestHeaders.AddInternal(headerName, headerValue); // Now we check the value - name pair. For some of them we need to initilize member variables. headerName = headerName.ToLower(); // If it is connection header if (headerName == "connection") { // If value is "Keep-Alive" ( lower case now ), set m_KeepAlive to true; headerValue = headerValue.ToLower(); m_KeepAlive = headerValue == "keep-alive"; } // If user supplied user name and password - parse it and store in m_NetworkCredentials if (headerName == "authorization") { int sepSpace = headerValue.IndexOf(' '); string authType = headerValue.Substring(0, sepSpace); if (authType.ToLower() == "basic") { string authInfo = headerValue.Substring(sepSpace + 1); // authInfo is base64 encoded username and password. byte[] authInfoDecoded = Convert.FromBase64String(authInfo); char[] authInfoDecChar = System.Text.Encoding.UTF8.GetChars(authInfoDecoded); string strAuthInfo = new string(authInfoDecChar); // The strAuthInfo comes in format username:password. Parse it. int sepColon = strAuthInfo.IndexOf(':'); if (sepColon != -1) { m_NetworkCredentials = new NetworkCredential(strAuthInfo.Substring(0, sepColon), strAuthInfo.Substring(sepColon + 1)); } } } } // Http headers were processed. Now we search for content length. string strContentLen = m_httpRequestHeaders[HttpKnownHeaderNames.ContentLength]; if (strContentLen != null) { try { m_contentLength = Convert.ToInt32(strContentLen); } catch (Exception) { throw new ProtocolViolationException("Invalid content length in request: " + strContentLen); } } }
bool GetResponse(BufferOffsetSize buffer, ref int pos, ref ReadState state) { string line = null; bool lineok = false; bool isContinue = false; bool emptyFirstLine = false; do { if (state == ReadState.Aborted) { throw GetReadException(WebExceptionStatus.RequestCanceled, null, "GetResponse"); } if (state == ReadState.None) { lineok = WebConnection.ReadLine(buffer.Buffer, ref pos, buffer.Offset, ref line); if (!lineok) { return(false); } if (line == null) { emptyFirstLine = true; continue; } emptyFirstLine = false; state = ReadState.Status; string[] parts = line.Split(' '); if (parts.Length < 2) { throw GetReadException(WebExceptionStatus.ServerProtocolViolation, null, "GetResponse"); } if (String.Compare(parts[0], "HTTP/1.1", true) == 0) { Version = HttpVersion.Version11; ServicePoint.SetVersion(HttpVersion.Version11); } else { Version = HttpVersion.Version10; ServicePoint.SetVersion(HttpVersion.Version10); } StatusCode = (HttpStatusCode)UInt32.Parse(parts[1]); if (parts.Length >= 3) { StatusDescription = String.Join(" ", parts, 2, parts.Length - 2); } else { StatusDescription = string.Empty; } if (pos >= buffer.Size) { return(true); } } emptyFirstLine = false; if (state == ReadState.Status) { state = ReadState.Headers; Headers = new WebHeaderCollection(); var headerList = new List <string> (); bool finished = false; while (!finished) { if (WebConnection.ReadLine(buffer.Buffer, ref pos, buffer.Offset, ref line) == false) { break; } if (line == null) { // Empty line: end of headers finished = true; continue; } if (line.Length > 0 && (line[0] == ' ' || line[0] == '\t')) { int count = headerList.Count - 1; if (count < 0) { break; } string prev = headerList[count] + line; headerList[count] = prev; } else { headerList.Add(line); } } if (!finished) { return(false); } // .NET uses ParseHeaders or ParseHeadersStrict which is much better foreach (string s in headerList) { int pos_s = s.IndexOf(':'); if (pos_s == -1) { throw new ArgumentException("no colon found", "header"); } var header = s.Substring(0, pos_s); var value = s.Substring(pos_s + 1).Trim(); if (WebHeaderCollection.AllowMultiValues(header)) { Headers.AddInternal(header, value); } else { Headers.SetInternal(header, value); } } if (StatusCode == HttpStatusCode.Continue) { ServicePoint.SendContinue = true; if (pos >= buffer.Offset) { return(true); } if (Request.ExpectContinue) { Request.DoContinueDelegate((int)StatusCode, Headers); // Prevent double calls when getting the // headers in several packets. Request.ExpectContinue = false; } state = ReadState.None; isContinue = true; } else { state = ReadState.Content; return(true); } } } while (emptyFirstLine || isContinue); throw GetReadException(WebExceptionStatus.ServerProtocolViolation, null, "GetResponse"); }
internal static unsafe WebHeaderCollection GetHeaders(byte[] memoryBlob, IntPtr originalAddress) { WebHeaderCollection headers = new WebHeaderCollection(WebHeaderCollectionType.HttpListenerRequest); fixed (byte* numRef = memoryBlob) { int num2; HTTP_REQUEST* http_requestPtr = (HTTP_REQUEST*) numRef; long num = (long) ((numRef - ((void*) originalAddress)) / 1); if (http_requestPtr->Headers.UnknownHeaderCount != 0) { HTTP_UNKNOWN_HEADER* http_unknown_headerPtr = ((HTTP_UNKNOWN_HEADER*) num) + http_requestPtr->Headers.pUnknownHeaders; for (num2 = 0; num2 < http_requestPtr->Headers.UnknownHeaderCount; num2++) { if ((http_unknown_headerPtr->pName != null) && (http_unknown_headerPtr->NameLength > 0)) { string str2; string name = new string(http_unknown_headerPtr->pName + ((sbyte*) num), 0, http_unknown_headerPtr->NameLength); if ((http_unknown_headerPtr->pRawValue != null) && (http_unknown_headerPtr->RawValueLength > 0)) { str2 = new string(http_unknown_headerPtr->pRawValue + ((sbyte*) num), 0, http_unknown_headerPtr->RawValueLength); } else { str2 = string.Empty; } headers.AddInternal(name, str2); } http_unknown_headerPtr++; } } HTTP_KNOWN_HEADER* http_known_headerPtr = &http_requestPtr->Headers.KnownHeaders; for (num2 = 0; num2 < 0x29; num2++) { if (http_known_headerPtr->pRawValue != null) { string str3 = new string(http_known_headerPtr->pRawValue + ((sbyte*) num), 0, http_known_headerPtr->RawValueLength); headers.AddInternal(HTTP_REQUEST_HEADER_ID.ToString(num2), str3); } http_known_headerPtr++; } } return headers; }