{"id":16366604,"url":"https://github.com/lecaillon/cassette","last_synced_at":"2025-03-23T02:32:40.837Z","repository":{"id":77262834,"uuid":"166642182","full_name":"lecaillon/Cassette","owner":"lecaillon","description":"An HTTP Client handler that caches successful responses and replays them for improving the stability of your testing environment and speeding up your test suite.","archived":false,"fork":false,"pushed_at":"2025-01-15T20:41:00.000Z","size":73,"stargazers_count":15,"open_issues_count":0,"forks_count":4,"subscribers_count":2,"default_branch":"master","last_synced_at":"2025-03-18T16:53:03.629Z","etag":null,"topics":["cache","cassette","cassette-http","continuous-integration","distributed-cache","httpclient","integration-tests","message-handler","middleware"],"latest_commit_sha":null,"homepage":"","language":"C#","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/lecaillon.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2019-01-20T09:04:59.000Z","updated_at":"2025-01-15T20:41:01.000Z","dependencies_parsed_at":null,"dependency_job_id":"28d3aff3-f3ed-4ce2-bda5-963a3e6b9870","html_url":"https://github.com/lecaillon/Cassette","commit_stats":null,"previous_names":[],"tags_count":2,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/lecaillon%2FCassette","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/lecaillon%2FCassette/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/lecaillon%2FCassette/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/lecaillon%2FCassette/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/lecaillon","download_url":"https://codeload.github.com/lecaillon/Cassette/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":245047977,"owners_count":20552430,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["cache","cassette","cassette-http","continuous-integration","distributed-cache","httpclient","integration-tests","message-handler","middleware"],"created_at":"2024-10-11T02:47:02.604Z","updated_at":"2025-03-23T02:32:40.561Z","avatar_url":"https://github.com/lecaillon.png","language":"C#","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Cassette [![Build Status](https://lecaillon.visualstudio.com/Cassette-CI/_apis/build/status/Cassette-CI?branchName=master)](https://lecaillon.visualstudio.com/Cassette-CI/_build/latest?definitionId=6\u0026branchName=master) [![Coverage status](https://img.shields.io/azure-devops/coverage/lecaillon/cassette-ci/6.svg?color=brightgreen)](https://lecaillon.visualstudio.com/Cassette-CI/_build/latest?definitionId=6\u0026branchName=master) [![NuGet](https://buildstats.info/nuget/Cassette.Http)](https://www.nuget.org/packages/Cassette.Http)\n\n\u003cimg align=\"right\" width=\"256px\" height=\"256px\" src=\"https://raw.githubusercontent.com/lecaillon/Cassette/master/images/logo256.png\"\u003e\n\nRecords and replays successful HTTP responses in your testing environment.\n\nIn a micro-service context, where your integration tests depend on a lot of external HTTP resources, Cassette is an ideal tool to improve the stability of your CI pipeline.\nIt is based on a very simple idea: uniquely identify all the requests that pass through and record succesfull reponses. After recording, replay the same responses without actually calling the real REST endpoint.\n\nTo create that unique request identifier, Cassette computes an hash from the HTTP method, the uri and the body.\n\n### Key features\n- Improves the stability of your testing environment.\n- Speeds up the execution of your test suite.\n- Avoids to many calls to your HTTP API dependencies, each time your CI pipeline runs.\n\n### Installation\nCassette is available as a single [NuGet package](https://www.nuget.org/packages/Cassette.Http).\n\n```\nInstall-Package Cassette.Http\n```\n\n### Requirement\n- **.NET Core 2.1+** or **.NET 4.6.1+**\n- Register an implementation of [`IDistributedCache`](https://docs.microsoft.com/en-us/aspnet/core/performance/caching/distributed) (Redis, SQL Server, in-memory).\n\n### Usage\n1. The easiest way to configure Cassette is to use the [HttpClientFactory](https://docs.microsoft.com/en-us/dotnet/standard/microservices-architecture/implement-resilient-applications/use-httpclientfactory-to-implement-resilient-http-requests). It will allow you to add the `ReplayingHandler` to every `HttpClient`. A sample that also uses [Refit](https://github.com/reactiveui/refit) is available [here](https://github.com/lecaillon/Cassette/blob/master/samples/AspNetCore.HttpClientFactory.QuickStart/Startup.cs).\n\n```c#\nservices.AddRefitClient\u003cIGeoApi\u003e()\n        .ConfigureHttpClient(options =\u003e options.BaseAddress = new Uri(\"https://geo.api.gouv.fr\"))\n        .AddReplayingHttpMessageHandler(); // Add the replaying message handler for the the IGeoApi, only\n                                           // if Cassette has been previously registered by calling AddCassette().\n                                           // The idea is to activate Cassette only during the integration tests.\n```\n\n\u003e Until the `AddCassette()` configuration method has been called, the HTTP message handler is not really added to the HttpClient, so its behavior remains unchanged.\n\n2. Finally activate Cassette during integration tests, by calling the `AddCassette()` configuration method **before** the registration of the message handlers. You can either use a feature toggle or even better create an [integration test project](https://docs.microsoft.com/en-us/aspnet/core/test/integration-tests) to override your DI configuration. Another sample can be found [here](https://github.com/lecaillon/Cassette/blob/master/test/Cassette.Tests/CustomWebApplicationFactory.cs).\n\n```c#\n// Declare the cache implementation Cassette will rely on\nservices.AddDistributedMemoryCache();\n\n// Register Cassette in the DI container\nservices.AddCassette(options =\u003e\n{\n    options.KeyPrefix = \"Cassette\";\n    options.CacheEntryOption.AbsoluteExpirationRelativeToNow = TimeSpan.FromHours(1);\n});\n```\n\n### Configuration\nCassette uses specific HTTP request headers to modify its behavior. They are defined in the classes `CassetteOptions` and `CassetteOptions.Refit`:\n- **NoRecord**: prevent caching of the HTTP response.\n- **ExcludeRequestBody**: exclude the request body from the computed key in cache when it contains an auto-generated identifier that would cause cache misses.\n- **ExcludeLastUriSegment**: exclude from the computed key in cache the last uri segment when its value is always different between calls, causing cache misses.\n\n#### Example of a Refit API where the POST endpoint is skipped by Cassette.\n```c#\npublic interface IGeoApi\n{\n    [Get(\"/regions\")]\n    Task\u003cList\u003cRegion\u003e\u003e GetRegions();\n\n    [Headers(CassetteOptions.Refit.NoRecord)]\n    [Post(\"/regions\")]\n    Task CreateRegion(Region region);\n}\n```\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Flecaillon%2Fcassette","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Flecaillon%2Fcassette","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Flecaillon%2Fcassette/lists"}