This allows customizing the way by-type parameters can be read: instead of always reading data from a cask.Request, this allows a decorator to parameterize the context type and pass it in explicitly from the wrapFunction method.
Essentially, this makes the context parameter of ArgReaders (which are used to translate data from a HTTP request to a scala parameter) customizable for every decorator.
Motivation
The idea behind this proposal is to uniformize the way "named" and "by-type" parameters within the same endpoint are handled. By "named" parameters I mean parameters which are set from the Map[String, Input] in the delegate function, and by by-type parameters I mean parameters which are computed from an arity zero ArgReader, and thus use the cask.Request context to compute their value.
E.g.
@cask.get(/:foo/:bar)
def index(foo: String, bar: Int, cookie1: cask.Cookies, req: cask.Request)
In this case, foo and bar and "named" and cookie1 and req are "by-type".
Right now, the wrapFunction method handles how named parameters are set, and therefore can centrally do arbitrary pre- and post-processing. However, by-type parameters must always use a cask.Request to compute any values, which can be problematic if the computation is expensive or if any kind of state is maintained.
This pull request removes this asymmetry, by allowing the wrapFunction to compute a custom context which is computed once before being passed to all InputReaders
Implementation approach
add InputContext type parameter to decorators
add a parameter of type InputContext to delegate. type Delegate = (InputContext, Map[String, Input)) => ...
change Decorator.invoke() to carry a list of input contexts, one for each parameter list
also change the Entrypoint macros to use these input contexts rather than hardcoding cask.Request (currently I've only done the work to support Scala 3 for this)
This is a proof of concept PR. As of this writing, the code only works for Scala 3.
This allows customizing the way by-type parameters can be read: instead of always reading data from a
cask.Request
, this allows a decorator to parameterize the context type and pass it in explicitly from thewrapFunction
method.Essentially, this makes the context parameter of
ArgReader
s (which are used to translate data from a HTTP request to a scala parameter) customizable for every decorator.Motivation
The idea behind this proposal is to uniformize the way "named" and "by-type" parameters within the same endpoint are handled. By "named" parameters I mean parameters which are set from the
Map[String, Input]
in the delegate function, and byby-type
parameters I mean parameters which are computed from an arity zeroArgReader
, and thus use thecask.Request
context to compute their value.E.g.
In this case,
foo
andbar
and "named" andcookie1
andreq
are "by-type".Right now, the
wrapFunction
method handles how named parameters are set, and therefore can centrally do arbitrary pre- and post-processing. However, by-type parameters must always use acask.Request
to compute any values, which can be problematic if the computation is expensive or if any kind of state is maintained.This pull request removes this asymmetry, by allowing the
wrapFunction
to compute a custom context which is computed once before being passed to allInputReader
sImplementation approach
InputContext
type parameter to decoratorsInputContext
todelegate
.type Delegate = (InputContext, Map[String, Input)) => ...
Decorator.invoke()
to carry a list of input contexts, one for each parameter listalso change the
Entrypoint
macros to use these input contexts rather than hardcodingcask.Request
(currently I've only done the work to support Scala 3 for this)This is a proof of concept PR. As of this writing, the code only works for Scala 3.