Integrating CORS with Effect HttpApi using a Layer
Hello all! I'm trying to build some handlers for Better-Auth in my Effect HttpApi and the solution I ended up with for my handlers is the example bellow. The problem for me is having to setup the CORS. I have a CorsLive Layer that already does this for me on every endpoint of my api but it fails on this specific group. Is there a better way to do this?
const authHandler = Effect.gen(function* () {
const repository = yield* AuthRepository;
const envVars = yield* EnvVars;
const request = yield* HttpServerRequest.HttpServerRequest;
const nodeRequest = NodeHttpServerRequest.toIncomingMessage(request);
const nodeResponse = NodeHttpServerRequest.toServerResponse(request);
const appUrl = envVars.APP_URL;
nodeResponse.setHeader("Access-Control-Allow-Origin", appUrl);
nodeResponse.setHeader("Access-Control-Allow-Methods", "GET, POST, PUT, DELETE, OPTIONS");
nodeResponse.setHeader("Access-Control-Allow-Headers", "Content-Type, Authorization");
nodeResponse.setHeader("Access-Control-Max-Age", "600");
nodeResponse.setHeader("Access-Control-Allow-Credentials", "true");
// Handle preflight requests
if (nodeRequest.method === "OPTIONS") {
nodeResponse.statusCode = 200;
nodeResponse.end();
return nodeResponse;
}
yield* Effect.tryPromise({
try: () => toNodeHandler(repository.handler)(nodeRequest, nodeResponse),
catch: (error) => {
return new BetterAuthApiError({ error });
},
});
return nodeResponse;
}).pipe(Effect.provide([AuthRepository.Default]));const authHandler = Effect.gen(function* () {
const repository = yield* AuthRepository;
const envVars = yield* EnvVars;
const request = yield* HttpServerRequest.HttpServerRequest;
const nodeRequest = NodeHttpServerRequest.toIncomingMessage(request);
const nodeResponse = NodeHttpServerRequest.toServerResponse(request);
const appUrl = envVars.APP_URL;
nodeResponse.setHeader("Access-Control-Allow-Origin", appUrl);
nodeResponse.setHeader("Access-Control-Allow-Methods", "GET, POST, PUT, DELETE, OPTIONS");
nodeResponse.setHeader("Access-Control-Allow-Headers", "Content-Type, Authorization");
nodeResponse.setHeader("Access-Control-Max-Age", "600");
nodeResponse.setHeader("Access-Control-Allow-Credentials", "true");
// Handle preflight requests
if (nodeRequest.method === "OPTIONS") {
nodeResponse.statusCode = 200;
nodeResponse.end();
return nodeResponse;
}
yield* Effect.tryPromise({
try: () => toNodeHandler(repository.handler)(nodeRequest, nodeResponse),
catch: (error) => {
return new BetterAuthApiError({ error });
},
});
return nodeResponse;
}).pipe(Effect.provide([AuthRepository.Default]));const CorsLive = Layer.unwrapEffect(
EnvVars.pipe(
Effect.map((envVars) =>
HttpApiBuilder.middlewareCors({
allowedOrigins: [envVars.APP_URL],
allowedMethods: ["GET", "POST", "PUT", "DELETE", "PATCH"],
allowedHeaders: ["Content-Type", "Authorization", "B3", "traceparent"],
credentials: true,
}),
),
),
);const CorsLive = Layer.unwrapEffect(
EnvVars.pipe(
Effect.map((envVars) =>
HttpApiBuilder.middlewareCors({
allowedOrigins: [envVars.APP_URL],
allowedMethods: ["GET", "POST", "PUT", "DELETE", "PATCH"],
allowedHeaders: ["Content-Type", "Authorization", "B3", "traceparent"],
credentials: true,
}),
),
),
);