I'm trying to create an Azure Function to take POST requests from Slack Message Interactions. I'm able to get a test request to come in following this guide using ngrok. However the payload is not coming in like a normal POST request body. Assuming this is because it's a "parameter" payload and not a body.
module.exports = async (context, req) => {
const { body } = req;
context.log(body);
context.res = {
body,
};
};
Output:
payload=%7B%22type%22%3A%22block_actions%22%2C%22user%22%3A%7B%22id%22%3A%22xxx%22%2C%22username%22%3A%22...
How do I parse this POST parameter payload into JSON in an Azure Function?
With help from this post I was able to figure this out for my use case.
Using qs package npm i qs
const { parse } = require('qs');
module.exports = async (context, req) => {
const payload = JSON.parse(parse(req.rawBody).payload);
context.log(payload);
context.res = {
payload,
};
};
Output:
{
type: 'block_actions',
user: {
id: 'xxx',
username: 'xxx',
name: 'xxx',
team_id: 'xxx'
},
api_app_id: 'xx',
...
}
Related
I'm struggling with AXIOS: it seems that my post request is not using my Cookie.
First of all, I'm creating an Axios Instance as following:
const api = axios.create({
baseURL: 'http://mylocalserver:myport/api/',
header: {
'Content-type' : 'application/json',
},
withCredentials: true,
responseType: 'json'
});
The API I'm trying to interact with is requiring a password, thus I'm defining a variable containing my password:
const password = 'mybeautifulpassword';
First, I need to post a request to create a session, and get the cookie:
const createSession = async() => {
const response = await api.post('session', { password: password});
return response.headers['set-cookie'];
}
Now, by using the returned cookie (stored in cookieAuth variable), I can interact with the API.
I know there is an endpoint allowing me to retrieve informations:
const readInfo = async(cookieAuth) => {
return await api.get('endpoint/a', {
headers: {
Cookie: cookieAuth,
}
})
}
This is working properly.
It's another story when I want to launch a post request.
const createInfo = async(cookieAuth, infoName) => {
try {
const data = JSON.stringify({
name: infoName
})
return await api.post('endpoint/a', {
headers: {
Cookie: cookieAuth,
},
data: data,
})
} catch (error) {
console.log(error);
}
};
When I launch the createInfo method, I got a 401 status (Unauthorized). It looks like Axios is not using my cookieAuth for the post request...
If I'm using Postman to make the same request, it works...
What am I doing wrong in this code? Thanks a lot for your help
I finally found my mistake.
As written in the Axios Doc ( https://axios-http.com/docs/instance )
The specified config will be merged with the instance config.
after creating the instance, I must follow the following structure to perform a post requests:
axios#post(url[, data[, config]])
My requests is working now :
await api.post('endpoint/a', {data: data}, {
headers: {
'Cookie': cookiesAuth
}
});
Hello I'm trying to use the coinase api using axios to make request. I have set up the neccessary api authentication using SHA256 HMAC. I have been able to make some GET Request and got response. I have been trying to make a POST Request but i have been getting 401 status code.
const name = "Test BTC Address";
const body = {
name: name
}
var encHash = {
baseUrl: 'https://api.coinbase.com',
method: 'POST',
path: '/v2/accounts/bbc2e3f7-a851-50ab-b4b3-a0f2a700846f/addresses',
body: body,
scopes: "wallet:addresses:create"
};
const sign = generateHashKey(encHash, key.APISECRET);
console.log(sign);
const config = {
headers: {
'CB-ACCESS-SIGN': sign.signature,
'CB-ACCESS-TIMESTAMP': sign.timestamp,
'CB-ACCESS-KEY': key.APIKEY,
'CB-VERSION': '2021-10-15'
}
}
const url = `${encHash.baseUrl}${encHash.path}`
console.log(url);
var options = await axios.post(url, body, config);
return res.send({data: options.data})
} catch (error) {
// console.error(error);
return res.send({error})
} ```
I read a lot of topics about how to handle POST requests with Lambda Proxy Integration from AWS, but no one of them helps me to solve my issue.
I read that if we are using a Lambda Proxy Integration the post body have to be like this :
{
"body": "{\"name\":\"Mickael2\"}"
}
Here is my Lambda function (very basic):
const AWS = require('aws-sdk')
const dynamoDB = new AWS.DynamoDB({ region: 'eu-west-3'})
const { v4: uuidv4 } = require('uuid');
exports.handler = (event, context, cb) => {
const body = JSON.parse(event.body).body;
const name = JSON.parse(body).name;
let uuid = uuidv4();
let response = {
statusCode: 200,
headers: {
'x-custom-header': 'My Header Value',
},
body: JSON.stringify({})
};
const params = {
Item: {
"id": {
S: uuid
},
"name": {
S: name
}
},
TableName: "Users3"
};
dynamoDB.putItem(params, function(err, data) {
if (err){
console.log(err, err.stack);
cb(null, response);
}
else{
console.log(data);
response.body = JSON.stringify({name:name, uuid: uuid })
cb(null, response);
}
});
};
For example when i am trying to give this body:
{
"name":"Mickael"
}
And doing console.log(event.body) i am getting:
{
"name": "Mickael" }
But when I am trying to get access to event.body.name i am getting undefined
Does someone have any other way to work with Post request on Lambda Proxy Integration? Thanks.
I see that you are using the Lambda function to push into DynamoDB. Since you're asking about other ways to handle it, if this Lambda function isn't doing anything else (and assuming you're using API Gateway to kick off the Lambda Function), my recommendation is to skip Lambda altogether and just go directly from APIGateway to DynamoDB. In your APIGW Integration Request, set it to use AWS Service instead of Lambda, then select DynamoDB as the service, Set the HTTP Method to POST, and set the Action to PutItem. And for the Integration Request Mapping Template, build out that same JSON as you are doing above {Item: {"id": {S: uuid}, "name": {S: name}}, TableName: "Users3"}.
I read that if we are using a Lambda Proxy Integration the post body have to be like this:
{
"body": "{\"name\":\"Mickael2\"}"
}
Depends what you mean by "post body", is that what you're sending or what you're receiving? If you're sending it, you can structure it however you want. If you're receiving it (i.e. in the lambda function), the structure will be as in your example, i.e. a body key in the event object, containing the stringified payload.
const body = JSON.parse(event.body).body;
If you're parsing the body, and the body is "{\"name\":\"Mickael2\"}" (i.e. stringified payload), then there is no body key/property on the resultant object, and therefore const body === undefined.
If you actually sent { body: "{\"name\":\"Mickael2\"}" } as the payload, which you shouldn't, then that code is valid.
const name = JSON.parse(body).name;
Depending on the actual payload, body is either an object, undefined, or a string at this point. If it's an object or undefined then parsing it again should throw an exception. If it's not doing so then perhaps it's because you are in fact supplying a payload of { body: "{\"name\":\"Mickael2\"}" }, in which case that code is valid, but as stated it's the wrong way to send the payload.
Your payload should be:
{
name: "Mickael2"
}
When it goes through proxy integration into your lambda, the event object will look like so (irrelevant bits removed):
{
body: "{\"name\":\"Mickael2\"}"
}
So this is how you should handle it in your lambda:
const payload = JSON.parse(event.body);
const name = payload.name;
I have the following lambda function that works when called from the front-end React app:
// Update a contact
module.exports.updateContact = async (event, _context) => {
const id = event.pathParameters.id;
const body = JSON.parse(event.body);
const paramName = body.paramName;
const paramValue = body.paramValue;
const params = {
Key: {
id: id
},
TableName: contactsTable,
ConditionExpression: 'attribute_exists(id)',
UpdateExpression: 'set ' + paramName + ' = :v',
ExpressionAttributeValues: {
':v': paramValue,
},
ReturnValues: 'ALL_NEW'
};
try {
const res = await db.update(params).promise();
}
catch (err){
console.log(err);
return err;
}
const response = {
statusCode: 200,
headers: {
'Access-Control-Allow-Origin': '*',
'Access-Control-Allow-Credentials': true,
},
body: JSON.stringify({
status: 'updated!',
[paramName]: paramValue,
}),
};
return response;
};
But it fails with status code 502 & 'InternalServerErrorException' message when called from Postman.
I tried to solve it with one of the suggestions found on stackoverflow with method override:
It doesn't work and I'm now getting status code 403 and 'MissingAuthenticationTokenException'.
I'm not sure what I'm doing wrong, seeking some guidance. Thank you.
It seems the API endpoint has an Authorizer configured on the API Gateway and the front end is sending the correct credentials, while the Postman configuration is not.
I would suggest to use the browser dev tools selecting the PUT request and copy it as cUrl:
then you can paste the copied cUrl command into the Postman request. It will prefill all the parameters: method, body and the headers.
hope this help
I can log in and see posts, but I can't seem to comment on these posts pragmatically, and have 0 clue on how to read Direct Messages. Here is my code for logging in and getting media id.
// import axios from 'axios';
// import cheerio from 'cheerio';
const request = require('request-promise');
const cheerio = require('cheerio');
class Instagram {
async commentOnPost({ mediaURL, comment }) {
console.log("here commentPost");
let mediaId = await this.getMediaKey({ mediaURL });
// post comment
const url = `https://www.instagram.com/web/comments/${mediaId}/add/`;
const data = {
'comment_text': comment
}
let commentData;
try {
commentData = await this.session({
method: "POST",
url,
form: data,
headers: {
'X-Requested-With': 'XMLHttpRequest',
'Referer': "https://www.instagram.com/" + mediaURL
},
json: true
});
} catch (err) {
console.log(err);
}
console.log(commentData);
}
async function testCase() {
let i = new Instagram();
await i.login({ username: "username", password: "password" });
await i.getMediaKey({ mediaURL: "/p/B7PGlAKl5vx/" });
await i.commentOnPost({ mediaURL: "/p/B7PGlAKl5vx/", comment: "pogchamp!" });
}
};
According to the logs, the code is submitting everything correctly, but I get a 403 error when I send a request to comment on a post. Anyone have experience with this? I have seen libraries like https://github.com/dilame/instagram-private-api but I am not sure how they work, nor how to replicate it in my code.