Record and replay HTTP sessions with Surf
Update documentation for release
Trivial style fixes
Simplify recording unit test



You can also use your local clone with git send-email.

#Surf-vcr - Record and Replay HTTP sessions

Surf-vcr is a testing middleware for the Surf HTTP client library. Surf-vcr records your client's HTTP sessions with a server to later mock the server's HTTP responses, providing deterministic testing of your clients.

The high-level design is based on VCR for Ruby.

Source code is available on SourceHut and Github. Patches may be sent via either service, but the CI is running on SourceHut.

#Table of Contents


Surf-vcr records HTTP sessions to a YAML file so you can review and modify (or even create) the requests and responses manually. You can then inject the pre-recorded responses into your client sessions.


You'll typically be using surf-vcr as a development dependency, so add it as such via Cargo:

cargo add -D surf-vcr

Or add it to your Cargo.toml file manually:

surf-vcr = "0.2.0"


Either in your application or the relevant test, register the middleware with your application in Record mode. You will connect to a functioning server and record all requests and responses to a file. You can safely replay and record multiple HTTP sessions (tests) with the same file concurrently.

Surf-vcr must be registered after any other middleware that modifies the Request or Response; otherwise it will not see their modifications and cannot record them.

I have found it useful to use a function in my application to create the Surf client with my middleware, then call that function in my tests as well so I know my test client and application client are identical:

fn create_surf_client() -> surf::Client {
    let session = MySessionMiddleware::new();


mod tests {
    use super::*;
    use async_std::task;
    use surf_vcr::{VcrError, VcrMiddleware, VcrMode};

    async fn create_test_client(mode: VcrMode, cassette: &'static str)
    -> std::result::Result<surf::Client, VcrError>
        let client = create_surf_client()
            .with(VcrMiddleware::new(mode, cassette).await?);


    async fn test_example_request() {
        let client = create_test_client(

        let req = surf::get("https://www.example.com")
            .insert_header("X-my-header", "stuff");

        let mut res = client.send(req).await.unwrap();
        assert_eq!(res.status(), surf::StatusCode::Ok);

        let content = res.body_string().await.unwrap();
        assert!(content.contains("illustrative examples"));

Take a look at the docs or the simple example for more.


To mock the server's responses simply change VcrMode::Record to VcrMode::Replay and re-run your tests. Surf-vcr will look up each request made, intercept it, and return the saved response.

#Modify Recorded Content

You can modify data before writing to your cassette files. This is useful while working with sensitive or dynamic data.

VcrMiddleware::new(VcrMode::Record, path).await?
    .with_modify_request(|req| {
            .and_modify(|val| *val = vec!["...(erased)...".into()]);
    .with_modify_response(|res| {
            .and_modify(|val| *val = vec!["...(erased)...".into()]);


All source code is licensed under the terms of the MPL 2.0 license.


Patches and pull requests are welcome. For major features or breaking changes, please open a ticket or start a discussion first so we can discuss what you would like to do.