haskell-servant / servant

Servat is a Haskell DSL for describing, serving, querying, mocking, documenting web applications and more!
https://docs.servant.dev/
1.83k stars 413 forks source link

Allow access to URL path in a more manageable format #879

Open KaneTW opened 6 years ago

KaneTW commented 6 years ago

I'm currently writing an implementation of rate limiting for servant-client, and it'd be very useful to have access to the current URL path as e.g. a [PathPiece] where

data PathPiece
  = StaticPath Text
  | Capture String Text

so that I can properly group rate limiting bins by specific Captures.

Ideally, I'd be able to do something like

type RateLimitedAPI = "foo" :> "bar" :> Capture "id" Int :> Capture "minor" Int :> RateLimit (IgnoreCapture "minor") :> Post '[JSON] Foo
phadej commented 6 years ago

why you don't put RateLimit before "minor" capture and treat it as all api endpoints share this rate limiter?

EDIT which might be good idea, as I don't recall too many API with granular per-resource rate limiting.

KaneTW commented 6 years ago

I need /foo/bar/:id/:minor to be a distinct bin than /foo/bar/:id.

phadej commented 6 years ago

let me think a bit.

phadej commented 6 years ago

For now, I'd suggest to name the bins explicitly: RateLimit "/foo/bar/:id".

KaneTW commented 6 years ago

I'll probably go for something like

type RateLimitedAPI = "foo" :> "bar" :> Capture "id" Int :> RateLimit "minor" :> Capture "minor" Int :> Post '[JSON] Foo

and use the currently constructed Request path + the type-level symbol as a bin.

KaneTW commented 6 years ago

Humm. I need to query my MonadRateLimit whether a request can be performed or not, but

I can use a custom header and populate it with the bin name, for now, but it's not particularly elegant.