public override async Task Invoke(IOwinContext context) { var contextEnv = context.Environment; Stream responseStream; if (!contextEnv.ContainsKey(CommonOwinKeys.AdditionalInfo)) { PushFunc pushPromise = null; var path = context.Request.Path.Value; var base64Req = path.Remove(0, 1); //remove leading / var isHtmlReq = Regex.Match(base64Req, Base64Regex).Success; var isJpeg = !isHtmlReq && path.EndsWith(TileExtension); var url = String.Empty; if (isHtmlReq) { var bingProcessor = new BingRequestProcessor(base64Req); var images = bingProcessor.GetTilesSoapRequestsUrls(); foreach (var image in images.Where(image => TryGetPushPromise(context, out pushPromise))) { Push(context.Request, pushPromise, image); } url = BingRequestsUrl + base64Req; } else if (isJpeg) { url = BingRequestProcessor.GetSoapUrlFromTileName(path); } else { url = BingServiceUrl + path; } if (isHtmlReq) { var responseString = new WebClient().DownloadString(url); //html on original request //TODO handle errors HtmlProcessor.PreprocessHtml(ref responseString); var response = Encoding.UTF8.GetBytes(responseString); responseStream = context.Response.Body; responseStream.Write(response, 0, response.Length); } else { DownloadVia11(url, context); } } else { var url = context.Get <string>(CommonOwinKeys.AdditionalInfo); DownloadVia11(url, context); } await Next.Invoke(context); }
protected override void Push(IOwinRequest request, PushFunc pushPromise, string pushReference) { // Copy the headers var headers = new HeaderDictionary( new Dictionary <string, string[]>(request.Headers, StringComparer.OrdinalIgnoreCase)); // Populate special HTTP2 headers headers[CommonHeaders.Method] = request.Method.ToUpper(); // TODO: Not all methods are allowed for push. Don't push, or change to GET? headers[CommonHeaders.Scheme] = request.Scheme; headers.Remove("Host"); headers[CommonHeaders.Authority] = request.Headers["Host"]; headers.Remove(CommonHeaders.ContentLength); // Push promises cannot emulate requests with bodies. // TODO: What about cache headers? If-Match, If-None-Match, If-Modified-Since, If-Unmodified-Since. // If-Match & If-None-Match are multi-value so the client could send e-tags for the primary resource and referenced resources. // If-Modified-Since and If-Unmodified-Since are single value, so it may not make sense to apply them for secondary resources. // Change the request path to the pushed resource headers[CommonHeaders.Path] = pushReference; pushPromise(headers); }
public static void ReplaceDefault(PushFunc pushFunc, GetFunc getFunc) { Set = pushFunc; Get = getFunc; }
protected abstract void Push(IOwinRequest request, PushFunc pushPromise, string pushReference);
protected bool TryGetPushPromise(IOwinContext context, out PushFunc pushPromise) { pushPromise = context.Get <PushFunc>(CommonOwinKeys.ServerPushFunc); return(pushPromise != null); }
protected bool TryGetPushPromise(IOwinContext context, out PushFunc pushPromise) { pushPromise = context.Get<PushFunc>(CommonOwinKeys.ServerPushFunc); return pushPromise != null; }
protected override void Push(IOwinRequest request, PushFunc pushPromise, string pushReference) { request.Set(CommonOwinKeys.AdditionalInfo, pushReference); // Copy the headers var headers = new HeaderDictionary( new Dictionary<string, string[]>(request.Headers, StringComparer.OrdinalIgnoreCase)); // Populate special HTTP2 headers headers[CommonHeaders.Method] = request.Method; // TODO: Not all methods are allowed for push. Don't push, or change to GET? headers[CommonHeaders.Scheme] = request.Scheme; headers.Remove("Host"); headers[CommonHeaders.Authority] = request.Headers["Host"]; headers[CommonHeaders.Path] = BingRequestProcessor.GetTileQuadFromSoapUrl(pushReference); headers.Remove(CommonHeaders.ContentLength); // Push promises cannot emulate requests with bodies. // TODO: What about cache headers? If-Match, If-None-Match, If-Modified-Since, If-Unmodified-Since. // If-Match & If-None-Match are multi-value so the client could send e-tags for the primary resource and referenced resources. // If-Modified-Since and If-Unmodified-Since are single value, so it may not make sense to apply them for secondary resources. pushPromise(headers); }
/// <summary> /// Overrides request processing logic. /// </summary> /// <param name="stream">The stream.</param> /// <param name="frame">The request header frame.</param> /// <returns></returns> protected override void ProcessRequest(Http2Stream stream, Frame frame) { /* 12 -> 8.1.3.1 * All HTTP/2 requests MUST include exactly one valid value for the * ":method", ":scheme", and ":path" header fields, unless this is a * CONNECT request (Section 8.3). An HTTP request that omits mandatory * header fields is malformed (Section 8.1.3.5). */ if (stream.Headers.GetValue(CommonHeaders.Method) == null || stream.Headers.GetValue(CommonHeaders.Path) == null || stream.Headers.GetValue(CommonHeaders.Scheme) == null) { stream.WriteRst(ResetStatusCode.ProtocolError); stream.Close(ResetStatusCode.ProtocolError); return; } Task.Factory.StartNew(async() => { try { var context = new Http2OwinMessageContext(stream); var contextEnv = context.OwinContext.Environment; PushFunc pushDelegate = null; pushDelegate = async pairs => { var promisedStream = CreateStream(); //assume that we have already received endStream promisedStream.HalfClosedLocal = true; stream.WritePushPromise(pairs, promisedStream.Id); var headers = new HeadersList(pairs); promisedStream.Headers.AddRange(headers); var http2MsgCtx = new Http2OwinMessageContext(promisedStream); var http2PushCtx = http2MsgCtx.OwinContext; http2PushCtx.Set(CommonOwinKeys.ServerPushFunc, pushDelegate); //pass add info from parent to child context. This info can store //reference table for example or something els that should be passed from //client request into child push requests. if (contextEnv.ContainsKey(CommonOwinKeys.AdditionalInfo)) { http2PushCtx.Set(CommonOwinKeys.AdditionalInfo, contextEnv[CommonOwinKeys.AdditionalInfo]); } await _next(http2PushCtx); http2MsgCtx.FinishResponse(); }; context.OwinContext.Set(CommonOwinKeys.ServerPushFunc, pushDelegate); context.OwinContext.Set(CommonOwinKeys.EnableServerPush, _isPushEnabled); await _next(context.OwinContext); context.FinishResponse(); } catch (Exception ex) { EndResponse(stream, ex); } }); }