private static void AddResponseHeaders(HttpWebResponse response, HttpResponseInfo responseInfo) { foreach (string key in response.Headers.Keys) { string headerValue = response.Headers[key].Trim(); //these headers can occur multiple times in the response //as per the RFC if the value is split by a comma should be //considered multiple message header fields however there are cases when the //header can contain a comma for example Date: Sun, December 23 if (String.Compare(key, "WWW-Authenticate", true) == 0 || String.Compare(key, "Proxy-Authenticate", true) == 0) { if (headerValue.StartsWith("Basic", StringComparison.OrdinalIgnoreCase) || headerValue.StartsWith("NTLM", StringComparison.OrdinalIgnoreCase) || headerValue.StartsWith("Negotiate", StringComparison.OrdinalIgnoreCase)) { //get the values string[] values = headerValue.Split(','); foreach (string value in values) { responseInfo.Headers.Add(key, value); } } else { responseInfo.Headers.Add(key, headerValue); } } else if (String.Compare(key, "Set-Cookie", true) == 0) { AddCookies(responseInfo, headerValue); } else { responseInfo.Headers.Add(key, headerValue); } } }
private void SendConnect(string host, int port) { string connectRequest = String.Format(Resources.ConnectRequest, host, port); byte[] connectBytes = Constants.DefaultEncoding.GetBytes(connectRequest); _connection.Stream.Write(connectBytes, 0, connectBytes.Length); //read the response ByteArrayBuilder builder = new ByteArrayBuilder(); byte[] buffer = new byte[MAX_BUFFER_SIZE]; int bytesRead = _connection.Stream.Read(buffer, 0, MAX_BUFFER_SIZE); if (bytesRead > 0) { builder.AddChunkReference(buffer, bytesRead); } if (builder.Length == 0) { throw new Exception("No response to connect"); } else { HttpResponseInfo respInfo = new HttpResponseInfo(); respInfo.ProcessResponse(builder.ToArray()); if (respInfo.Status != 200) { throw new Exception("Connect response didn't get 200 status"); } else { //secure the connection _connection.SecureStream(host); } } }
/// <summary> /// Override to do something with the response before returning it to the client /// </summary> /// <param name="responseInfo"></param> /// <returns></returns> protected virtual HttpResponseInfo OnBeforeResponseToClient(HttpResponseInfo responseInfo) { return(responseInfo); }
/// <summary> /// Writes a response to the client stream /// </summary> /// <param name="responseInfo"></param> protected virtual void ReturnResponse(HttpResponseInfo responseInfo) { HttpServerConsole.Instance.WriteLine(LogMessageType.Information, "Sending response: {0} for request: {1}", responseInfo.StatusLine, _requestInfo.RequestLine); if (_currDataStoreRequestInfo != null) { _currDataStoreRequestInfo.ResponseStatus = responseInfo.Status.ToString(); _currDataStoreRequestInfo.ResponseTime = DateTime.Now; } //process response headers if (responseInfo.Status == 401) { //we need to send the proxy support header/ or overwrite the existing proxy support header responseInfo.Headers["Proxy-Support"] = "Session-Based-Authentication"; } //if connection is close disconnect, or if the client sent us a connection close message if (String.Compare(responseInfo.Headers[CONNECTION_HEADER], "close", true) == 0 || String.Compare(_requestInfo.Headers[CONNECTION_HEADER], "close", true) == 0) { _isClose = true; } byte[] responseHead = HandleResponseByteChunk(responseInfo.ResponseHead); if (!TryWriteToStream(responseHead)) { return; } ; // Return the substitute response body if (responseInfo.ResponseBody.IsChunked) { byte[] chunk; byte[] chunkBuf; while ((chunk = responseInfo.ResponseBody.ReadChunk()) != null) { //write the chunk size line chunkBuf = Constants.DefaultEncoding.GetBytes(String.Format("{0:x}\r\n", chunk.Length)); chunkBuf = HandleResponseByteChunk(chunkBuf); if (!TryWriteToStream(chunkBuf)) { return; } //write the chunk chunk = HandleResponseByteChunk(chunk); if (!TryWriteToStream(chunk)) { return; } chunkBuf = Constants.DefaultEncoding.GetBytes("\r\n"); chunkBuf = HandleResponseByteChunk(chunkBuf); if (!TryWriteToStream(chunkBuf)) { return; } } //write a last chunk with the value 0 // write the last chunk size chunkBuf = Constants.DefaultEncoding.GetBytes("0\r\n\r\n"); chunkBuf = HandleResponseByteChunk(chunkBuf); if (!TryWriteToStream(chunkBuf)) { return; } } else { byte[] buffer = responseInfo.ResponseBody.ToArray(); if (buffer != null) { buffer = HandleResponseByteChunk(buffer); if (!TryWriteToStream(buffer)) { return; } } } //cleanup the request info _requestBuilder = new ByteArrayBuilder(); if (_currDataStoreRequestInfo != null) { TrafficDataStore.SaveResponse(_currDataStoreRequestInfo.Id, _currentRequestResponseBytes); } _currDataStoreRequestInfo = null; _currentRequestResponseBytes = null; //close the connection if the request had a connection close header if (_isClose) { ClientStreamWrapper.Close(); } else { _isBusy = false; ClientStreamWrapper.BeginRead(Buffer, 0, Buffer.Length, new AsyncCallback(OnRead), ClientStreamWrapper); } }
/// <summary> /// Constructor /// </summary> /// <param name="response">The result of an HttpClient send operation</param> /// <param name="result">The Http response, null if an error occurred</param> public HttpClientRequestCompleteEventArgs(HttpResponseInfo response) { _result = HttpClientResult.Success; _httpResponse = response; }
/// <summary> /// Sends the request to the site /// </summary> /// <param name="requestInfo"></param> /// <returns></returns> public override HttpResponseInfo SendRequest(HttpRequestInfo requestInfo) { HttpWebRequest webRequest = WebRequest.Create(requestInfo.FullUrl) as HttpWebRequest; if (ShouldHandleCookies) { webRequest.CookieContainer = _cookieJar; } ProcessRequestDelay(requestInfo); webRequest.Timeout = _timeout; //attempt to reserve a connection group name for the current object //this will make the web request keep alive work properly webRequest.ConnectionGroupName = GetHashCode().ToString(); SetNetworkSettings(webRequest); CopyHeaders(requestInfo, webRequest); //request Method (GET, POST, etc..) webRequest.Method = requestInfo.Method; string version = requestInfo.HttpVersion.Replace("HTTP/", ""); if (!version.Equals("1.0") && !version.Equals("1.1")) { version = "1.1"; } webRequest.ProtocolVersion = Version.Parse(version); webRequest.AllowAutoRedirect = false; //add POST data, if any byte[] postData = requestInfo.ContentData; if (postData != null && postData.Length > 0) { try { webRequest.ContentLength = postData.Length; Stream requestStream = webRequest.GetRequestStream(); requestStream.Write(postData, 0, postData.Length); requestStream.Close(); } catch (ProtocolViolationException ex) //ignore malformed request such as AppScan requests { SdkSettings.Instance.Logger.Log(TraceLevel.Verbose, "WebRequestClient: Got a malformed request: {0}", ex.Message); } } HttpWebResponse response = null; //pass the request to the target server try { response = webRequest.GetResponse() as HttpWebResponse; } catch (WebException webException) { response = webException.Response as HttpWebResponse; if (response == null) { throw webException; } } HttpResponseInfo responseInfo = null; //read response if (response != null) { string responseLine = String.Format("HTTP/{0} {1} {2}\r\n", response.ProtocolVersion, (int)response.StatusCode, response.StatusDescription); responseInfo = new HttpResponseInfo(responseLine); AddResponseHeaders(response, responseInfo); //add response body string transferEncoding = response.Headers["Transfer-Encoding"]; responseInfo.ResponseBody.IsChunked = transferEncoding != null && String.Compare("chunked", transferEncoding, true) == 0; Stream responseStream = response.GetResponseStream(); int read; byte[] buffer = new byte[MAX_BUFFER_SIZE]; while ((read = responseStream.Read(buffer, 0, MAX_BUFFER_SIZE)) > 0) { responseInfo.ResponseBody.AddChunkReference(buffer, read); } response.Close(); } return(responseInfo); }
/// <summary> /// Sends the request to the site /// </summary> /// <param name="requestInfo"></param> /// <returns></returns> public override HttpResponseInfo SendRequest(HttpRequestInfo requestInfo) { PrepareConnection(requestInfo); HttpClientRequest request = new HttpClientRequest(_connection); //check if the request requires credentials HttpAuthenticationInfo authInfo; if (HttpAuthenticationManager.Instance.RequiresCredentials(requestInfo, out authInfo)) { requestInfo.Headers.Add(HttpAuthenticationManager.Instance.GetBasicAuthHeader(authInfo)); } //delay the request ProcessRequestDelay(requestInfo); request.SendRequest(requestInfo, requestInfo.IsSecure); bool success = request.RequestCompleteEvent.WaitOne(_timeout); if (!success || request.Response == null) { throw new Exception(Resources.RequestTimeout); } string rawResponse = Constants.DefaultEncoding.GetString(request.Response); string responseStatus = HttpResponseInfo.GetResponseStatus(rawResponse); bool isPlatformAuth = String.Compare(responseStatus, "401") == 0; bool isProxyAuth = String.Compare(responseStatus, "407") == 0; if (isPlatformAuth || isProxyAuth) { //check the headers HttpResponseInfo respInfo = new HttpResponseInfo(rawResponse); List <HTTPHeader> authHeaders = new List <HTTPHeader>(); if (isPlatformAuth) { authHeaders = respInfo.Headers.GetHeaders("WWW-Authenticate"); } else if (isProxyAuth) { authHeaders = respInfo.Headers.GetHeaders("Proxy-Authenticate"); } bool usesBasic = false; for (int i = authHeaders.Count - 1; i > -1; i--) //go backwards the basic header is usually last { HTTPHeader header = authHeaders[i]; if (header.Value.IndexOf("Basic", StringComparison.OrdinalIgnoreCase) == 0) { usesBasic = true; break; } } if (usesBasic) { //try to get the credentials from the user authInfo = HttpAuthenticationManager.Instance.GetCredentials(requestInfo, isProxyAuth); if (authInfo != null) { //add the basic auth header requestInfo.Headers.Add(HttpAuthenticationManager.Instance.GetBasicAuthHeader(authInfo)); //create a new request PrepareConnection(requestInfo); request = new HttpClientRequest(_connection); //proceed with new request request.SendRequest(requestInfo, requestInfo.IsSecure); success = request.RequestCompleteEvent.WaitOne(_timeout); if (!success) { throw new Exception(Resources.RequestTimeout); } } } } if (request.Response != null) { return(new HttpResponseInfo(request.Response)); } return(null); }