dherault / serverless-offline

Emulate AWS λ and API Gateway locally when developing your Serverless project
MIT License
5.19k stars 795 forks source link

"Unsupported Media Type" When Invoking Lambda from Within Another Lambda #747

Closed xiaoqiaomm closed 4 years ago

xiaoqiaomm commented 5 years ago

I would like to use this plugin to invoke a lambda ('my-function-local') from within another lambda (local-lambda). Below is my lambda function which will invoke another lambda locally and when I run "serverless invoke local --function local-lambda" it throws a "Unsupported Media Type" exception. Does it mean the function it's invoking is not deployed into localhost:3000?

export async function localLambda(event) {
  const lambda = new AWS.Lambda({
    region: 'us-east-1',
    endpoint: 'http://localhost:3000',
  });
  let response;
  const lambdaInvokeParameters = {
    FunctionName: 'my-function-local',
    InvocationType: 'Event',
    LogType: 'Tail',
    Payload: JSON.stringify({
      "body": {"tableName":"my_table"}
    }),
  }
  try {
    response = await lambda.invoke(lambdaInvokeParameters).promise();
  } catch (err) {
  return (err);
  }
  console.log("response: ", response);
}
dnalborczyk commented 5 years ago

hey @xiaoqiaomm

severless invoke local only runs in the context of serverless and is not "hosted" with an underlying server - unlike serverless-offline. so you might have to file a bug over there.

lambda invokes with serverless-offline should work as well (has been recently implemented), although I have not used it myself [yet].

dnalborczyk commented 5 years ago

@xiaoqiaomm feel free to re-open, if you feel this issue is related to serverless-offline.

ghost commented 5 years ago

Hey @dnalborczyk , I am facing the same issue, trying to dynamically invoke another lambda using the AWS SDK from a local lambda, such as described in this issue.

I do not use serverless invoke local, but run serverless offline, call my Lambda1 which invokes Lambda2, and the response from that is a 415 Unsupported Media Type error.

Calling Lambda2 directly (through http, not using the SDK) works fine locally.

However I am not sure if the bug origin is from this plugin or from the SDK itself?

dnalborczyk commented 5 years ago

hey @flosch-hb

As far a I know the aws-sdk does the http request for you, and should work as well. If you could provide a small/simple repro I can have a look.

re-opening for now and marking as bug

ghost commented 5 years ago

Sure, I can probably provide that early next week, thanks for looking :)

I am not sure if lambda.invoke() use an HTTP layer at all actually? This is the part that confuse me the most with invocation...

ghost commented 5 years ago

Hej @dnalborczyk, sorry about the wrong report, you are actually right, it works locally without problem. Not sure why I faced this bug 2 weeks ago then, but if it comes back, I would create a new issue to reproduce it. I guess this can be closed, sorry again!

EDIT: this happen indeed when you run sls invoke local on the scenario described by the author. But not sure what is the cause of it then?

moravcik commented 5 years ago

@flosch-hb did you find what was your problem and how did you resolve it?

I am facing the same issue - running serverless-offline, invoking local lambda from within another lambda and getting the Unsupported Media Type error

ghost commented 5 years ago

@moravcik it happens when you run sls invoke local on a lambda ran offline, I did not find any solution but according to @dnalborczyk this would be related to serverless itself, no serverless-offline. We should probably open an issue there?

moravcik commented 5 years ago

@flosch-hb my use case is little bit different, I don't use sls invoke local, but sls offline start. I have HTTP event-based lambda, from which I try to invoke another lambda - all of them running locally.

Finally I managed to get it working via serverless-offline-lambda plugin, so I don't need to open more issues ;) Thank you, anyway.

dnalborczyk commented 5 years ago

@moravcik

If you could create a small repro repository which outlines your problem that would be great. the 'lambda-invokestuff inserverless-offline` is fairly new, so it might contain bugs.

vepanimas commented 5 years ago

@xiaoqiaomm,

Huh, I had the same error and spent a lot of time trying to figure out what's going on. You should know, that errors like {"message":"Unsupported Media Type","code":"UnknownError","time":"2019-08-28T02:02:12.671Z","statusCode":415,"retryable":false,"retryDelay":36.433060399406216}, null, {"FunctionName":"hello2","InvocationType":"Event","Payload":"{\"body\":{\"test\":1}}"} could be thrown if you specified the wrong function name.

Function name should be specified as {service_name}-{stage}-{name}, not {name}.

Correct: myservice-prod-my-function-local

Wrong: my-function-local

Hope that will help somebody 😄.

moravcik commented 5 years ago

@dnalborczyk I have prepared a small repo to reproduce this problem: https://github.com/moravcik/serverless-offline-unsupported-media-type

After updated to full function name with service name and stage, as suggested by @vepanimas, it works. Is this the intended behavior or a bug?

dnalborczyk commented 5 years ago

thank you for the repo @moravcik ! I'll have a look. Even if it's not a bug, or even if it works as intended, user experience could still be improved with better error messages.

vepanimas commented 5 years ago

@dnalborczyk, It looks like the error itself is from AWS Sdk, because it can't reach the specified endpoint. We can have a catch-all route in serverless offline (like {apiVersion}/functions/*/invocations) to handle these errors.

