/// <inheritdoc />
        public int Serialize(ref byte[] bytes, int offset, HttpResponseMessage response, IFormatterResolver formatterResolver)
        {
            if (response is null)
            {
                return(MessagePackBinary.WriteNil(ref bytes, offset));
            }

            int startOffset = offset;

            offset += MessagePackBinary.WriteFixedArrayHeaderUnsafe(ref bytes, offset, 5);

            // Version:
            offset += MessagePackBinary.WriteString(ref bytes, offset, response.Version.ToString());

            // Status Code
            offset += MessagePackBinary.WriteUInt16(ref bytes, offset, (ushort)response.StatusCode);

            // ReasonPhrase
            offset += MessagePackBinary.WriteString(ref bytes, offset, response.ReasonPhrase);

            // Headers
            KeyValuePair <string, IEnumerable <string> >[] headers = response.Headers.ToArray();
            offset += MessagePackBinary.WriteMapHeader(ref bytes, offset, headers.Length);
            foreach (KeyValuePair <string, IEnumerable <string> > kvp in headers)
            {
                // See http://www.w3.org/Protocols/rfc2616/rfc2616-sec4.html#sec4.2 Header names are not case-sensitive
                // so we normalize to lower case
                offset += MessagePackBinary.WriteString(ref bytes, offset, kvp.Key.ToLowerInvariant());

                string[] values = kvp.Value.ToArray();
                offset += MessagePackBinary.WriteFixedArrayHeaderUnsafe(ref bytes, offset, values.Length);
                foreach (string v in values)
                {
                    offset += MessagePackBinary.WriteString(ref bytes, offset, v);
                }
            }

            // NOTE we don't serialize the request, as we substitute with the supplied one in the Recording.

            // Content
            offset += HttpContentFormatter.Serialize(ref bytes, offset, response.Content);

            return(offset - startOffset);
        }
Esempio n. 2
0
        /// <inheritdoc />
        public int Serialize(ref byte[] bytes, int offset, HttpRequestMessage request,
                             IFormatterResolver formatterResolver)
        {
            if (request is null)
            {
                return(MessagePackBinary.WriteNil(ref bytes, offset));
            }

            int startOffset = offset;

            offset += MessagePackBinary.WriteFixedArrayHeaderUnsafe(ref bytes, offset, 5);

            // RequestPart.Version:
            offset += MessagePackBinary.WriteString(ref bytes, offset, request.Version.ToString());

            // RequestPart.Uri:
            offset += MessagePackBinary.WriteString(ref bytes, offset, request.RequestUri.ToString());

            // RequestPart.Method:
            offset += MessagePackBinary.WriteString(ref bytes, offset, request.Method.Method);

            // RequestPart.Headers:
            KeyValuePair <string, IEnumerable <string> >[] headers = request.Headers.ToArray();
            offset += MessagePackBinary.WriteMapHeader(ref bytes, offset, headers.Length);
            foreach (KeyValuePair <string, IEnumerable <string> > kvp in headers)
            {
                // See http://www.w3.org/Protocols/rfc2616/rfc2616-sec4.html#sec4.2 Header names are not case-sensitive
                // so we normalize to lower case
                offset += MessagePackBinary.WriteString(ref bytes, offset, kvp.Key.ToLowerInvariant());

                string[] values = kvp.Value.ToArray();
                offset += MessagePackBinary.WriteFixedArrayHeaderUnsafe(ref bytes, offset, values.Length);
                foreach (string v in values)
                {
                    offset += MessagePackBinary.WriteString(ref bytes, offset, v);
                }
            }

            // RequestPart.Content:
            offset += HttpContentFormatter.Serialize(ref bytes, offset, request.Content);
            return(offset - startOffset);
        }
