Effect CommunityEC
Effect Community9mo ago
6 replies
MrOffersen

Issues with Layers in HTTP API with Auth Middleware

Hello! I'm trying to make a http api with an auth middleware that provides the current user to be used in handlers. But I'm running into problems with the layers it seems.

Here's a playground: https://effect.website/play#e71fa7270ec3

Anyone mind explaining what I'm doing wrong here? And if there's a more preferred way?
import { ... } from "@effect/platform" // omitted to not make message too long for discord
import { NodeHttpServer, NodeRuntime } from "@effect/platform-node"
import { Context, Effect, Layer, Schema } from "effect"
import { createServer } from "node:http"

class User extends Schema.Class<User>("User")({ name: Schema.String }) {}

class Me extends Context.Tag("Me")<Me, User>() {}

class AuthenticationMiddleware extends HttpApiMiddleware.Tag<AuthenticationMiddleware>()(
  "AuthenticationMiddleware",
  { provides: Me }
) {}

const AuthenticationMiddlewareLive = Layer.effect(
  AuthenticationMiddleware,
  Effect.gen(function*() {
    // extract session from httponly cookie (omitted for simplicity)
    return Effect.succeed(new User({ name: "alice" }))
  })
)

const Api = HttpApi.make("api").add(
  HttpApiGroup.make("greetings")
    .add(HttpApiEndpoint.get("hello", "/hello").addSuccess(Schema.String))
).middleware(AuthenticationMiddleware)

const GreetingsLive = HttpApiBuilder.group(Api, "greetings", (handlers) =>
  Effect.gen(function*() {
    const me = yield* Me

    return handlers.handle("hello", () => Effect.succeed(`hello ${me.name}`))
  }))

// type of ApiLive: Layer.Layer<HttpApi.Api, never, Me> but I would expect it to be Layer.Layer<HttpApi.Api, never, never> since AuthenticationMiddlewareLive provides Me? 
const ApiLive = HttpApiBuilder.api(Api).pipe(
  Layer.provide(GreetingsLive),
  Layer.provide(AuthenticationMiddlewareLive)
)

const Main = HttpApiBuilder.serve(HttpMiddleware.logger).pipe(
  Layer.provide(ApiLive),
  Layer.provide(NodeHttpServer.layer(createServer, { port: 4000 }))
)

NodeRuntime.runMain(Layer.launch(Main))
Was this page helpful?