internal HttpInterceptionResponse Build() { var response = new HttpInterceptionResponse() { ContentFactory = _contentFactory ?? EmptyContentFactory, ContentMatcher = _contentMatcher, ContentStream = _contentStream, ContentMediaType = _mediaType, HasCustomPort = _hasCustomPort, IgnoreHost = _ignoreHost, IgnorePath = _ignorePath, IgnoreQuery = _ignoreQuery, Method = _method, OnIntercepted = _onIntercepted, Priority = _priority, ReasonPhrase = _reasonPhrase, RequestUri = _uriBuilder.Uri, StatusCode = _statusCode, UserMatcher = _requestMatcher, Version = _version, }; if (_requestHeaders?.Count > 0) { var headers = new Dictionary <string, IEnumerable <string> >(); foreach (var pair in _requestHeaders) { headers[pair.Key] = pair.Value; } response.RequestHeaders = headers; } if (_responseHeaders?.Count > 0) { var headers = new Dictionary <string, IEnumerable <string> >(); foreach (var pair in _responseHeaders) { headers[pair.Key] = pair.Value; } response.ResponseHeaders = headers; } if (_contentHeaders?.Count > 0) { var headers = new Dictionary <string, IEnumerable <string> >(); foreach (var pair in _contentHeaders) { headers[pair.Key] = pair.Value; } response.ContentHeaders = headers; } return(response); }
private bool TryGetResponse(HttpRequestMessage request, out HttpInterceptionResponse response) { response = _mappings.Values .OrderByDescending((p) => p.Priority.HasValue) .ThenBy((p) => p.Priority) .Where((p) => p.InternalMatcher.IsMatch(request)) .FirstOrDefault(); return(response != null); }
/// <summary> /// Registers an HTTP request interception, replacing any existing registration. /// </summary> /// <param name="builder">The <see cref="HttpRequestInterceptionBuilder"/> to use to create the registration.</param> /// <returns> /// The current <see cref="HttpClientInterceptorOptions"/>. /// </returns> /// <exception cref="ArgumentNullException"> /// <paramref name="builder"/> is <see langword="null"/>. /// </exception> public HttpClientInterceptorOptions Register(HttpRequestInterceptionBuilder builder) { if (builder == null) { throw new ArgumentNullException(nameof(builder)); } HttpInterceptionResponse interceptor = builder.Build(); ConfigureMatcherAndRegister(interceptor); return(this); }
/// <summary> /// Deregisters an existing HTTP request interception, if it exists. /// </summary> /// <param name="builder">The HTTP interception to deregister.</param> /// <returns> /// The current <see cref="HttpClientInterceptorOptions"/>. /// </returns> /// <exception cref="ArgumentNullException"> /// <paramref name="builder"/> is <see langword="null"/>. /// </exception> /// <remarks> /// If <paramref name="builder"/> has been reconfigured since it was used /// to register a previous HTTP request interception it will not remove that /// registration. In such cases, use <see cref="Clear"/>. /// </remarks> public HttpClientInterceptorOptions Deregister(HttpRequestInterceptionBuilder builder) { if (builder == null) { throw new ArgumentNullException(nameof(builder)); } HttpInterceptionResponse interceptor = builder.Build(); string key = BuildKey(interceptor); _mappings.Remove(key); return(this); }
/// <summary> /// Registers an HTTP request interception, replacing any existing registration. /// </summary> /// <param name="builder">The <see cref="HttpRequestInterceptionBuilder"/> to use to create the registration.</param> /// <returns> /// The current <see cref="HttpClientInterceptorOptions"/>. /// </returns> /// <exception cref="ArgumentNullException"> /// <paramref name="builder"/> is <see langword="null"/>. /// </exception> public HttpClientInterceptorOptions Register(HttpRequestInterceptionBuilder builder) { if (builder == null) { throw new ArgumentNullException(nameof(builder)); } HttpInterceptionResponse interceptor = builder.Build(); string key = BuildKey(interceptor.Method, interceptor.RequestUri); _mappings[key] = interceptor; return(this); }
private void ConfigureMatcherAndRegister(HttpInterceptionResponse registration) { RequestMatcher matcher; if (registration.UserMatcher != null) { matcher = new DelegatingMatcher(registration.UserMatcher); } else { matcher = new RegistrationMatcher(registration, _comparer); } registration.InternalMatcher = matcher; string key = BuildKey(registration); _mappings[key] = registration; }
/// <summary> /// Registers an HTTP request interception, replacing any existing registration. /// </summary> /// <param name="method">The HTTP method to register an interception for.</param> /// <param name="uri">The request URI to register an interception for.</param> /// <param name="contentStream">A delegate to a method that returns the response stream.</param> /// <param name="statusCode">The optional HTTP status code to return.</param> /// <param name="mediaType">The optional media type for the content-type.</param> /// <param name="responseHeaders">The optional HTTP response headers for the response.</param> /// <param name="contentHeaders">The optional HTTP response headers for the content.</param> /// <param name="onIntercepted">An optional delegate to invoke when the HTTP message is intercepted.</param> /// <returns> /// The current <see cref="HttpClientInterceptorOptions"/>. /// </returns> /// <exception cref="ArgumentNullException"> /// <paramref name="method"/>, <paramref name="uri"/> or <paramref name="contentStream"/> is <see langword="null"/>. /// </exception> public HttpClientInterceptorOptions Register( HttpMethod method, Uri uri, Func <Task <Stream> > contentStream, HttpStatusCode statusCode = HttpStatusCode.OK, string mediaType = JsonMediaType, IEnumerable <KeyValuePair <string, IEnumerable <string> > > responseHeaders = null, IEnumerable <KeyValuePair <string, IEnumerable <string> > > contentHeaders = null, Func <HttpRequestMessage, Task> onIntercepted = null) { if (method == null) { throw new ArgumentNullException(nameof(method)); } if (uri == null) { throw new ArgumentNullException(nameof(uri)); } if (contentStream == null) { throw new ArgumentNullException(nameof(contentStream)); } var interceptor = new HttpInterceptionResponse() { ContentStream = contentStream, ContentHeaders = contentHeaders, ContentMediaType = mediaType, Method = method, OnIntercepted = onIntercepted, RequestUri = uri, ResponseHeaders = responseHeaders, StatusCode = statusCode }; string key = BuildKey(method, uri); _mappings[key] = interceptor; return(this); }
/// <summary> /// Registers an HTTP request interception for a stream, replacing any existing registration. /// </summary> /// <param name="method">The HTTP method to register an interception for.</param> /// <param name="uri">The request URI to register an interception for.</param> /// <param name="contentStream">A delegate to a method that returns the response stream.</param> /// <param name="statusCode">The optional HTTP status code to return.</param> /// <param name="mediaType">The optional media type for the content-type.</param> /// <param name="responseHeaders">The optional HTTP response headers for the response.</param> /// <param name="contentHeaders">The optional HTTP response headers for the content.</param> /// <param name="onIntercepted">An optional delegate to invoke when the HTTP message is intercepted.</param> /// <returns> /// The current <see cref="HttpClientInterceptorOptions"/>. /// </returns> /// <exception cref="ArgumentNullException"> /// <paramref name="method"/>, <paramref name="uri"/> or <paramref name="contentStream"/> is <see langword="null"/>. /// </exception> public HttpClientInterceptorOptions RegisterStream( HttpMethod method, Uri uri, Func <Task <Stream> > contentStream, HttpStatusCode statusCode = HttpStatusCode.OK, string mediaType = JsonMediaType, IEnumerable <KeyValuePair <string, IEnumerable <string> > >?responseHeaders = null, IEnumerable <KeyValuePair <string, IEnumerable <string> > >?contentHeaders = null, Func <HttpRequestMessage, Task>?onIntercepted = null) { if (method == null) { throw new ArgumentNullException(nameof(method)); } if (uri == null) { throw new ArgumentNullException(nameof(uri)); } if (contentStream == null) { throw new ArgumentNullException(nameof(contentStream)); } var interceptor = new HttpInterceptionResponse() { ContentStream = contentStream, ContentHeaders = contentHeaders, ContentMediaType = mediaType, Method = method, OnIntercepted = DelegateHelpers.ConvertToBooleanTask(onIntercepted), RequestUri = uri, ResponseHeaders = responseHeaders, StatusCode = statusCode, }; ConfigureMatcherAndRegister(interceptor); return(this); }
internal HttpInterceptionResponse Build() { var response = new HttpInterceptionResponse() { ContentFactory = _contentFactory ?? EmptyContentFactory, ContentStream = _contentStream, ContentMediaType = _mediaType, Method = _method, OnIntercepted = _onIntercepted, ReasonPhrase = _reasonPhrase, RequestUri = _uriBuilder.Uri, StatusCode = _statusCode, Version = _version, }; if (_responseHeaders?.Count > 0) { var headers = new Dictionary <string, IEnumerable <string> >(); foreach (var pair in _responseHeaders) { headers[pair.Key] = pair.Value; } response.ResponseHeaders = headers; } if (_contentHeaders?.Count > 0) { var headers = new Dictionary <string, IEnumerable <string> >(); foreach (var pair in _contentHeaders) { headers[pair.Key] = pair.Value; } response.ContentHeaders = headers; } return(response); }
/// <summary> /// Builds the mapping key to use for the specified intercepted HTTP request. /// </summary> /// <param name="interceptor">The configured HTTP interceptor.</param> /// <returns> /// A <see cref="string"/> to use as the key for the interceptor registration. /// </returns> private static string BuildKey(HttpInterceptionResponse interceptor) { if (interceptor.UserMatcher != null || interceptor.ContentMatcher != null) { // Use the internal matcher's hash code as UserMatcher (a delegate) // will always return the hash code. See https://stackoverflow.com/q/6624151/1064169 return($"CUSTOM:{interceptor.InternalMatcher!.GetHashCode().ToString(CultureInfo.InvariantCulture)}"); } var builderForKey = new UriBuilder(interceptor.RequestUri); string keyPrefix = string.Empty; if (interceptor.IgnoreHost) { builderForKey.Host = "*"; keyPrefix = "IGNOREHOST;"; } if (interceptor.IgnorePath) { builderForKey.Path = string.Empty; keyPrefix += "IGNOREPATH;"; } if (interceptor.IgnoreQuery) { builderForKey.Query = string.Empty; keyPrefix += "IGNOREQUERY;"; } if (!interceptor.HasCustomPort) { builderForKey.Port = -1; } return($"{keyPrefix};{interceptor.Method!.Method}:{builderForKey}"); }
/// <summary> /// Deregisters an existing HTTP request interception, if it exists. /// </summary> /// <param name="method">The HTTP method to deregister.</param> /// <param name="uri">The request URI to deregister.</param> /// <returns> /// The current <see cref="HttpClientInterceptorOptions"/>. /// </returns> /// <exception cref="ArgumentNullException"> /// <paramref name="method"/> or <paramref name="uri"/> is <see langword="null"/>. /// </exception> public HttpClientInterceptorOptions Deregister(HttpMethod method, Uri uri) { if (method == null) { throw new ArgumentNullException(nameof(method)); } if (uri == null) { throw new ArgumentNullException(nameof(uri)); } var interceptor = new HttpInterceptionResponse() { Method = method, RequestUri = uri, }; string key = BuildKey(interceptor); _mappings.Remove(key); return(this); }
private static async Task <HttpResponseMessage> BuildResponseAsync(HttpRequestMessage request, HttpInterceptionResponse response) { var result = new HttpResponseMessage(response.StatusCode); try { result.RequestMessage = request; if (response.ReasonPhrase != null) { result.ReasonPhrase = response.ReasonPhrase; } if (response.Version != null) { result.Version = response.Version; } if (response.ContentStream != null) { result.Content = new StreamContent(await response.ContentStream().ConfigureAwait(false) ?? Stream.Null); } else { byte[] content = await response.ContentFactory !().ConfigureAwait(false) ?? Array.Empty <byte>(); result.Content = new ByteArrayContent(content); } PopulateHeaders(result.Content.Headers, response.ContentHeaders); // Do not overwrite a custom Content-Type header if already set if (!result.Content.Headers.TryGetValues("content-type", out var contentType)) { result.Content.Headers.ContentType = new MediaTypeHeaderValue(response.ContentMediaType); } PopulateHeaders(result.Headers, response.ResponseHeaders); } catch (Exception) { result.Dispose(); throw; } return(result); }