Esempio n. 3
0
        /// <inheritdoc />
        public HttpRequestMessage Deserialize(byte[] bytes, int offset, IFormatterResolver formatterResolver, out int readSize)
        {
            if (MessagePackBinary.IsNil(bytes, offset))
            {
                readSize = 1;
                return(null);
            }

            int startOffset = offset;

            int count = MessagePackBinary.ReadArrayHeader(bytes, offset, out readSize);

            offset += readSize;
            if (count != 5)
            {
                throw new InvalidOperationException("Request format invalid.");
            }

            // RequestPart.Version:
            string versionStr = MessagePackBinary.ReadString(bytes, offset, out readSize);

            offset += readSize;
            if (!Version.TryParse(versionStr, out Version version))
            {
                throw new InvalidOperationException($"Request version '{versionStr}' in invalid format!");
            }

            // RequestPart.UriScheme:
            string uriStr = MessagePackBinary.ReadString(bytes, offset, out readSize);

            offset += readSize;
            if (!Uri.TryCreate(uriStr, UriKind.Absolute, out Uri uri))
            {
                throw new InvalidOperationException($"Request Uri '{uri}' could not be parsed");
            }

            // RequestPart.Method:
            HttpMethod method = HttpMethodFormatter.Instance.Deserialize(bytes, offset, formatterResolver, out readSize);

            offset += readSize;

            // Create request so we can add headers and content
            HttpRequestMessage request = new HttpRequestMessage(method, uri)
            {
                Version = version
            };

            // RequestPart.Headers:
            int headersCount = MessagePackBinary.ReadMapHeader(bytes, offset, out readSize);

            offset += readSize;

            if (headersCount > 0)
            {
                while (headersCount-- > 0)
                {
                    string key = MessagePackBinary.ReadString(bytes, offset, out readSize);
                    offset += readSize;

                    int valuesCount = MessagePackBinary.ReadArrayHeader(bytes, offset, out readSize);
                    offset += readSize;

                    // Note, we can't have an empty array, and if we tried adding one it would be ignored anyway
                    // therefore it's safe to just start looping and call add for each entry.
                    while (valuesCount-- > 0)
                    {
                        string headerValue = MessagePackBinary.ReadString(bytes, offset, out readSize);
                        offset += readSize;

                        request.Headers.TryAddWithoutValidation(key, headerValue);
                    }
                }
            }

            // RequestPart.Content:
#pragma warning disable DF0023 // Marks undisposed objects assinged to a property, originated from a method invocation.
            request.Content = HttpContentFormatter.Deserialize(bytes, offset, out readSize);
#pragma warning restore DF0023 // Marks undisposed objects assinged to a property, originated from a method invocation.

            offset += readSize;

            readSize = offset - startOffset;

            return(request);
        }
        /// <inheritdoc />
        public HttpResponseMessage Deserialize(byte[] bytes, int offset, IFormatterResolver formatterResolver, out int readSize)
        {
            if (MessagePackBinary.IsNil(bytes, offset))
            {
                readSize = 1;
                return(null);
            }

            int startOffset = offset;

            int count = MessagePackBinary.ReadArrayHeader(bytes, offset, out readSize);

            offset += readSize;
            if (count != 5)
            {
                throw new InvalidOperationException("Response format invalid.");
            }

            // Version
            string versionStr = MessagePackBinary.ReadString(bytes, offset, out readSize);

            offset += readSize;
            if (!Version.TryParse(versionStr, out Version version))
            {
                throw new InvalidOperationException($"Response version '{versionStr}' in invalid format!");
            }

            // Status Code
            HttpStatusCode statusCode = (HttpStatusCode)MessagePackBinary.ReadUInt16(bytes, offset, out readSize);

            offset += readSize;

            // ReasonPhrase
            string reasonPhrase = MessagePackBinary.ReadString(bytes, offset, out readSize);

            offset += readSize;

            // Create response so we can start updating it's headers
            HttpResponseMessage response = new HttpResponseMessage(statusCode)
            {
                Version      = version,
                ReasonPhrase = reasonPhrase
            };

            // Headers
            int headersCount = MessagePackBinary.ReadMapHeader(bytes, offset, out readSize);

            offset += readSize;

            if (headersCount > 0)
            {
                while (headersCount-- > 0)
                {
                    string key = MessagePackBinary.ReadString(bytes, offset, out readSize);
                    offset += readSize;

                    int valuesCount = MessagePackBinary.ReadArrayHeader(bytes, offset, out readSize);
                    offset += readSize;

                    // Note, we can't have an empty array, and if we tried adding one it would be ignored anyway
                    // therefore it's safe to just start looping and call add for each entry.
                    while (valuesCount-- > 0)
                    {
                        string headerValue = MessagePackBinary.ReadString(bytes, offset, out readSize);
                        offset += readSize;

                        response.Headers.TryAddWithoutValidation(key, headerValue);
                    }
                }
            }

            // Content
#pragma warning disable DF0023 // Marks undisposed objects assinged to a property, originated from a method invocation.
            response.Content = HttpContentFormatter.Deserialize(bytes, offset, out readSize);
#pragma warning restore DF0023 // Marks undisposed objects assinged to a property, originated from a method invocation.

            readSize = offset - startOffset;
            return(response);
        }
        /// <inheritdoc />
        public int Serialize(ref byte[] bytes, int offset, HttpRequestMessage request, IFormatterResolver formatterResolver)
        {
            if (request is null)
            {
                return(MessagePackBinary.WriteNil(ref bytes, offset));
            }

            int startOffset = offset;

            Uri uri = request.RequestUri;

            offset += MessagePackBinary.WriteFixedArrayHeaderUnsafe(ref bytes, offset, _parts.Count + 1);

            // Add the parts into the key output, to further mangle the hash and prevent collisions.
            offset += MessagePackBinary.WriteUInt16(ref bytes, offset, (ushort)Parts);

            foreach (RequestPart part in _parts)
            {
                switch (part)
                {
                case RequestPart.Version:
                    offset += MessagePackBinary.WriteString(ref bytes, offset, request.Version.ToString());
                    break;

                case RequestPart.UriScheme:
                    offset += MessagePackBinary.WriteString(ref bytes, offset, uri.Scheme);
                    break;

                case RequestPart.UriUserInfo:
                    offset += MessagePackBinary.WriteString(ref bytes, offset, uri.UserInfo);
                    break;

                case RequestPart.UriHost:
                    offset += MessagePackBinary.WriteString(ref bytes, offset, uri.Host);
                    break;

                case RequestPart.UriPort:
                    int port = uri.Port;
                    // Note -1 is returned for a protocol with no default port and no port specified, this
                    // should never really happen in practice.  Also port numbers should never exceed 65535.
                    // For these edge case we treat as the default port and we store 0, which is a special port
                    // That we should never explicitly use in a Http request.
                    if (port < 1 || port > ushort.MaxValue)
                    {
                        port = 0;
                    }
                    offset += MessagePackBinary.WriteUInt16(ref bytes, offset, (ushort)port);
                    break;

                case RequestPart.UriPath:
                    // Strip the preceding '/' from path.
                    offset += MessagePackBinary.WriteString(ref bytes, offset, uri.AbsolutePath.Substring(1));
                    break;

                case RequestPart.UriQuery:
                    // Strip the preceding '?' from path.
                    offset += MessagePackBinary.WriteString(ref bytes, offset, uri.Query.Substring(1));
                    break;

                case RequestPart.Method:
                    offset += MessagePackBinary.WriteString(ref bytes, offset, request.Method.Method);
                    break;

                case RequestPart.Headers:
                    KeyValuePair <string, IEnumerable <string> >[] headers = request.Headers.ToArray();
                    offset += MessagePackBinary.WriteMapHeader(ref bytes, offset, headers.Length);
                    foreach (KeyValuePair <string, IEnumerable <string> > kvp in headers)
                    {
                        // See http://www.w3.org/Protocols/rfc2616/rfc2616-sec4.html#sec4.2 Header names are not case-sensitive
                        // so we normalize to lower case
                        offset += MessagePackBinary.WriteString(ref bytes, offset, kvp.Key.ToLowerInvariant());

                        string[] values = kvp.Value.ToArray();
                        offset += MessagePackBinary.WriteFixedArrayHeaderUnsafe(ref bytes, offset, values.Length);
                        foreach (string v in values)
                        {
                            offset += MessagePackBinary.WriteString(ref bytes, offset, v);
                        }
                    }
                    break;

                case RequestPart.Content:
                    offset += HttpContentFormatter.Serialize(ref bytes, offset, request.Content);
                    break;

                default:
                    throw new ArgumentOutOfRangeException();
                }
            }

            return(offset - startOffset);
        }