Description
Hi there 👋
When EmberServer is used, Request attributes will never be empty.
This is because EmberServer stores connection and other information in attributes by default.
Corresponding code
- https://github.com/http4s/http4s/blob/series/0.23/ember-server/shared/src/main/scala/org/http4s/ember/server/internal/ServerHelpers.scala#L341
- https://github.com/http4s/http4s/blob/series/0.23/ember-server/shared/src/main/scala/org/http4s/ember/server/internal/ServerHelpers.scala#L502
Also, it is not possible to explicitly change the conditional branching of whether connection information is stored in attributes by default.
This means that whenever unixSocket is not used, there will always be a value for attributes.
I checked what the attributes look like when using VaultSessionMiddleware as a test.
def transformRoutes[F[_]: Functor](routes: HttpRoutes[F]): SessionRoutes[F, Option[Vault]] = {
Kleisli { contextRequest: ContextRequest[F, Option[Vault]] =>
val initVault = contextRequest.context.fold(contextRequest.req.attributes)(context =>
Vault.union(context, contextRequest.req.attributes)
)
println(contextRequest.context) // None
println(contextRequest.req.attributes.isEmpty) // false
println(contextRequest.req.attributes.lookup(Request.Keys.ConnectionInfo)) // Some(Connection(127.0.0.1:8080,127.0.0.1:57720,false))
...
What's wrong with this?
Cookies are always generated unless you use something like withAttribute(VaultSessionReset.key, VaultSessionReset)
in a Meiji way.
I added the following Route to VaultSessionExample as a test, and a cookie was generated even though I did not set an Attribute in the Response.
case GET -> Root / "context" / "not" / "empty" => Ok("Context not empty")
I think we should only generate cookies if we explicitly set a value for attributes in the response.
The easiest way is to add a conditional branch so that a value is passed to ContextResponse only if Response or Context is empty.
outContext
.lookup(VaultSessionReset.key)
.fold(
outContext
.lookup(VaultKeysToRemove.key)
.fold(
// Adding conditional branching
if (outContext.isEmpty) {
ContextResponse(None, resp)
} else {
ContextResponse(outContext.some, resp.withAttributes(outContext))
}
)(toRemove =>
ContextResponse(toRemove.l.foldLeft(outContext) { case (v, k) => v.delete(k) }.some,
resp.withAttributes(outContext)
)
)
)(reset => ContextResponse(None, resp.withAttributes(outContext)))
If this solution is acceptable, I will create a pull request.
If I am wrong, I would appreciate it if you could let me know.
Thanks!