I'm seeing two errors in my code.I'm trying to call external API using API-Gateway --> AWS lambda
const getStatus = (defaultOptions, path, payload) => new Promise((resolve, reject) => {
const options = { ...defaultOptions, path, method: 'GET' };
const req = https.request(options, res => {
let buffer = "";
res.on('data', chunk => buffer += chunk)
res.on('end', () => resolve(JSON.parse(buffer)))
});
req.on('error', e => reject(e.message));
req.write(JSON.stringify(payload));
req.end();
})
exports.handler = async (event) => {
const defaultOptions = {
host: event.xyz.abc.com,
port: 443,
headers: {
'Content-Type': 'application/json',
'Authorization': 'Bearer 12345432157'
}
}
var status_info = await getStatus(defaultOptions, event./userId, '');
const response = {
statusCode: 200,
body: JSON.stringify(status_info),
};
return response;
};
1.{ "errorType": "TypeError", "errorMessage": "Cannot read properties of undefined (reading 'abc')", "trace": [ "TypeError: Cannot read properties of undefined (reading 'abc')", " at Runtime.exports.handler (/var/task/index.js:16:29)", " at Runtime.handleOnceNonStreaming (file:///var/runtime/index.mjs:1028:29)" ] }
2.var status_info = await getStatus(defaultOptions, event./userId, '');
unexpected token /
There are many good ways to call the external API from lambda.
But there are many cases where axios does the job very well.
https://kuchbhilearning.blogspot.com/2022/10/call-external-api-from-aws-lambda-using.html
A short site example of the way that needs to be used with axios.
Related
I dont know why but if function not get error, it work perfectly , but when it get error, catch always display
res.end is not a function
it like i can't use res in catch, but in try res still work, Am i missing something?
import axios from "axios";
import { NextApiResponse } from "next";
const handler = async (res: NextApiResponse): Promise<void> => {
return new Promise((resolve, _) => {
axios({
method: "get",
headers: { "Content-type": "application/json" },
url:
process.env.NODE_ENV === "production"
? "https://.../refresh_token"
: "http://localhost:4000/refresh_token",
withCredentials: true,
})
.then((response) => {
res.statusCode = 200;
res.setHeader("Content-Type", "application/json");
res.setHeader("Cache-Control", "max-age=180000");
res.end(JSON.stringify(response.data));
resolve();
})
.catch((error) => {
res.statusCode = 500;
res.end(JSON.stringify((error as Error).message));
resolve();
});
});
};
export default handler;
The first parameter in your handler function should be a NextApiRequest object, not a NextApiResponse object:
const handler = async (req: NextApiRequest, res: NextApiResponse): Promise<void> => { //...
Since req is expected to be the first parameter, passing res there will mean calling end on the NextApiRequest object — an error because end doesn't exist there.
I want to code the multipart-form POST REQUEST below using apollo-datasource-rest
My attempt to code this leads to a BAD REQUEST error
const { RESTDataSource } = require('apollo-datasource-rest');
process.env.NODE_TLS_REJECT_UNAUTHORIZED = '0';
class SalesforceApi extends RESTDataSource {
constructor() {
super();
this.initialize({});
this.getAccessToken()
.then((accessToken) => {
this.headers = {
Authorization: `Bearer ${accessToken}`,
};
});
}
async getAccessToken() {
console.log('Getting Salesforce access token');
try {
const response = await this.post(
'https://test.salesforce.com/services/oauth2/token',
{
username: 'FILTERED#FILTERED',
password: `${'FILTERED'}`,
grant_type: 'password',
client_id: 'FILTERED',
client_secret: 'FILTERED',
},
{
headers: {
'Content-Type': 'multipart/form-data',
},
},
);
const { accessToken } = response;
console.log(`ChangeGear sessionId: ${accessToken}`);
return accessToken;
} catch (error) {
console.log(`${error}`);
}
return 'No access token!!!';
}
module.exports = SalesforceApi;
[server:salesforce:local] POST https://test.salesforce.com/services/oauth2/token (343ms)
[server:salesforce:local] Error: 400: Bad Request
If memory serves correctly, form data is serialized slightly differently hence why the FormData interface exists. And the apollo-datasource-rest's this.post method is just a wrapper around fetch, so something like the below should work.
Instead of passing the body as a JSON object, try something like this
const formData = new FormData();
formData.append('username', 'FILTERED#FILTERED');
// ... more append lines for your data
const response = await this.post(
'https://test.salesforce.com/services/oauth2/token',
formData
{
headers: {
'Content-Type': 'multipart/form-data',
},
},
);
Hi What I am trying to do is to save the localStorage in to variable somewhere , So i can refer to it in different test scenario but I am not sure if that is possible as my token1 variable is always empty.
this is my support/command.js file
Cypress.Commands.add('postTokenLogin', () => {
cy.request({
method: 'POST',
url: '***/people/sign_in',
body: {
"login": "test#test.com",
"password":"***",
},
headers:{
'content-type': 'application/json'
}
}).then((response) => {
expect(response.body).have.property('firstName')
expect(response.body.token).have.property('authorization')
cy.setLocalStorage('token',response.body.token.authorization )
})
})
now in my test case I wanna be able to use that token inside my header
import "cypress-localstorage-commands";
let token1 = '';
describe('HTTP Example', ()=>{
before(() => {
cy.postTokenLogin();
cy.saveLocalStorage();
});
beforeEach(() => {
cy.restoreLocalStorage();
});
it("the value of JWT Token should exist in localStorage", () => {
cy.getLocalStorage('token').then(token => {
cy.log("the token", token); // I get JWT Token in here
});
});
it('GET List ', ()=>{
cy.getLocalStorage('token').then((token) => {
token1 = token;
})
cy.log('Let Tokennn is ===>' , token1) // Always Empty
cy.request({
method: 'GET',
url: '***/peopleList',
headers:{
'content-type': 'application/json',
'Authorization': token1 // ===> this is also empty
}
}).then((response) => {
expect(response.body).have.property('firstName')
expect(response.body).have.property('lastname')
})
})
})
Can I have another it('GET colours ', ()=>{}) and just pass the token1?
You are working in a async code, so if you need to use the token instead of validation, you should nest the code like below
import "cypress-localstorage-commands";
let token1 = '';
describe('HTTP Example', () => {
before(() => {
cy.postTokenLogin();
cy.saveLocalStorage();
});
beforeEach(() => {
cy.restoreLocalStorage();
});
it("the value of JWT Token should exist in localStorage", () => {
cy.getLocalStorage('token').then(token => {
cy.log("the token", token); // I get JWT Token in here
});
});
it('GET List ', () => {
cy.getLocalStorage('token').then((token) => {
token1 = token;
cy.log('Let Tokennn is ===>', token1) // Always Empty
cy.request({
method: 'GET',
url: '***/peopleList',
headers: {
'content-type': 'application/json',
'Authorization': token1 // ===> this is also empty
}
}).then((response) => {
expect(response.body).have.property('firstName')
expect(response.body).have.property('lastname')
})
})
})
I have the following code which I import and use in a VueJS application.
I want to be able to errors returned by the API centrally and it seems that interceptors would do the job for me but I don't understand where I set them up
import axios from 'axios'
import store from './store/index'
export default () => {
try{
var token = store.state.user.token.token
}catch(err){
var token = ""
}
return axios.create({
baseURL: "http://localhost:3333/api/v1",
headers: {
"Authorization": `Bearer ${token}`
}
})
}
I have tried this, but it does not work.
import axios from 'axios'
import store from './store/index'
axios.interceptors.request.use((config) => {
console.info("debug ", config);
return config;
}, (error) => {
console.error("debug ", error);
return Promise.reject(error);
});
export default () => {
try{
var token = store.state.user.token.token
}catch(err){
var token = ""
}
return axios.create({
baseURL: "http://localhost:3333/api/v1",
headers: {
"Authorization": `Bearer ${token}`
}
})
}
After some fiddling, I have worked it out.
You have to first create an axios object with axios.create(), then assign your intercepters to the object after which you can return the object. Here is the code I used that worked.
var axiosInstance = axios.create({
baseURL: "http://localhost:3333/api/v1",
headers: {
"Authorization": `Bearer ${token}`
},
})
//This allows you to intercept the request before it is sent and alter headers or anyting else that is passed to the axios config.
axiosInstance.interceptors.request.use((config)=>{
return config
}, (error) => {
console.log("Interceptor Request Error" + error)
})
//This allows you to intercept the response and check the status and error messages and if ncessary reject the promise.
axiosInstance.interceptors.response.use((response) => {
console.log(response.data)
return response
}, (error) => {
console.log("Interceptor Response Error" + error)
})
return axiosInstance
Now I know how to do this, I could move my Authorization code out of the create function and put it in the request interceptor axiosInstance.interceptors.request.use
I try to do a simple post request with axios.
My code snippet:
const getOauthToken = async () => {
try {
const headers = {
'Content-Type': 'application/x-www-form-urlencoded',
'X-ProxyPass' : '...',
}
const data = {
...
}
return await axios.post('/oauth2/token', data, {headers: headers});
} catch (error) {
throw new Error(`Unable to get an authentication token. Reason ${error}`);
}
};
This call fails with http 400. When I set the headers as default with
axios.defaults.headers.post['X-ProxyPass'] = '...';
axios.defaults.headers.post['Content-Type'] = 'application/x-www-form-urlencoded';
then it works.
Found the solution in the documentation of axios.
If I use "application/x-www-form-urlencoded", I have to use querystring to serialize in the needed format.
return await axios.post('/oauth2/token', querystring.stringify(data), {headers: headers});
But why it works, when I set the headers as default headers i still mysterious.