All Projects → justeat → Httpclient Interception

justeat / Httpclient Interception

Licence: apache-2.0
A .NET Standard library for intercepting server-side HTTP dependencies

Projects that are alternatives of or similar to Httpclient Interception

Headerpropagation
ASP.NET Core middleware to propagate HTTP headers from the incoming request to the outgoing HTTP Client requests. This is a backport to ASP.NET Core 2.1 (and 2.2) of the ASP.NET Core HeaderPropagation middleware I had recently contributed to the ASP.NET Core project.
Stars: ✭ 23 (-78.7%)
Mutual labels:  netstandard, httpclient
Fluentlyhttpclient
Http Client for .NET Standard with fluent APIs which are intuitive, easy to use and also highly extensible.
Stars: ✭ 73 (-32.41%)
Mutual labels:  netstandard, httpclient
Solr Express
A simple and lightweight query .NET library for Solr, in a controlled, buildable and fail fast way.
Stars: ✭ 66 (-38.89%)
Mutual labels:  netstandard
Shapes
📐 Net standard geometry/shape manipulation library, can be used to merge / split shapes
Stars: ✭ 95 (-12.04%)
Mutual labels:  netstandard
Resty
The minimalist framework of RESTful(server and client) - Resty
Stars: ✭ 1,268 (+1074.07%)
Mutual labels:  httpclient
Rest Client
A tool for automated testing REST API, generating exquisite testing report and REST API documentation.
Stars: ✭ 1,181 (+993.52%)
Mutual labels:  httpclient
Entityframeworkcore.dataencryption
A plugin for Microsoft.EntityFrameworkCore to add support of encrypted fields using built-in or custom encryption providers.
Stars: ✭ 88 (-18.52%)
Mutual labels:  netstandard
Httpclientfactory
safe HttpClient For netcore And netframework
Stars: ✭ 64 (-40.74%)
Mutual labels:  httpclient
Bookfx
Composing Excel spreadsheets based on a tree of nested components like the HTML DOM.
Stars: ✭ 102 (-5.56%)
Mutual labels:  netstandard
House
微信公众号:程序员博博。有完整版的PDF下载。
Stars: ✭ 85 (-21.3%)
Mutual labels:  httpclient
Nlua
Bridge between Lua and the .NET.
Stars: ✭ 1,326 (+1127.78%)
Mutual labels:  netstandard
Aspnetcore Practice
ASP.NET Core 專案練習集合,ASP.NET Core Practice Projects
Stars: ✭ 80 (-25.93%)
Mutual labels:  httpclient
Api Client Generator
Angular REST API client generator from Swagger YAML or JSON file with camel case settigs
Stars: ✭ 92 (-14.81%)
Mutual labels:  httpclient
Cashew
A simple and elegant yet powerful HTTP client cache for .NET
Stars: ✭ 70 (-35.19%)
Mutual labels:  httpclient
Mailmergelib
MailMergeLib is a mail message client library which provides comfortable mail merge capabilities for text, inline images and attachments, as well as good throughput and fault tolerance for sending mail messages.
Stars: ✭ 97 (-10.19%)
Mutual labels:  netstandard
Abotx
Cross Platform C# Web crawler framework, headless browser, parallel crawler. Please star this project! +1.
Stars: ✭ 63 (-41.67%)
Mutual labels:  netstandard
Zigbeenet
A .NET Standard library for working with ZigBee
Stars: ✭ 76 (-29.63%)
Mutual labels:  netstandard
Neatinput
A .NET standard project which aims to make keyboard and mouse input monitoring easy on Windows and eventually Linux.
Stars: ✭ 89 (-17.59%)
Mutual labels:  netstandard
Utf Unknown
Charset detector build in C# - .NET Core 2-3, .NET standard 1-2 & .NET 4+
Stars: ✭ 103 (-4.63%)
Mutual labels:  netstandard
Yahoofinanceapi
A handy Yahoo! Finance api wrapper, based on .NET Standard 2.0
Stars: ✭ 99 (-8.33%)
Mutual labels:  netstandard

HttpClient Interception

A .NET Standard library for intercepting server-side HTTP dependencies.

NuGet version

Linux/macOS Windows Linux/macOS/Windows
Build Status Build status Build status codecov Azure Pipelines build status
Build History Build history Build history Build history

Introduction

This library provides functionality for intercepting HTTP requests made using the HttpClient class in code targeting .NET Standard 2.0 (and later), and .NET Framework 4.6.1 and 4.7.2.

The primary use-case is for providing stub responses for use in tests for applications, such as an ASP.NET Core application, to drive your functional test scenarios.

The library is based around an implementation of DelegatingHandler, which can either be used directly as an implementation of HttpMessageHandler, or can be provided to instances of HttpClient. This also allows it to be registered via Dependency Injection to make it available for use in code under test without the application itself requiring any references to JustEat.HttpClientInterception or any custom abstractions of HttpClient.

