public void Add(Guid ruleGuid, TransferItem transferItem, bool storeIsAll) { var requestLine = transferItem.HttpRequestLine.URL; string index; if (storeIsAll == false) { if (ContainsItem(ruleGuid, requestLine, out index)) { lock (sync) { RemoveItemFromCache(index, requestLine); } } } index = Guid.NewGuid().ToString(); var item = new QItemCache { RuleGuid = ruleGuid, ResponseId = transferItem.BrowserSocket.guid, RequestLine = requestLine, Response = null, IsAllStore = storeIsAll, Key = index, StatusCode = -1 }; var policy = new CacheItemPolicy(); cache.Add(index, item, policy); responseGuidLinkIndex.TryAdd(item.ResponseId, index); urlLinkIndex.TryAdd(index, item.RequestLine); ruleGuidLinkIndex.TryAdd(index, item.RuleGuid); }
protected override void OnReceiveResponse(TransferItem item) { if (Rules.Where(rule => rule.IsAccept(item.HttpRequestLine.URL)).Any(rule => rule.IsStoreResponse)) { cache.SetValue(item.BrowserSocket.guid, item.Response, item.ResponseStatusLine.StatusCode); } }
protected override void OnReceiveRequest(TransferItem item) { if (CheckOnBlackList(item) == false) { return; } CheckOnRules(item); }
private bool CheckOnBlackList(TransferItem item) { // In BlackList must be rule with QBehavior = Block if (BlackList.Any(rule => rule.IsAccept(item.HttpRequestLine.URI))) { item.State.NextStep = null; return(false); } return(true); }
private void CheckOnRules(TransferItem item) { foreach (var rule in Rules) { if (rule.IsAccept(item.HttpRequestLine.URL)) { if (rule.IsStoreResponse) { cache.Add(rule.Guid, item, rule.IsAllStoreResponse); } item.HttpRequestLine.URL = rule.Redirect(item.HttpRequestLine.URL); break; } } }
private void CallOnReceiveResponse(string responseMessageChunked) { var transferItem = new TransferItem(); transferItem.Headers = ResponseHeaders; transferItem.HttpRequestLine = RequestLine; transferItem.ResponseStatusLine = ResponseStatusLine; transferItem.BrowserSocket = BrowserSocket; transferItem.RemoteSocket = RemoteSocket; transferItem.State = State; transferItem.Response = GetResponse(responseMessageChunked); OnReceiveResponse(transferItem); if (State.PersistConnectionRemoteSocket == false && RemoteSocket != null) { RemoteSocket.CloseSocket(); RemoteSocket = null; } State.NextStep = null; }
/// <summary> /// </summary> protected virtual void OnReceiveRequest(TransferItem item) { throw new NotImplementedException(); }
/// <summary> /// Pipeline step: read the HTTP request from the client, schedule /// the next step to be <c>SendRequest</c>, and call /// <c>OnReceiveRequest</c> /// </summary> protected virtual void ReadRequest() { try { RequestLine = new HttpRequestLine(BrowserSocket); } catch (IoBroken) { // The request line is the first line of a HTTP request. // If none comes in a timely fashion, then we eventually // get a IoBroken exception, which is common enough // not to be rethrown. AbortRequest(); return; } catch (SocketException) { // Ditto AbortRequest(); return; } RequestHeaders = new HttpHeaders(BrowserSocket); if (RequestLine.Method.Equals("CONNECT")) { BrowserSocket.Send501(); AbortRequest(); return; } // We call OnReceiveRequest now because Connect() will // modify the request URI. State.NextStep = SendRequest; var item = new TransferItem(); item.Headers = RequestHeaders; item.HttpRequestLine = RequestLine; item.BrowserSocket = BrowserSocket; item.RemoteSocket = RemoteSocket; item.State = State; OnReceiveRequest(item); RequestLine.URI = item.HttpRequestLine.URL; // Now we parse the request to: // 1) find out where we should connect // 2) find out whether there is a message body in the request // 3) find out whether the BrowserSocket connection should be kept-alive if (State.NextStep != null) { // Step 1) if (RelayHttpProxyHost == null) { int NewDestinationPort; string NewDestinationHost = ParseDestinationHostAndPort(RequestLine, RequestHeaders, out NewDestinationPort); Console.WriteLine("Connect to {0}", NewDestinationHost); Connect(NewDestinationHost, NewDestinationPort); } else { Connect(RelayHttpProxyHost, RelayHttpProxyPort); } // Step 2) // Find out whether the request has a message body // (RFC 2616, section 4.3); if it has, get the message length State.RequestHasMessage = false; State.RequestMessageLength = 0; State.RequestMessageChunked = false; if (RequestHeaders.TransferEncoding != null) { State.RequestHasMessage = true; State.RequestMessageChunked = Array.IndexOf(RequestHeaders.TransferEncoding, "chunked") >= 0; Debug.Assert(State.RequestMessageChunked); } else if (RequestHeaders.ContentLength != null) { State.RequestMessageLength = (uint)RequestHeaders.ContentLength; // Note: HTTP 1.0 wants "Content-Length: 0" when there // is no entity body. (RFC 1945, section 7.2) if (State.RequestMessageLength > 0) { State.RequestHasMessage = true; } } } // Step 3) State.UseDefaultPersistBrowserSocket = true; if (RequestHeaders.ProxyConnection != null) { // Note: This is not part of the HTTP 1.1 standard. See // http://homepage.ntlworld.com./jonathan.deboynepollard/FGA/web-proxy-connection-header.html foreach (string i in RequestHeaders.ProxyConnection) { if (i.Equals("close")) { State.PersistConnectionBrowserSocket = false; State.UseDefaultPersistBrowserSocket = false; break; } if (i.Equals("keep-alive")) { State.PersistConnectionBrowserSocket = true; State.UseDefaultPersistBrowserSocket = false; break; } } if (RelayHttpProxyHost == null) { RequestHeaders.ProxyConnection = null; } } // Note: we do not remove fields mentioned in the // 'Connection' header (the specs say we should). }
private bool CheckOnBlackList(TransferItem item) { // In BlackList must be rule with QBehavior = Block if (BlackList.Any(rule => rule.IsAccept(item.HttpRequestLine.URI))) { item.State.NextStep = null; return false; } return true; }
/// <summary> /// </summary> protected virtual void OnReceiveResponse(TransferItem item) { throw new NotImplementedException(); }