aws lambda - 503 service unavailable when calling 3rd party API using axios - node.js

I have a lambda function which is calling 3rd party API using axios, when it calls 3rd party API, it creates a new entry on their database, which is working fine but the lambda function is returning 503 service unavailable
Following is my code -
let algcon = {
method: 'post',
url: constants.API_URL,
timeout: 1000 * 7,
headers: {
'Content-Type': 'application/json',
"User-Agent": "axios 0.21.1",
'token': myToken ? JSON.stringify(myToken.access) : ''
},
data: invoiceData,
};
await axios(algcon).then(function (response) {
}).catch(function (error) {
console.log(error) //here it is throwing 503 service unavailable error
});
I have increased lambda execution time but still getting the same error. Please help!!

Your code looks fine to me,
the default timeout of an API gateway response is 6500 milliseconds
You can update it as -
Go to API gateway
Select Lamda function
Click on integration
Click on Manage integration
Update default timeout
Like I did in below screenshot -

Related

ETIMEDOUT error when making a request to sendgrid API

I'm using the node js request module to send emails via sendgrid. I am getting the error ETIMEDOUT. I intend on using node-retry npm module to retry the sending, but how can I detect what the error code is? Does the sendgrid API return the error code somehow? Also when I do detect the error code, is it just a matter of waiting X seconds to send the email again? If so how do I determine what X is?
_makeAPIRequest (httpMethod, url, body) {
var defer = Q.defer();
var options = {
method: httpMethod,
url: this.SENDGRID_API_URL + url,
headers: {
'content-type': 'application/json',
authorization: 'Bearer ' + SENDGRID_API_KEY
},
body: body,
json: true
};
request(options, function (error, response, body) {
if (error) {
console.dir(error);
return defer.reject(error);
}
defer.resolve(body);
});
return defer.promise;
}
ETIMEDOUT is an OS error message. It indicates a failed attempt, at the TCP/IP level, to connect to a remote host, probably the one mentioned in SENDGRID_API_URL.
The default value for that is https://api.sendgrid.com/v3/. For some reason, possibly an outbound firewall or some sort of network configuration trouble, your nodejs program cannot reach that URL, and waits for a response. You should check your value of that URL.
If this is intermittent (doesn't happen all the time) you probably can wait a few seconds and try again.
If it starts happening after you've sent a bunch of emails, you may be hitting a limit at sendgrid. Pace out your sending of emails; try putting a half-second delay between them.

axios get request Error: Request failed with status code 504

here is my code that makes an Http Get request to an API end point from one of the services running on Amazon Fargate service. The API is powered by Amazon API gateway and Lambda. Also this is a private api used with in the VPC and I also have setup the apigateway VPC end point to facilitate the same. I have received this error only once. All the subsequent calls made to the API were successful.
My suspicion is that the lambda was not warm and that resulted a timeout. I am going to try setting a timeout for the axios code. any suggestions welcome
async getItems(): Promise < any > {
try {
let url = `https://vpce-[id].execute-api.ap-southeast-2.vpce.amazonaws.com/prod/items`
const response = await axios.get(url, {
headers: {
'Authorization': `Bearer ${token}`,
'x-apigw-api-id': `[api-id]`
}
});
return response.data;
} catch(error) {
console.log(error);
throw error;
}
}
Turns out my lambda is timing out after the 30 seconds configured time. I could increase the lambda timeout, but the configurable timeout for API gateway is 30 seconds.
It has only happened once and i believe that it's because lambda cold start. As a workaround, I am taking the retry approach. The API request will be retried 3 times.

cognitive computer vision api, Initial 202 response from api call, then 401 error from Operation-Location

Running this in a reactjs project, this is my current code:
let response = await fetch('https://apis-cv.cognitiveservices.azure.com/vision/v1.0/recognizeText?handwriting=true', {
method: 'POST',
headers: { 'Content-Type': 'application/octet-stream', 'Ocp-Apim-Subscription-Key': '<MY KEY HERE>' },
body: this.makeblob(event.target.result)
});
console.log(response);
My initial response has status 202: with an Operation-Location given. (i.e https://apis-cv.cognitiveservices.azure.com/vision/v1.0/textOperations/a60b86b2-bf85-4e3b-8beb-65dc075e81d7 )
but the Operation-Location results in a 401:
{"error":{"code":"401","message":"Access denied due to invalid subscription key or wrong API endpoint. Make sure to provide a valid key for an active subscription and use a correct regional API endpoint for your resource."}}
I have also tried with a url and content-type: application/json and get the same result.
The error message is quite clear: you forgot to add the 'Ocp-Apim-Subscription-Key' in your second query, when you try to get the result of your TextOperations.
Can you add your implementation of how you try to get the result?

AWS lambda basic-authentication without custom authorizer

I have a problem with setting up the basic authentication for my AWS lambda function written in Node.js.
The problem:
AWS lambda function which is a proxy for an additional service. This function only forwards the whole request and give the user the whole response. That's why I need to force the usage of the Authentication header and I would like to have the prompt window for passing the credentials: https://developer.mozilla.org/en-US/docs/Web/HTTP/Authentication
Apart from the proxy part of my lambda function, I focused on the problem with authentication and I have written this code:
export const proxy = async (event) => {
const authorizationHeader = event.headers.Authorization;
if (typeof authorizationHeader === undefined) {
throw new Error("Unauthorized");
}
...
};
service:
name: proxy-auth-test
plugins:
- serverless-webpack
provider:
name: aws
runtime: nodejs8.10
memorySize: 128
timeout: 10
functions:
proxy-async:
handler: handler.proxy
events:
- http:
method: get
path: api/proxy
resources:
Resources:
GatewayResponse:
Type: 'AWS::ApiGateway::GatewayResponse'
Properties:
ResponseParameters:
gatewayresponse.header.WWW-Authenticate: "'Basic'"
ResponseType: UNAUTHORIZED
RestApiId:
Ref: 'ApiGatewayRestApi'
StatusCode: '401'
The endpoint is working properly, but I can't get the prompt window for passing the credentials. I set up the GatewayResponse according to this https://medium.com/#Da_vidgf/http-basic-auth-with-api-gateway-and-serverless-5ae14ad0a270 but I don't wanna provide the additional lambda function which is responsible only for authorization of the users.
In my case, I can't authorize the users before executing the final lambda function because this function only forwards the request (credentials too), nothing more.
Has anyone ever tried to setup basic auth with the prompt window without the additional authorizer with the usage of serverless and AWS lambda?
When returning a response from an integration the WWW-Authenticate is remapped to X-Amzn-Remapped-WWW-Authenticate (1). Browsers will not handle this remapped header so they don't show a prompt.
This means that you have to move your authorization logic to the Lambda Authorizer at a HTTP request level and return 'unauthorized' to the callback as stated in the medium link that you referenced. This is the only way to return a WWW-Authenticate header as of now.
Sources:
1: https://docs.aws.amazon.com/apigateway/latest/developerguide/api-gateway-known-issues.html
You are not returning statusCode in the response. The article you are following seems to be using Custom Authorizer that always returns 401 status code with callback('Unauthorized'). Your Lambda function needs to return appropriate error code and headers.
if (typeof authorizationHeader === undefined) {
return {
statusCode: 401,
body: 'unauthorized',
headers: {
'WWW-Authenticate': 'Basic'
}
}
}

OpenWhisk returns whole response object instead of just the data

I have an OpenWhisk action that returns a response object, because I want to be able to control the headers and HTTP status code. My action returns something like this:
return {
statusCode: 200,
headers: { 'Content-Type': 'application/json' },
body: { x: 1 }
};
I deploy the action in a package from the command-line with:
wsk action update myproj/myaction --kind nodejs:6 myaction.zip --web true
And expose it as API on IBM Cloud Functions with:
wsk api create /myproj /myaction get myproj/myaction
But when I visit the API call with curl, I get the whole response object, not just the data:
curl '.../myproj/myaction'
{
"statusCode": 200,
"headers": {
"Content-Type": "application/json"
},
"body": { x: 1 }
}
I was expecting to get just { x: 1 }.
What do I need to do to fix this?
The default API Gateway service behaviour expects body data to be returned from the action, not the full HTTP response parameters.
Change the return statement to the following to resolve this issue.
return {
x: 1
};
Controlling the full HTTP response using the returned action parameters needs the --response-type http flag setting on the web action.
$ wsk api create /myproj /myaction get myproj/myaction --response-type http

Resources