コード例 #1
0
        /// <summary>
        /// Returns a <see cref="string"/> that can be used to compare a URI against another.
        /// </summary>
        /// <param name="registration">The <see cref="HttpInterceptionResponse"/> to use to build the URI.</param>
        /// <param name="uri">The optional <see cref="Uri"/> to use to build the URI if not using the one associated with <paramref name="registration"/>.</param>
        /// <returns>
        /// A <see cref="string"/> containing the URI to use for string comparisons for URIs.
        /// </returns>
        private static string GetUriStringForMatch(HttpInterceptionResponse registration, Uri uri = null)
        {
            var builder = new UriBuilder(uri ?? registration.RequestUri);

            if (!registration.HasCustomPort)
            {
                builder.Port = -1;
            }

            if (registration.IgnoreHost)
            {
                builder.Host = "*";
            }

            if (registration.IgnorePath)
            {
                builder.Path = string.Empty;
            }

            if (registration.IgnoreQuery)
            {
                builder.Query = string.Empty;
            }

            return(builder.ToString());
        }
コード例 #2
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);
    }
コード例 #3
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);
    }
コード例 #4
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;
    }
コード例 #5
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);
    }
コード例 #6
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}");
    }
コード例 #7
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);
    }
コード例 #8
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);
    }
コード例 #9
0
 /// <summary>
 /// Initializes a new instance of the <see cref="RegistrationMatcher"/> class.
 /// </summary>
 /// <param name="registration">The <see cref="HttpInterceptionResponse"/> to use for matching.</param>
 /// <param name="comparer">The string comparer to use to compare URIs.</param>
 internal RegistrationMatcher(HttpInterceptionResponse registration, IEqualityComparer <string> comparer)
 {
     _comparer     = comparer;
     _registration = registration;
     _expected     = GetUriStringForMatch(registration);
 }