dherault / dherault/serverless-offline
CORS config not applied to the lambda invoke server (lambdaPort), only to HTTP event routes
- Dominant language
- JavaScript
- Stars
- 5.3k
- Forks
- 811
- Avg merge
- 2d 4h
- Merged PRs (30d)
- 3
Description
### Summary
`provider.httpApi.cors` is honoured by the HTTP event server but not by the lambda invoke server, so invoking a function locally through the AWS SDK from a browser origin fails CORS preflight.
### Detail
`src/events/http/HttpServer.js` attaches an `onPreResponse` hook that reads `getHttpApiCorsConfig(...)` and sets `access-control-allow-origin` and friends (around line 108 on `master` today).
`src/lambda/HttpServer.js` — the server bound to `lambdaPort`, serving `/2015-03-31/functions/{name}/invocations` — constructs its Hapi server with no equivalent hook:
```js
constructor(options, lambda) {
this.#lambda = lambda
this.#options = options
const { host, lambdaPort } = options
const serverOptions = { host, port: lambdaPort }
this.#server = new Server(serverOptions)
}
```
So a browser app that calls a function via `@aws-sdk/client-lambda` pointed at the offline lambda endpoint gets no CORS headers, and preflight `OPTIONS` is not answered, even when `provider.httpApi.cors` is configured.
### Reproduce
1. Configure `provider.httpApi.cors` in `serverless.yml`.
2. Run `serverless offline`.
3. From a page on some origin, invoke a function through `@aws-sdk/client-lambda` with `endpoint` set to `http://localhost:`.
4. The request fails CORS; responses from the invoke endpoint carry no `access-control-*` headers.
Requests to the HTTP event routes on `httpPort` work correctly, which is what makes the asymmetry visible.
### Suggested fix
Reuse the existing CORS logic on the lambda server. The smallest version is to attach the same `onPreResponse` hook in `src/lambda/HttpServer.js`, which needs access to the `serverless` config — currently not passed to that constructor. A tidier variant extracts the existing hook from `src/events/http/HttpServer.js` into a shared helper used by both servers.
We have been carrying the extract-and-share variant on a fork for a while and it has held up in daily use. Happy to open a PR against `master` in whichever shape you prefer — or to close this if the behaviour is intentional and the invoke endpoint is considered out of scope for CORS.
Contributor guide
Research direction
Start with the CORS hook around line 108 in src/events/http/HttpServer.js, then compare how src/lambda/HttpServer.js constructs the lambdaPort server and accesses configuration. Trace how provider.httpApi.cors reaches the existing hook and verify that the invoke endpoint answers OPTIONS and includes the expected access-control headers when the issue is resolved.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- javascript
- Domain
- api, backend
- Issue type
- Bug
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Activity status
- Quiet
- Clarity
- Mostly clear
- Newbie friendliness
- 52/100