serverless-express icon indicating copy to clipboard operation
serverless-express copied to clipboard

serverless-express callback request

Open namiomiru opened this issue 3 years ago • 4 comments

s3(image) + cloudfront + lambda@edge I'm only processing image requests from users authenticated with vanilla http.

*** vanilla-http

xxx.cloudfront.net/image.png

const authUtil = require("./middlewares/auth");

exports.handler = (event, context, callback) => { const { request, response } = event.Records[0].cf;

result = authUtil(request);

if(result.success) {
    callback(null, request);
} 

};

// This works well. (image download)

serverless-express

router.get('/:file', async (req, res) => { const { event, context } = getCurrentInvoke() const eventRequest = event.Records[0].cf.request;

res.json(eventRequest) });

// not working


{"clientIp":"000.000.000.000","headers":{"host":[{"key":"Host","value":"dl78camcjz7wt.cloudfront.net"}],"user-agent":[{"key":"User-Agent","value":"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.77 Safari/537.36"}],"


I need help to solve this problem.

namiomiru avatar Jun 20 '21 13:06 namiomiru

@brettstack do you know how this can be done? to summarise the issue and what I understand the question here to be, basically how do you return the request object in Lambda@Edge so that the request passes through to the origin (viewer/origin request events) instead of express returning a response to the client

robgott avatar Apr 25 '22 03:04 robgott

possible solution using the legacy succeed method of the context which is accessible via getCurrentInvoke

    const { getCurrentInvoke } = require('@vendia/serverless-express')
    const currentInvoke = getCurrentInvoke()
    currentInvoke.context.succeed(currentInvoke.event.Records[0].cf.request)

robgott avatar Apr 25 '22 03:04 robgott

@robgott I can confirm that this works for the s3 origin purpose from cloudfront through lambda@edge origin request integration.

logusgraphics avatar Oct 16 '23 16:10 logusgraphics

Getting the lambda context via getCurrentInvoke() and subsequently calling context.succeed() with the event would break the abstraction in the route handler of using express request/response model.

An alternative approach is to internally use one of the esoteric HTTP response codes to signal the lambda handler that the request should be passed on to the cloudfront origin.

const routeHandler = async (req, res) => {
  if (...) {
    // forward the request to the origin
    res
      .status(203)
      .end();
    return;
  }

  // express handler returns a response
  res
    .status(200)
    .send(...);
}

const app = express();
configureApplication(app);
const serverlessExpressHandler = serverlessExpress({ app });

export const handler = async (event, context) => {
  const result = await serverlessExpressHandler(event, context);
  if (result.status == 203) {
    return event.Records[0].cf.request;
  }
  return result;
}

peter-at-work avatar Feb 22 '24 02:02 peter-at-work