public void PUT_Verb() { // arrange var verb = "PUT"; // act var result = KnownHttpVerb.Parse(verb); // assert Assert.AreEqual(verb, result.Name); Assert.IsFalse(result.ConnectRequest); Assert.IsFalse(result.ContentBodyNotAllowed); Assert.IsFalse(result.ExpectNoContentResponse); Assert.IsTrue(result.RequireContentBody); }
protected HttpWebResponse(SerializationInfo serializationInfo, StreamingContext streamingContext) : base(serializationInfo, streamingContext) { m_HttpResponseHeaders = (WebHeaderCollection)serializationInfo.GetValue("m_HttpResponseHeaders", typeof(WebHeaderCollection)); m_Uri = (Uri)serializationInfo.GetValue("m_Uri", typeof(Uri)); #if !FEATURE_PAL m_Certificate = (X509Certificate)serializationInfo.GetValue("m_Certificate", typeof(X509Certificate)); #endif // !FEATURE_PAL Version version = (Version)serializationInfo.GetValue("m_Version", typeof(Version)); m_IsVersionHttp11 = version.Equals(HttpVersion.Version11); m_StatusCode = (HttpStatusCode)serializationInfo.GetInt32("m_StatusCode"); m_ContentLength = serializationInfo.GetInt64("m_ContentLength"); m_Verb = KnownHttpVerb.Parse(serializationInfo.GetString("m_Verb")); m_StatusDescription = serializationInfo.GetString("m_StatusDescription"); m_MediaType = serializationInfo.GetString("m_MediaType"); }
/// <summary> /// Initializes a new instance of the <see cref="HttpWebResponseSocks" /> class. /// </summary> /// <param name="responseUri">The response URI.</param> /// <param name="verb">The verb.</param> /// <param name="statusCode">The status code.</param> /// <param name="responseHeaders">The response headers.</param> /// <param name="responseStream">The response stream.</param> /// <exception cref="InvalidOperationException"></exception> internal HttpWebResponseSocks(Uri responseUri, KnownHttpVerb verb, HttpStatusCode statusCode, WebHeaderCollection responseHeaders, Stream responseStream) { StatusCode = statusCode; Headers = responseHeaders; ResponseUri = responseUri; _socksConnection = null; _verb = verb; // Build stream object for WebResponse string contentEncodingKey; DecompressionMethods compressionMethod; if (!Headers.ContainsHeaderKey(HttpResponseHeader.ContentEncoding.ToString(), out contentEncodingKey) || !Enum.TryParse(Headers[contentEncodingKey], true, out compressionMethod)) { _responseStream = responseStream; return; } // If content encoding is var contentEncoding = Headers[contentEncodingKey].Trim().ToLowerInvariant(); switch (compressionMethod) { case DecompressionMethods.GZip: _responseStream = new GZipStream(responseStream, CompressionMode.Decompress); Headers[HttpRequestHeader.ContentLength] = "-1"; break; case DecompressionMethods.Deflate: _responseStream = new DeflateStream(responseStream, CompressionMode.Decompress); Headers[HttpRequestHeader.ContentLength] = "-1"; break; default: throw new InvalidOperationException($"Unknown encoding type '{contentEncoding}'"); } }
internal HttpWebResponse(Uri responseUri, KnownHttpVerb verb, CoreResponseData coreData, string mediaType, bool usesProxySemantics, DecompressionMethods decompressionMethod) { m_Uri = responseUri; m_Verb = verb; m_MediaType = mediaType; m_UsesProxySemantics = usesProxySemantics; m_ConnectStream = coreData.m_ConnectStream; m_HttpResponseHeaders = coreData.m_ResponseHeaders; m_ContentLength = coreData.m_ContentLength; m_StatusCode = coreData.m_StatusCode; m_StatusDescription = coreData.m_StatusDescription; m_IsVersionHttp11 = coreData.m_IsVersionHttp11; //if the returned contentlength is zero, preemptively invoke calldone on the stream. //this will wake up any pending reads. if (m_ContentLength == 0 && m_ConnectStream is ConnectStream) { ((ConnectStream)m_ConnectStream).CallDone(); } // handle Content-Location header, by combining it with the orginal request. string contentLocation = m_HttpResponseHeaders[HttpKnownHeaderNames.ContentLocation]; if (contentLocation != null) { try { m_Uri = new Uri(m_Uri, contentLocation); } catch (UriFormatException e) { GlobalLog.Assert("Exception on response Uri parsing.", e.ToString()); } } // decompress responses by hooking up a final response Stream - only if user required it if (decompressionMethod != DecompressionMethods.None) { string contentEncoding = m_HttpResponseHeaders[HttpKnownHeaderNames.ContentEncoding]; if (contentEncoding != null) { if (((decompressionMethod & DecompressionMethods.GZip) != 0) && contentEncoding.IndexOf(HttpWebRequest.GZipHeader) != -1) { m_ConnectStream = new GZipWrapperStream(m_ConnectStream, CompressionMode.Decompress); m_ContentLength = -1; // unknown on compressed streams // Setting a response header after parsing will ruin the Common Header optimization. // This seems like a corner case. ContentEncoding could be added as a common header, with a special // property allowing it to be nulled. m_HttpResponseHeaders[HttpKnownHeaderNames.ContentEncoding] = null; } else if (((decompressionMethod & DecompressionMethods.Deflate) != 0) && contentEncoding.IndexOf(HttpWebRequest.DeflateHeader) != -1) { m_ConnectStream = new DeflateWrapperStream(m_ConnectStream, CompressionMode.Decompress); m_ContentLength = -1; // unknown on compressed streams // Setting a response header after parsing will ruin the Common Header optimization. // This seems like a corner case. ContentEncoding could be added as a common header, with a special // property allowing it to be nulled. m_HttpResponseHeaders[HttpKnownHeaderNames.ContentEncoding] = null; } } } }
/// <summary> /// Equalses the specified verb. /// </summary> /// <param name="verb">The verb.</param> /// <returns></returns> public bool Equals(KnownHttpVerb verb) { if (this != verb) return String.Compare(Name, verb.Name, StringComparison.OrdinalIgnoreCase) == 0; return true; }
/// <summary> /// Creates a request to the specified URI. /// </summary> /// <param name="uri">The URI to send request to.</param> /// <param name="type">Request type.</param> /// <param name="requestData">Request data.</param> /// <param name="settings">Request settings.</param> /// <returns></returns> /// <exception cref="System.NotImplementedException">Only http://xxxx and https://xxxx URI are supported!</exception> public static IWebRequestResult Create( Uri uri, KnownHttpVerb type = KnownHttpVerb.Get, Dictionary <string, string> requestData = null, WebRequestSettings settings = null ) { if (!uri.Scheme.Equals("http") && !uri.Scheme.Equals("https")) { throw new NotImplementedException("Only http://xxxx and https://xxxx URI are supported!"); } var requestDataString = string.Empty; if (requestData != null && requestData.Any()) { // Aggregate all the parameters in a query string requestDataString = string.Join("&", requestData.Select(varSet => $"{HttpUtility.UrlPathEncode(varSet.Key)}={HttpUtility.UrlEncode(varSet.Value)}")); } // Append data in GET/HEAD format switch (type) { case KnownHttpVerb.Get: case KnownHttpVerb.Head: var ub = new UriBuilder(uri); ub.Query = (string.IsNullOrWhiteSpace(ub.Query)) ? requestDataString : $"{ub.Query}&{requestDataString}"; uri = ub.Uri; break; } // Create web request (request type is based on proxy type) var requestResult = (settings?.Proxy is WebProxySocks) ? HttpWebRequestSocksResult.Create(uri) : HttpWebRequestResult.Create(uri); // Set request proxy requestResult.Request.Proxy = settings?.Proxy; // Set HTTP request type (POST, GET etc) requestResult.Request.Method = type.ToString().ToUpperInvariant(); // Override headers if needed if (settings?.Headers != null) { requestResult.AddHeaders(settings.Headers); } // Set request encoding var requestEncoding = settings?.Encoding ?? Encoding.UTF8; if (settings?.Headers.ContainsKey(HttpRequestHeader.AcceptCharset) ?? false && string.IsNullOrWhiteSpace(settings?.Headers[HttpRequestHeader.AcceptCharset])) { requestResult.Request.Headers[HttpRequestHeader.AcceptCharset] = requestEncoding.WebName; } // Forcibly set a ContentType header on POST/PUT/DELETE request switch (type) { case KnownHttpVerb.Post: case KnownHttpVerb.Put: // Set content type if it is empty if (string.IsNullOrWhiteSpace(requestResult.Request.ContentType)) { requestResult.Request.ContentType = "application/x-www-form-urlencoded"; } // Send request BODY if needed var postDataBytes = requestEncoding.GetBytes(requestDataString); requestResult.Request.ContentLength = postDataBytes.Length; using (var stream = requestResult.Request.GetRequestStream()) { stream.Write(postDataBytes, 0, postDataBytes.Length); stream.Close(); } break; default: if (string.IsNullOrWhiteSpace(requestResult.Request.ContentType)) { requestResult.Request.ContentType = $"text/html; charset={requestEncoding.WebName}"; } break; } return(requestResult); }
/// <summary> /// Parses the specified name. /// </summary> /// <param name="name">The name.</param> /// <returns></returns> public static KnownHttpVerb Parse(string name) { KnownHttpVerb verb; if (!NamedHeaders.TryGetValue(name, out verb)) verb = new KnownHttpVerb(name, false, false, false, false); return verb; }
//private bool IncrementRequestCount(ApplicationInstance instance) //{ // LbIncrementRequestCountRequest request = new LbIncrementRequestCountRequest(Settings.Credentials); // request.ApplicationId = instance.ApplicationId; // request.InstanceId = instance.Id; // EndPoints.LoadBalancerWebService.IncrementRequestCount(request); // return true; //} //private void DecrementRequestCount(ApplicationInstance instance) //{ // LbDecrementRequestCountRequest request = new LbDecrementRequestCountRequest(Settings.Credentials); // request.ApplicationId = instance.ApplicationId; // request.InstanceId = instance.Id; // EndPoints.LoadBalancerWebService.DecrementRequestCount(request); //} /// <summary> /// Sends the request to server /// Implemented using Managed Fusion URL Rewriter /// Reference: http://www.managedfusion.com/products/url-rewriter/ /// </summary> /// <param name="context">The context.</param> /// <returns></returns> private WebResponse SendRequestToTarget(HttpContext context, Uri requestUrl, ReverseProxyContext rpContext, out bool incremented) { incremented = false; // get the request WebRequest request = WebRequest.CreateDefault(requestUrl); if (request == null) { throw new HttpException((int)HttpStatusCode.BadRequest, "The requested url, <" + requestUrl + ">, could not be found."); } // keep the same HTTP request method request.Method = context.Request.HttpMethod; var knownVerb = KnownHttpVerb.Parse(request.Method); // depending on the type of this request specific values for an HTTP request if (request is HttpWebRequest) { var httpRequest = request as HttpWebRequest; httpRequest.AllowAutoRedirect = false; httpRequest.ServicePoint.Expect100Continue = false; // add all the headers from the other proxied session to this request foreach (string name in context.Request.Headers.AllKeys) { // add the headers that are restricted in their supported manor switch (name) { case "User-Agent": httpRequest.UserAgent = context.Request.UserAgent; break; case "Connection": string connection = context.Request.Headers[name]; if (connection.IndexOf("Keep-Alive", StringComparison.OrdinalIgnoreCase) > 0) { httpRequest.KeepAlive = true; } List <string> list = new List <string>(); foreach (string conn in connection.Split(',')) { string c = conn.Trim(); if (!c.Equals("Keep-Alive", StringComparison.OrdinalIgnoreCase) && !c.Equals("Close", StringComparison.OrdinalIgnoreCase)) { list.Add(c); } } if (list.Count > 0) { httpRequest.Connection = String.Join(", ", list.ToArray()); } break; case "Transfer-Encoding": httpRequest.SendChunked = true; httpRequest.TransferEncoding = context.Request.Headers[name]; break; case "Expect": httpRequest.ServicePoint.Expect100Continue = true; break; case "If-Modified-Since": DateTime ifModifiedSince; if (DateTime.TryParse(context.Request.Headers[name], out ifModifiedSince)) { httpRequest.IfModifiedSince = ifModifiedSince; } break; case "Content-Length": httpRequest.ContentLength = context.Request.ContentLength; break; case "Content-Type": httpRequest.ContentType = context.Request.ContentType; break; case "Accept": httpRequest.Accept = String.Join(", ", context.Request.AcceptTypes); break; case "Referer": httpRequest.Referer = context.Request.UrlReferrer.OriginalString; break; } // add to header if not restricted if (!WebHeaderCollection.IsRestricted(name, false)) { // it is nessisary to get the values for headers that are allowed to specifiy // multiple values in an instance (i.e. Cookie) string[] values = context.Request.Headers.GetValues(name); foreach (string value in values) { request.Headers.Add(name, value); } } } } // Add Proxy Standard Protocol Headers // http://en.wikipedia.org/wiki/X-Forwarded-For request.Headers.Add("X-Forwarded-For", context.Request.UserHostAddress); // Add Server Variables // http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html#sec14.45 string currentServerName = context.Request.ServerVariables["SERVER_NAME"]; string currentServerPort = context.Request.ServerVariables["SERVER_PORT"]; string currentServerProtocol = context.Request.ServerVariables["SERVER_PROTOCOL"]; if (currentServerProtocol.IndexOf("/") >= 0) { currentServerProtocol = currentServerProtocol.Substring(currentServerProtocol.IndexOf("/") + 1); } string currentVia = String.Format("{0} {1}:{2} ({3})", currentServerProtocol, currentServerName, currentServerPort, "Monoscape.LoadBalancerController"); request.Headers.Add("Via", currentVia); // // ContentLength is set to -1 if their is no data to send if ((request.ContentLength >= 0) && (!knownVerb.ContentBodyNotAllowed)) { int bufferSize = 64 * 1024; using (Stream requestStream = request.GetRequestStream(), bufferStream = new BufferedStream(context.Request.InputStream, bufferSize)) { byte[] buffer = new byte[bufferSize]; try { while (true) { // make sure that the stream can be read from if (!bufferStream.CanRead) { break; } int bytesReturned = bufferStream.Read(buffer, 0, bufferSize); // if not bytes were returned the end of the stream has been reached // and the loop should exit if (bytesReturned == 0) { break; } // write bytes to the response requestStream.Write(buffer, 0, bytesReturned); } } catch (Exception e) { Log.Error(typeof(ProxyHandler), "", e); } } } WebResponse response; try { // Increment application instance request count //incremented = IncrementRequestCount(rpContext.ApplicationInstance); if (addReqResult != null) { int requestId = rpContext.AddReqCaller.EndInvoke(addReqResult); // Remove request from load balancer request queue ASyncRemoveRequestFromQueue caller = new ASyncRemoveRequestFromQueue(RemoveRequestFromQueue); caller.BeginInvoke(requestId, null, null); } // Send request to the proxy target response = request.GetResponse(); } catch (WebException e) { Log.Error(typeof(ProxyHandler), "Error received from " + request.RequestUri + ": " + e.Message, e); response = e.Response; } if (response == null) { Log.Error(typeof(ProxyHandler), "The requested url " + requestUrl + " could not be found."); throw new HttpException((int)HttpStatusCode.NotFound, "The requested url could not be found."); } Log.Info(typeof(ProxyHandler), response.GetType().ToString()); if (response is HttpWebResponse) { HttpWebResponse httpResponse = response as HttpWebResponse; Log.Info(typeof(ProxyHandler), "Received '" + ((int)httpResponse.StatusCode) + " " + httpResponse.StatusDescription + "'"); } return(response); }
public bool Equals(KnownHttpVerb verb) { return this==verb || string.Compare(Name, verb.Name, StringComparison.OrdinalIgnoreCase)==0; }
public static KnownHttpVerb Parse(string name) { KnownHttpVerb knownHttpVerb = NamedHeaders[name] as KnownHttpVerb; if (knownHttpVerb==null) { // unknown verb, default behaviour knownHttpVerb = new KnownHttpVerb(name, false, false, false, false); } return knownHttpVerb; }
// // InitializeKnownVerbs - Does basic init for this object, // such as creating defaultings and filling them // static KnownHttpVerb() { NamedHeaders = new ListDictionary(CaseInsensitiveAscii.StaticInstance); Get = new KnownHttpVerb("GET", false, true, false, false); Connect = new KnownHttpVerb("CONNECT", false, true, true, false); Head = new KnownHttpVerb("HEAD", false, true, false, true); Put = new KnownHttpVerb("PUT", true, false, false, false); Post = new KnownHttpVerb("POST", true, false, false, false); MkCol = new KnownHttpVerb("MKCOL",false,false,false,false); NamedHeaders[Get.Name] = Get; NamedHeaders[Connect.Name] = Connect; NamedHeaders[Head.Name] = Head; NamedHeaders[Put.Name] = Put; NamedHeaders[Post.Name] = Post; NamedHeaders[MkCol.Name] = MkCol; }