grbknr1996 commented 4 years ago

https://stackoverflow.com/questions/58735411/unable-to-invoke-a-lambda-from-another-lambda-using-aws-serverless-offline

please help me out and thanks in advance

dnalborczyk commented 4 years ago

hey @grbknr1996 you can have a look at the lambda invoke test here: https://github.com/dherault/serverless-offline/tree/master/tests/integration/lambda-invoke yo give you some ideas.

you might be just missing the access key id and secret access key, not sure.

grbknr1996 commented 4 years ago

Hi @dnalborczyk Please see my question.Its giving unsupported media type I have tried like what you have tried

dnalborczyk commented 4 years ago

your endpoint /jobs might be wrong. the error message btw is misleading and doesn't point to the actual error. you can literally clone (copy/paste) the test case and start it manually yourself and compare to your own implementation.

evbots commented 4 years ago

I realized the local "invoke" endpoint port is different from the local webserver port. I was setting my webserver port to 4000, but the invoke port is 3002 by default on the 6.x branch. This means your lambda endpoint config must be whatever the invoke port is (which for me is 3002). { endpoint: 'http://localhost:3002' }

dnalborczyk commented 4 years ago

@dnalborczyk, It looks like the error itself is from AWS Sdk, because it can't reach the specified endpoint. We can have a catch-all route in serverless offline (like {apiVersion}/functions/*/invocations) to handle these errors.

the problem is that this exception is being thrown by the aws-sdk. I don't think it's a good idea to give it a special treatment over any other exception being thrown by any framework. although we could point it out in the documentation.

malnaqeeb commented 4 years ago

@dnalborczyk I have prepared a small repo to reproduce this problem: https://github.com/moravcik/serverless-offline-unsupported-media-type

After updated to full function name with service name and stage, as suggested by @vepanimas, it works. Is this the intended behavior or a bug?

Hi @moravcik , I get the repo on my machine and it's work just fine. I copied the lambda functions to my project (in the same name and added the functions to serverless.yml) but get the error again. Aslo when I run your example i get in the terminal :

Serverless: Routes for apiTest:
Serverless: GET /api
Serverless: POST /{apiVersion}/functions/serverless-offline-unsupported-media-type-example-test-apiTest/invocations

Serverless: Routes for invokeTest:
Serverless: POST /{apiVersion}/functions/serverless-offline-unsupported-media-type-example-test-invokeTest/invocations

But in my terminal, I got:

Serverless: Routes for apiTest:
Serverless: GET /api

Serverless: Routes for invokeTest:
Serverless: (none)
Serverless: Offline Lambda Server listening on http://localhost:4000

So could you help me to figure out which mistake I have done?

thienkhoi1 commented 4 years ago

@xiaoqiaomm,

Huh, I had the same error and spent a lot of time trying to figure out what's going on. You should know, that errors like {"message":"Unsupported Media Type","code":"UnknownError","time":"2019-08-28T02:02:12.671Z","statusCode":415,"retryable":false,"retryDelay":36.433060399406216}, null, {"FunctionName":"hello2","InvocationType":"Event","Payload":"{\"body\":{\"test\":1}}"} could be thrown if you specified the wrong function name.

Function name should be specified as {service_name}-{stage}-{name}, not {name}.

Correct: myservice-prod-my-function-local

Wrong: my-function-local

Hope that will help somebody 😄.

This worked for me. Thank you a lot.

phmasek commented 3 years ago

I received the same error but it was because I was using the wrong port on my lambdaConfig.endpoint. I incorrectly set it to the httpPort (default: 3000) instead of the correct lambdaPort (default: 3002).

(Read more here: https://www.serverless.com/plugins/serverless-offline#usage-and-command-line-options)

Maybe this will help someone looking around.

andrehadianto commented 3 years ago

hey @grbknr1996 you can have a look at the lambda invoke test here: https://github.com/dherault/serverless-offline/tree/master/tests/integration/lambda-invoke yo give you some ideas.

you might be just missing the access key id and secret access key, not sure.

How can I go about to insert the access key id and secret access key? Is it in the .env?

smcelhinney commented 3 years ago

I realized the local "invoke" endpoint port is different from the local webserver port. I was setting my webserver port to 4000, but the invoke port is 3002 by default on the 6.x branch. This means your lambda endpoint config must be whatever the invoke port is (which for me is 3002). { endpoint: 'http://localhost:3002' }

This is what it was for me. Thanks for saving my mental health.

RishivikramN commented 3 years ago

I received the same error but it was because I was using the wrong port on my lambdaConfig.endpoint. I incorrectly set it to the httpPort (default: 3000) instead of the correct lambdaPort (default: 3002).

(Read more here: https://www.serverless.com/plugins/serverless-offline#usage-and-command-line-options)

Maybe this will help someone looking around.

This helped me, Thanks!!!

IgorStetsiuk commented 2 years ago

Hi! In my case, there were two ports configurations. So when you invoke Lambda 2 in case (API Gateway -> Sync Lambda 1 -> Invoke Async Lambda 2) pay attention to the endpoint configuration. I was needed to change the port to be 4006 instead of 4005

image