Coder Social home page Coder Social logo

rvcr's Introduction

rvcr

crates.io

Record-and-replay testing middleware for reqwest http client.

Inspired by:

Builds on top of:

Examples

To record HTTP requests, initialize client like following

  use std::path::PathBuf;
  use reqwest::Client;
  use reqwest_middleware::{ClientBuilder, ClientWithMiddleware};
  use rvcr::{VCRMiddleware, VCRMode};

  let mut bundle = PathBuf::from(env!("CARGO_MANIFEST_DIR"));
  bundle.push("tests/resources/replay.vcr.json");

  let middleware: VCRMiddleware = VCRMiddleware::try_from(bundle.clone())
      .unwrap()
      .with_mode(VCRMode::Record);

  let vcr_client: ClientWithMiddleware = ClientBuilder::new(reqwest::Client::new())
      .with(middleware)
      .build();

Now ClientWithMiddleware instance will be recording requests to a file located in tests/resources/replay.vcr.json inside the project.

To use recorded VCR cassette files, replace .with_mode(VCRMode::Record) with .with_mode(VCRMode::Replay), or omit it, since replay is used by default.

Search mode

When replaying, rVCR can skip requests already found when searching for subsequent requests (the default). To disable skipping requests, which is useful, for example, if requests are done in parallel and responses may come in random order, use .with_search(VCRReplaySearch::SearchAll).

Filtering sensitive information

Your requests and responses may contain sensitive information such as authentication details, user information etc. which you don't want to commit to your source control.

You can modify requests and responses before they are stored and restored using with_modify_request and with_modify_response.

You can change anything in the body, URI, headers etc. to hide any information you want. Here's an example which filters sensitive information in query parameters:

  let middleware = VCRMiddleware::try_from(bundle.clone())
      .unwrap()
      .with_mode(VCR::Record)
      .with_modify_request(|req| {
          let sensitive_query_params = ["access_token", "appsecret_proof"];

          // Replace sensitive data in query params
          let filtered_query_params = req.uri.clone().query_pairs().map(|(k, v)| {
              if sensitive_query_params.contains(&k.as_ref()) {
                  (k.clone(), Cow::from(k.to_uppercase()))
              } else {
                  (k, v)
              }
          });

          // Overwrite query params with filtered ones
          req.uri
              .query_pairs_mut()
              .clear()
              .extend_pairs(filtered_query_params)
              .finish();
      });

VCR cassette fie compression

Sometimes VCR files can be too large and this harder to maintain in a version control system.

To save some space and turn on bzip2 compression for artifacts, use .compression(true) method of the builder.

rvcr's People

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

rvcr's Issues

Blocking client

Hi, first of all, it's awesome to see a library inspired by Ruby vcr. Nice work!

When making requests to an API as a client, not a server, the extra complexity of async is often not needed. In fact, the use case of consuming an API and using vcr to test it is exactly the case where, in my opinion, async is likely not needed.

Are there plans to add support for the synchronous, blocking client reqwest::blocking::Client? I don't think reqwest-middleware supports it, so either that would need to happen or another approach would need to be taken.

reqwest-middleware 0.2 breaks RVCR

So I got a bit further this time but it seems there is some API change in reqwest-middleware version 0.2 that breaks RVCR. I got further with 0.1.6 but on 0.2 onwards I get the following type error when trying to follow the example:

code:

  let middleware: VCRMiddleware = VCRMiddleware::try_from(bundle.clone())
      .unwrap()
      .with_mode(VCRMode::Record);

  let vcr_client: ClientWithMiddleware = ClientBuilder::new(reqwest::Client::new())
      .with(middleware) //<< error occurs here
      .build();

output:

error[E0277]: expected a `Fn<(Request, &'a mut task_local_extensions::extensions::Extensions, Next<'a>)>` closure, found `VCRMiddleware`
  --> framework/tests/acceptance.rs:19:15
   |
19 |         .with(middleware)
   |          ---- ^^^^^^^^^^ expected an `Fn<(Request, &'a mut task_local_extensions::extensions::Extensions, Next<'a>)>` closure, found `VCRMiddleware`
   |          |
   |          required by a bound introduced by this call
   |
   = help: the trait `for<'a> Fn<(Request, &'a mut task_local_extensions::extensions::Extensions, Next<'a>)>` is not implemented for `VCRMiddleware`
   = note: required for `VCRMiddleware` to implement `reqwest_middleware::Middleware`

I'm not totally sure what's going on here. The Middleware trait still exists in the latest sourcecode for reqwest-middleware and is specified in that function, M must implement Middleware. I'm guessing that the definition of Middleware has changed, and this compiler output is a bit misleading.

Filtering sensitive data

Would you be open to a basic, non-full-featured, implementation of Filter Sensitive Data?

I can't promise any timeline or that I'd do it at all, but I want to check with you before working on it.

Thanks!

Chrono set to specific version

Hey, thanks for publishing this it looks really helpful and I'm excited to give it a try. I hit a problem quickly though, Cargo.toml sets chrono to version = "=0.4.20". The = forces that specific version and not any newer version so my project that uses 0.4.24 is not compatible. Specifically the error is:

❯ cargo add rvcr
    Updating crates.io index
      Adding rvcr v0.1.1 to dependencies.
    Updating crates.io index
error: failed to select a version for `chrono`.
    ... required by package `termibot v3.0.0 (/home/mattsi/dev/rust/termibot/bot)`
versions that meet the requirements `^0.4.24` are: 0.4.26, 0.4.25, 0.4.24

all possible versions conflict with previously selected packages.

  previously selected package `chrono v0.4.20`
    ... which satisfies dependency `chrono = "=0.4.20"` of package `rvcr v0.1.1`
    ... which satisfies dependency `rvcr = "^0.1.1"` of package `framework v0.1.0 (/home/mattsi/dev/rust/termibot/framework)`

failed to select a version for `chrono` which could resolve this conflict

Is there an explicit reason why newer chrono versions aren't supported? I had a quick look in the git history but couldn't see any documented reason.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.