Skip to content

feat: support direct AWS SDK Invoke requests (#106)#331

Open
naorpeled wants to merge 1 commit into
jeremydaly:mainfrom
naorpeled:feat/direct-lambda-invoke
Open

feat: support direct AWS SDK Invoke requests (#106)#331
naorpeled wants to merge 1 commit into
jeremydaly:mainfrom
naorpeled:feat/direct-lambda-invoke

Conversation

@naorpeled

Copy link
Copy Markdown
Collaborator

Summary

Closes #106. Adds opt-in support for processing requests that bypass API Gateway/ALB and are invoked directly via the AWS SDK Invoke API — both RequestResponse and Event invocation types.

Enable it at init:

const api = require('lambda-api')({ directInvoke: true });

With the flag on, an event that has no requestContext is detected as the new lambda interface and routed normally. Direct invocations return an unwrapped response instead of the API Gateway proxy envelope:

// Handler: res.status(200).json({ id: 123 })
// Invoke Payload:
{ "statusCode": 200, "body": { "id": 123 } }

Why unwrapped instead of the proxy envelope?

The { statusCode, headers, body, isBase64Encoded } envelope is specifically the API Gateway/ALB/Function-URL proxy contract, not a general Invoke contract — returning it forces a direct caller to JSON.parse twice (the Payload, then the stringified body) and ships meaningless headers/isBase64Encoded. The unwrapped { statusCode, body } gives single-parse ergonomics while preserving statusCode, which is the only success/failure signal available since Lambda API never throws out of run(). Binary responses keep isBase64Encoded: true with the raw base64 body.

Backward compatibility

directInvoke defaults to false, so nothing changes by default. API Gateway and ALB events always carry a requestContext, so they keep the normal envelope even with the flag on — one handler transparently serves all three sources. Tests include explicit backward-compat and dual-mode guards.

Changes

  • src/index.js — parse the directInvoke config option
  • src/lib/request.js — gate lambda interface detection (only when directInvoke is on and no requestContext)
  • src/lib/response.js — return the unwrapped { statusCode, body } payload for the lambda interface
  • index.d.ts — add Options.directInvoke and Request.interface
  • __tests__/ — new Lambda Direct Invoke suite (unwrapped shape, routing, unwrapped errors, base64, HEAD, backward-compat + dual-mode guards) and a sample-event-lambda1.json fixture
  • README.md — document the option, the lambda interface value, and a new Direct Lambda Invocations section

Notes

  • The Event (async) invocation type needs no special handling — AWS discards the function's return value, so behavior is identical to RequestResponse from the framework's side.
  • Caveat documented: response headers/cookies are dropped in the unwrapped shape, and req.ip/clientType/clientCountry fall back to their defaults for direct invocations.

Testing

npm test green: build (CJS/ESM/types) + tsd + jest unit (492 passed) + jest module-compat. eslint and prettier --check clean.

Add an opt-in `directInvoke` option so Lambda API can process requests
that bypass API Gateway/ALB and are invoked directly via the AWS SDK
`Invoke` API (both RequestResponse and Event invocation types).

When `directInvoke: true`, an event without a `requestContext` is
detected as the new `lambda` interface and routed normally. Instead of
the API Gateway proxy envelope (whose stringified `body` forces callers
to double-parse), a direct invocation returns an unwrapped
`{ statusCode, body }` payload — the parsed value plus the status code,
which is the only success/failure signal since Lambda API never throws.
Binary responses keep `isBase64Encoded: true` with the raw base64 body.

The option defaults to `false`, so API Gateway/ALB behavior (which always
carry a `requestContext`) is unchanged and one handler serves all three.

- src/index.js: parse `directInvoke` config
- src/lib/request.js: gate `lambda` interface detection
- src/lib/response.js: unwrapped response for the `lambda` interface
- index.d.ts: add `Options.directInvoke` and `Request.interface`
- __tests__: Lambda Direct Invoke suite + fixture (shape, routing,
  errors, base64, HEAD, backward-compat and dual-mode guards)
- README.md: document the option, interface value, and new section

Closes jeremydaly#106
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Process AWS SDK “Invoke” requests

1 participant