Пример #1
0
        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);
        }
Пример #2
0
        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);
        }
Пример #3
0
        /// <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);
        }
Пример #4
0
        /// <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);
        }
Пример #6
0
        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);
        }
Пример #8
0
        /// <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);
        }
Пример #9
0
        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);
        }
Пример #10
0
        /// <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}");
        }
Пример #11
0
        /// <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);
        }
Пример #12
0
        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);
        }