tower-rs / tower-rs/tower-http

A means to conditionally provide a response to a request in lieu of calling the inner service

Open
#426 6 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

Dominant language
Rust
Stars
913
Forks
231
Avg merge
1d 20h
Merged PRs (30d)
8

Description

Feature Request

Conditionally provide a response instead of calling the inner service.

Motivation

This middleware provides a way to conditionally skip calling the inner service
if a response is already available for the request.

Probably the simplest visual for this is providing a cached response, though it
is unlikely that this middleware is suitable for a robust response cache interface
(or, more accurately, it's not the motivation for developing this so I haven't
looked into it adequately enough to provide a robust argument for it being so!).

The premise is simple - write a (non-async) function that assesses the current request
for the possibility of providing a response before invoking the inner service. Return
the "early" response if that is possible, otherwise return the request.

The differences between using this and returning an error from a pre-inner layer are.

  1. The response will still pass through any post-inner layer processing
  2. You aren't "hacking" the idea of an error when all you are trying to do is avoid
    calling the inner service when it isn't necessary.

Possible uses:

  • A pre-inner layer produces a successful response before the inner service is called
  • Caching (though see above - this could, however, be the layer that skips the inner
    call while a more robust pre-inner layer implements the actual caching)
  • Mocking
  • Debugging
  • ...
Proposal

The idea should be fairly straightforward to implement, being a merge of the capabilities of tower predicate layers
and simple pre-service layers. The slight complications of providing alternative responses from the function,
and providing different futures from the poll method can be overcome by judicious use of enums.

For simplicity, the first iteration should only allow sync functions. Maybe at a later date async functions can be
allowed (particularly after async methods in traits become generally available), which would then allow for a
more generic stack of multiple "end" services to be constructed in the vein of the chain of responsibility pattern!

Alternatives

Since the main purpose of this middleware is, effectively, to conditionally switch from pre-request processing to post-response processing - i.e. it's effectively a Request->Request mapper or a Request->Response generator - there currently exists no general way to do this in the provided filters of the crate.

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start by reviewing the crate's existing predicate layers and simple pre-service layers, then compare how they handle request mapping, response generation, and post-inner processing. Done means a synchronous function can conditionally return an alternative response without calling the inner service, while that response still passes through post-inner processing.

Written by the indexing model from the issue text.

Assessment

Tech stack
rust
Domain
api, backend
Issue type
Feature
Difficulty
5/5
Estimated time
Over a week
Activity status
Quiet
Clarity
Mostly clear
Newbie friendliness
35/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.