Exemplo n.º 1
0
        /// <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);
                }
            });
        }