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

Req.url incorrectly evaluated for paths with nested proxy - ApiGateway

Open saltonmassally opened this issue 3 years ago • 5 comments

GIven the following resource /testing/{proxy+} a call to /testing/creategroup is evaluated to /creategroup rather than /testing/creatgroup.

Looking at getPathWithQueryStringParams, it appears that if proxy pathParameter is present, it is simply used, discarding the other parts. Would substituting the value for proxy for the token {proxxy+} into event.resource (/testing/{proxy+}) be a potential approach to fixing this?

saltonmassally avatar Apr 26 '21 00:04 saltonmassally

This appears related: https://github.com/vendia/serverless-express/issues/362

thetumper avatar May 13 '21 21:05 thetumper

is there a workaround for this? my use case is wanting to create a callback url to a path, and with the same url structure as @saltonmassally has defined above.

thyming avatar Apr 05 '22 16:04 thyming

I've found a workaround for this, in my specific case I had to do this:

const handle = async (event, context) => {
  event.resource = '/users/{proxy+}'.replace(/^\/users/, '');
  event.requestContext.resourcePath = '/users/{proxy+}'.replace(/^\/users/, '');
  event.pathParameters.proxy = `users/${event.pathParameters.proxy}`;

  return serverlessExpressInstance(event, context)
}

sanchesrm avatar Apr 06 '22 13:04 sanchesrm

I've found a workaround for this, in my specific case I had to do this:

const handle = async (event, context) => {
  event.resource = '/users/{proxy+}'.replace(/^\/users/, '');
  event.requestContext.resourcePath = '/users/{proxy+}'.replace(/^\/users/, '');
  event.pathParameters.proxy = `users/${event.pathParameters.proxy}`;

  return serverlessExpressInstance(event, context)
}

Thank you for this. It worked perfectly for my scenario as well. In my case, I had a non-changeable scenario where the nested greedy proxy had to be attached to a resource that also happens to be a pathParameter.

In my case, the fix was


export const handler: APIGatewayProxyHandler = async (event, context, callback) => {
    // Enable support for a "version" pathParameter that was defined in the AWS CDK project stack.
    // In the stack, the greedy proxy (.addProxy()) is attached to this resource.

    const nextEvent: APIGatewayProxyEvent = {
        ...event,
        resource: event.resource.replace(/^\/{version}/, ''),
        requestContext: {
            ...(event.requestContext ?? {}),
            resourcePath: event.requestContext.resourcePath.replace(/^\/{version}/, '')
        },
        pathParameters: {
            ...(event.pathParameters ?? {}),
            // Get the actual value of the "version" pathParameter and prefix it to the value of "proxy"
            proxy: `${event.pathParameters?.['version']}/${event.pathParameters?.['proxy']}`
        }
    };

    server = await boostrap();

    // Pass the modified event to the serverless express handler
    return server(nextEvent, context, callback);
};




pejulian avatar Sep 29 '22 11:09 pejulian

I got the same error. It worked (without any changes in the event) only with the old version:

import serverlessExpress from 'aws-serverless-express';

async function bootstrap(): Promise<Server> {
  const app = await NestFactory.create(AppModule, {
    logger: ['error', 'warn'],
  });

  await app.init();

  const expressApp = app.getHttpAdapter().getInstance();
  return serverlessExpress.createServer(expressApp);
}

export const handler: Handler = async (
  event: APIGatewayProxyEvent,
  context: Context,
) => {
  server = server ?? (await bootstrap());

  return serverlessExpress.proxy(server, event, context, 'PROMISE').promise;
};

wladimirgrf avatar Jan 21 '23 22:01 wladimirgrf