/// <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); }
/// <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); }
/// <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); }