Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

How to combine nested filters? #744

Closed
cutsoy opened this issue Nov 6, 2020 · 2 comments
Closed

How to combine nested filters? #744

cutsoy opened this issue Nov 6, 2020 · 2 comments
Labels
feature New feature or request

Comments

@cutsoy
Copy link

cutsoy commented Nov 6, 2020

I would like to write a Rust package that implements a few "sub-endpoints" for another developer's consumer crate (e.g. for OAuth or other APIs).

For example, I have the following "integrated" code that I want to separate into two packages (the "shared" crate and a "consumer" crate).

// Integrated crate
impl InfoRefs for Repo {
    fn capabilities(&self) -> Vec<Capability>;
}

let info_refs = warp::path!(String / String / "info" / "refs")
    .map(|(owner, name)| Repo { owner, name })
    .and(warp::query::<Query>())
    .map(|(repo, query)| {
        // Build response
        Response::builder()
            .body(
                // ...
                repo.capabilities()
                // ...
            )
    });

In short, this is and(path.map, query).map

The problem is, I want to move these lines into the "shared" crate:

  // Consumer crate
  let info_refs = warp::path!(String / String / "info" / "refs")
      .map(|(owner, name)| Repo { owner, name })
-     .and(warp::query::<Query>())
-     .map(|(repo, query)| {
-         // Build response
-         Response::builder()
-             .body(
-                 // ...
-                 repo.capabilities()
-                 // ...
-             )
-     });
+    .and(git_service::info_refs);

However, this isn't currently possible because there's no way to write this info_refs function that can use both the output of the developer's own path map and the result of the query parse. Specifically, moving this to another crate would create:

// Shared crate
pub fn info_refs() -> impl Filter<...> {
    warp::query::<Query>().map(|query| {
        // ...
    })
}

Calling this from the consumer crate would result in and(path.map, query.map), which is obviously incorrect and not useful because we can no longer access the result of path.map here.

What's the recommended work around for this? There are a lot of useful types that are not exported by Warp, like Wrap, that could potentially be useful in this situation.

@cutsoy cutsoy added the feature New feature or request label Nov 6, 2020
@cutsoy cutsoy changed the title How to combine How to combine nested filters? Nov 6, 2020
@cutsoy
Copy link
Author

cutsoy commented Nov 6, 2020

Nevermind, this is probably related to #607 (although I hope my question did not come across as aggressive). I hope it would be possible to feature-gate some of these types because it's quite difficult to express some common patterns ("middleware" in general actually) without some of these types.

For example, the use case I am describing, could in the future be written as:

pub fn info_refs<F>() -> impl Wrap<F> where F: Filter, F::Extract: InfoRefs {
    warp::wrap_fn(|filter| {
        filter.and(warp::query::<Query>())
              .map(|(repo, query)| ...)
    })
}

Unfortunately, Wrap is still sealed.

@jxs
Copy link
Collaborator

jxs commented Nov 7, 2020

see #693 (comment)

@jxs jxs closed this as completed Nov 8, 2020
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
feature New feature or request
Projects
None yet
Development

No branches or pull requests

2 participants