Пример #1
0
        // Returns the request offset into the builder buffer
        public UInt32 Build(ExtendedByteBuilder builder, HttpClient client, Boolean keepAlive)
        {
            if (method == null)
            {
                throw new InvalidOperationException("The HttpRequest method must be set");
            }
            //
            // <METHOD> <resource> HTTP/1.1\r\n
            //
            builder.AppendAscii(method); // Todo: Should I verify that method is ascii beforehand?
            builder.AppendAscii(' ');
            if (!String.IsNullOrEmpty(resource))
            {
                builder.AppendAscii(resource); // Todo: Should I verify that resource is ascii beforehand?
            }
            else if (resourceAppender != null)
            {
                resourceAppender(builder);
            }
            else
            {
                throw new InvalidOperationException("The HttpRequest resource must be set");
            }
            builder.Append(VersionPart);
            //
            // Host: <host>[:<port>]
            //
            builder.Append(Http.HostHeaderPrefix);
            if (overrideHostHeader != null)
            {
                builder.AppendAscii(overrideHostHeader);
            }
            else
            {
                builder.AppendAscii(client.IPOrHost);
                if (client.Port != 80 || forcePortInHostHeader)
                {
                    builder.AppendAscii(':');
                    builder.AppendNumber(client.Port, 10);
                }
            }
            builder.Append(Http.Newline);
            //
            // Header: Content-Length
            //
            // TODO: when do I not need a Content-Length?
            UInt32 contentLengthOffset = UInt32.MaxValue;

            {
                Boolean hasContent;
                UInt32  contentLength;
                if (content.contentAsBytes != null)
                {
                    hasContent    = true;
                    contentLength = (UInt32)content.contentAsBytes.Length;
                }
                else if (content.contentAsString != null)
                {
                    hasContent    = true;
                    contentLength = content.contentAsStringEncoder.GetEncodeLength(content.contentAsString);
                }
                else if (content.contentAppender != null)
                {
                    hasContent    = true;
                    contentLength = UInt32.MaxValue; // Placeholder
                }
                else
                {
                    hasContent    = false;
                    contentLength = 0;
                }
                if (hasContent)
                {
                    builder.Append(Http.ContentLengthHeaderPrefix);
                    contentLengthOffset = builder.contentLength;
                    builder.AppendNumber(contentLength);
                    builder.Append(Http.Newline);
                    if (content.contentType != null)
                    {
                        builder.Append(Http.ContentTypeHeaderPrefix);
                        builder.AppendAscii(content.contentType);
                        builder.Append(Http.Newline);
                    }
                }
            }
            //
            // Header: Connection
            //
            if (keepAlive)
            {
                builder.Append(Http.ConnectionHeaderPrefix);
                builder.Append(Http.ConnectionKeepAlive);
                builder.Append(Http.Newline);
            }
            else
            {
                builder.Append(Http.ConnectionHeaderPrefix);
                builder.Append(Http.ConnectionClose);
                builder.Append(Http.Newline);
            }
            //
            // Extra Headers
            //
            if (extraHeaders != null)
            {
                builder.Append(extraHeaders);
            }
            if (extraHeadersAppender != null)
            {
                extraHeadersAppender(builder);
            }
            //
            // End of Headers \r\n\r\n
            //
            builder.Append(Http.Newline);
            //
            // Content
            //
            if (content.contentAsBytes != null)
            {
                builder.Append(content.contentAsBytes);
            }
            else if (content.contentAsString != null)
            {
                builder.Append(content.contentAsStringEncoder, content.contentAsString);
            }
            else if (content.contentAppender != null)
            {
                //
                // Get the content
                //
                var contentStart = builder.contentLength;
                content.contentAppender(builder);
                UInt32 contentLength = builder.contentLength - contentStart;
                // Patch the request with the new content length
                UInt32 shift; // Shift everything before Content-Length: value to the right
                if (contentLength == 0)
                {
                    builder.bytes[contentLengthOffset + 9] = (Byte)'0';
                    shift = 9; // Shift everything
                }
                else
                {
                    shift = 9;
                    var temp = contentLength;
                    while (true)
                    {
                        builder.bytes[contentLengthOffset + shift] = (Byte)('0' + (temp % 10));
                        temp = temp / 10;
                        if (temp == 0)
                        {
                            break;
                        }
                        shift--;
                    }
                }
                // Shift the beginning of the request to compensate for a smaller Content-Length
                if (shift > 0)
                {
                    var offset = contentLengthOffset - 1;
                    while (true)
                    {
                        builder.bytes[offset + shift] = builder.bytes[offset];
                        if (offset == 0)
                        {
                            break;
                        }
                        offset--;
                    }
                }
                return(shift);
            }
            return(0);
        }