This design means that no HTTP server needs to be hosted to proxy traffic to/from, so does not consume any additional system resources, such as needing to bind a port for HTTP traffic, making it lightweight to use.

Installation

To install the library from NuGet using the .NET SDK run:

dotnet add package JustEat.HttpClientInterception

Basic Examples

Request Interception

Fluent API

Below is a minimal example of intercepting an HTTP GET request to an API for a JSON resource to return a custom response using the fluent API:

// using JustEat.HttpClientInterception;

var options = new HttpClientInterceptorOptions();

var builder = new HttpRequestInterceptionBuilder()
    .Requests()
    .ForHost("public.je-apis.com")
    .ForPath("terms")
    .Responds()
    .WithJsonContent(new { Id = 1, Link = "https://www.just-eat.co.uk/privacy-policy" })
    .RegisterWith(options);

var client = options.CreateHttpClient();

// The value of json will be "{\"Id\":1,\"Link\":\"https://www.just-eat.co.uk/privacy-policy\"}"
var json = await client.GetStringAsync("http://public.je-apis.com/terms");

HttpRequestInterceptionBuilder objects are mutable, so properties can be freely changed once a particular setup has been registered with an instance of HttpClientInterceptorOptions as the state is captured at the point of registration. This allows multiple responses and paths to be configured from a single HttpRequestInterceptionBuilder instance where multiple registrations against a common hostname.

HTTP Bundle Files

HTTP requests to intercept can also be configured in an "HTTP bundle" file, which can be used to store the HTTP requests to intercept and their corresponding responses as JSON.

This functionality is analogous to our Shock pod for iOS.

JSON

Below is an example bundle file, which can return content in formats such as a string, JSON and base64-encoded data.

The full JSON schema for HTTP bundle files can be found here.

{
  "$schema": "https://raw.githubusercontent.com/justeat/httpclient-interception/master/src/HttpClientInterception/Bundles/http-request-bundle-schema.json",
  "id": "my-bundle",
  "comment": "A bundle of HTTP requests",
  "items": [
    {
      "id": "home",
      "comment": "Returns the home page",
      "uri": "https://www.just-eat.co.uk",
      "contentString": "<html><head><title>Just Eat</title></head></html>"
    },
    {
      "id": "terms",
      "comment": "Returns the Ts & Cs",
      "uri": "https://public.je-apis.com/terms",
      "contentFormat": "json",
      "contentJson": {
        "Id": 1,
        "Link": "https://www.just-eat.co.uk/privacy-policy"
      }
    }
  ]
}
Code
// using JustEat.HttpClientInterception;

var options = new HttpClientInterceptorOptions().RegisterBundle("my-bundle.json");

var client = options.CreateHttpClient();

// The value of html will be "<html><head><title>Just Eat</title></head></html>"
var html = await client.GetStringAsync("https://www.just-eat.co.uk");

// The value of json will be "{\"Id\":1,\"Link\":\"https://www.just-eat.co.uk/privacy-policy\"}"
var json = await client.GetStringAsync("http://public.je-apis.com/terms");

Further examples of using HTTP bundles can be found in the tests, such as for changing the response code, the HTTP method, and matching to HTTP requests based on the request headers.

Fault Injection

Below is a minimal example of intercepting a request to inject an HTTP fault:

// using JustEat.HttpClientInterception;

var options = new HttpClientInterceptorOptions();

var builder = new HttpRequestInterceptionBuilder()
    .Requests()
    .ForHost("public.je-apis.com")
    .WithStatus(HttpStatusCode.InternalServerError)
    .RegisterWith(options);

var client = options.CreateHttpClient();

// Throws an HttpRequestException
await client.GetStringAsync("http://public.je-apis.com");

Registering Request Interception When Using IHttpClientFactory

If you are using IHttpClientFactory to register HttpClient for Dependency Injection in a .NET Core 2.1 application (or later), you can implement a custom IHttpMessageHandlerBuilderFilter to register during test setup, which makes an instance of HttpClientInterceptorOptions available to inject an HTTP handler.

A working example of this approach can be found in the sample application.

using Microsoft.Extensions.Http;

public class InterceptionFilter : IHttpMessageHandlerBuilderFilter
{
    private readonly HttpClientInterceptorOptions _options;

    internal InterceptionFilter(HttpClientInterceptorOptions options)
    {
        _options = options;
    }

    public Action<HttpMessageHandlerBuilder> Configure(Action<HttpMessageHandlerBuilder> next)
    {
        return (builder) =>
        {
            // Run any actions the application has configured for itself
            next(builder);

            // Add the interceptor as the last message handler
            builder.AdditionalHandlers.Add(_options.CreateHttpMessageHandler());
        };
    }
}
var options = new HttpClientInterceptorOptions();
services.AddSingleton<IHttpMessageHandlerBuilderFilter, InterceptionFilter>(
    (_) => new InterceptionFilter(options));

