예제 #1
0
 internal Enumerator(ProtoRequestHeaders collection)
 {
     _collection        = collection;
     _bits              = collection._bits;
     _next              = 0;
     _current           = default(KeyValuePair <string, StringValues>);
     _hasUnknown        = collection.MaybeUnknown != null;
     _unknownEnumerator = _hasUnknown
         ? collection.MaybeUnknown.GetEnumerator()
         : default(Dictionary <string, StringValues> .Enumerator);
 }
예제 #2
0
        public static MessageBody For(
            ProtoVersion httpVersion,
            ProtoRequestHeaders headers,
            Proto1Connection context)
        {
            // see also http://tools.ietf.org/html/rfc2616#section-4.4
            var keepAlive = httpVersion != ProtoVersion.Proto10;

            var upgrade = false;

            if (headers.HasConnection)
            {
                var connectionOptions = ProtoHeaders.ParseConnection(headers.HeaderConnection);

                upgrade   = (connectionOptions & ConnectionOptions.Upgrade) == ConnectionOptions.Upgrade;
                keepAlive = (connectionOptions & ConnectionOptions.KeepAlive) == ConnectionOptions.KeepAlive;
            }

            if (upgrade)
            {
                if (headers.HeaderTransferEncoding.Count > 0 || (headers.ContentLength.HasValue && headers.ContentLength.Value != 0))
                {
                    BadProtoRequestException.Throw(RequestRejectionReason.UpgradeRequestCannotHavePayload);
                }

                return(new Proto1UpgradeMessageBody(context));
            }

            if (headers.HasTransferEncoding)
            {
                var transferEncoding = headers.HeaderTransferEncoding;
                var transferCoding   = ProtoHeaders.GetFinalTransferCoding(transferEncoding);

                // https://tools.ietf.org/html/rfc7230#section-3.3.3
                // If a Transfer-Encoding header field
                // is present in a request and the chunked transfer coding is not
                // the final encoding, the message body length cannot be determined
                // reliably; the server MUST respond with the 400 (Bad Request)
                // status code and then close the connection.
                if (transferCoding != TransferCoding.Chunked)
                {
                    BadProtoRequestException.Throw(RequestRejectionReason.FinalTransferCodingNotChunked, transferEncoding);
                }

                // TODO may push more into the wrapper rather than just calling into the message body
                // NBD for now.
                return(new Proto1ChunkedEncodingMessageBody(keepAlive, context));
            }

            if (headers.ContentLength.HasValue)
            {
                var contentLength = headers.ContentLength.Value;

                if (contentLength == 0)
                {
                    return(keepAlive ? MessageBody.ZeroContentLengthKeepAlive : MessageBody.ZeroContentLengthClose);
                }

                return(new Proto1ContentLengthMessageBody(keepAlive, contentLength, context));
            }

            // If we got here, request contains no Content-Length or Transfer-Encoding header.
            // Reject with 411 Length Required.
            if (context.Method == ProtoMethod.Post || context.Method == ProtoMethod.Put)
            {
                var requestRejectionReason = httpVersion == ProtoVersion.Proto11 ? RequestRejectionReason.LengthRequired : RequestRejectionReason.LengthRequiredProto10;
                BadProtoRequestException.Throw(requestRejectionReason, context.Method);
            }

            return(keepAlive ? MessageBody.ZeroContentLengthKeepAlive : MessageBody.ZeroContentLengthClose);
        }