Setting Up HttpClient for Dependency Injection Manually

Below is an example of setting up IServiceCollection to register HttpClient for Dependency Injection in a manner that allows tests to use HttpClientInterceptorOptions to intercept HTTP requests. Similar approaches can be used with other IoC containers.

You may wish to consider registering HttpClient as a singleton, rather than as transient, if you do not use properties such as BaseAddress on instances of HttpClient. This allows the same instance to be used throughout the application, which improves performance and resource utilisation under heavy server load. If using a singleton instance, ensure that you manage the lifetime of your message handlers appropriately so they are not disposed of incorrectly and update the registration for your HttpClient instance appropriately.

services.AddTransient(
    (serviceProvider) =>
    {
        // Create a handler that makes actual HTTP calls
        HttpMessageHandler handler = new HttpClientHandler();

        // Have any delegating handlers been registered?
        var handlers = serviceProvider
            .GetServices<DelegatingHandler>()
            .ToList();

        if (handlers.Count > 0)
        {
            // Attach the initial handler to the first delegating handler
            DelegatingHandler previous = handlers.First();
            previous.InnerHandler = handler;

            // Chain any remaining handlers to each other
            foreach (DelegatingHandler next in handlers.Skip(1))
            {
                next.InnerHandler = previous;
                previous = next;
            }

            // Replace the initial handler with the last delegating handler
            handler = previous;
        }

        // Create the HttpClient using the inner HttpMessageHandler
        return new HttpClient(handler);
    });

Then in the test project register HttpClientInterceptorOptions to provide an implementation of DelegatingHandler. If using a singleton for HttpClient as described above, update the registration for the tests appropriately so that the message handler is shared.

var options = new HttpClientInterceptorOptions();

var server = new WebHostBuilder()
    .UseStartup<Startup>()
    .ConfigureServices(
        (services) => services.AddTransient((_) => options.CreateHttpMessageHandler()))
    .Build();

server.Start();

Further Examples

Further examples of using the library can be found by following the links below:

  1. Example tests
  2. Sample application with tests
  3. This library's own tests

Benchmarks

Generated with the Benchmarks project using BenchmarkDotNet using commit c31abf3 on 02/05/2020.

BenchmarkDotNet=v0.12.1, OS=Windows 10.0.18363.815 (1909/November2018Update/19H2)
Intel Core i9-9980HK CPU 2.40GHz, 1 CPU, 16 logical and 8 physical cores
.NET Core SDK=3.1.201
  [Host]     : .NET Core 3.1.3 (CoreCLR 4.700.20.11803, CoreFX 4.700.20.12001), X64 RyuJIT
  DefaultJob : .NET Core 3.1.3 (CoreCLR 4.700.20.11803, CoreFX 4.700.20.12001), X64 RyuJIT


Method Mean Error StdDev Gen 0 Gen 1 Gen 2 Allocated
GetBytes 3.374 μs 0.0156 μs 0.0146 μs 0.4044 - - 3.33 KB
GetHtml 3.590 μs 0.0150 μs 0.0133 μs 0.3967 - - 3.25 KB
GetJsonNewtonsoftJson 9.316 μs 0.1269 μs 0.1125 μs 1.0834 - - 8.95 KB
GetJsonSystemTextJson 7.074 μs 0.0524 μs 0.0490 μs 0.6866 - - 5.7 KB
GetStream 34.545 μs 0.3502 μs 0.3275 μs 0.4272 - - 3.66 KB
RefitNewtonsoftJson 25.978 μs 0.1982 μs 0.1757 μs 1.7700 - - 14.93 KB
RefitSystemTextJson 23.343 μs 0.2181 μs 0.2040 μs 1.0986 - - 9.46 KB

Feedback

Any feedback or issues can be added to the issues for this project in GitHub.

Repository

The repository is hosted in GitHub: https://github.com/justeat/httpclient-interception.git

Building and Testing

Compiling the library yourself requires Git and the .NET Core SDK to be installed (version 3.1.102 or later).

To build and test the library locally from a terminal/command-line, run one of the following set of commands:

Linux/macOS

git clone https://github.com/justeat/httpclient-interception.git
cd httpclient-interception
./build.sh

Windows

git clone https://github.com/justeat/httpclient-interception.git
cd httpclient-interception
.\Build.ps1

License

This project is licensed under the Apache 2.0 license.

Note that the project description data, including the texts, logos, images, and/or trademarks, for each open source project belongs to its rightful owner. If you wish to add or remove any projects, please contact us at [email protected].