Using fastify and fluent-json-schema
I'm trying to figure out how to make a POST route body required in the openapi schema output
const postSomethingSchema = S.object()
.prop("fieldA", S.string())
export const postSchema = {
operationId: "createSomething",
body: postSomethingSchema,
response: { 200: somethingSchema },
};
Today, this generates the following, (without the required key I'm looking for of course)
"post": {
"operationId": "createSomething",
"requestBody": {
"required": true, // I can't figure out how to get this!
"content": {...}
Related
The LinkedIn API documentation for UGC Posts seems to imply you can share a post with a document by setting shareMediaCategory: "NATIVE_DOCUMENT", but there is no additional information about how to make this work. The documentation seems limited to images/videos.
This is what I have tried so far.
const registerUpload = () => {
// Doesn't seem to be documented, but the API responses on the LinkedIn site
// returns 'urn:li:digitalmediaRecipe:feedshare-document', so it seemed like a decent guess
const type = 'document'; // 'image' or 'video' works fine
return axios({
method: 'post',
url: 'https://api.linkedin.com/v2/assets?action=registerUpload',
data: {
registerUploadRequest: {
owner,
recipes: [
`urn:li:digitalmediaRecipe:feedshare-${type}`,
],
serviceRelationships: [
{
identifier: 'urn:li:userGeneratedContent',
relationshipType: 'OWNER',
},
],
...(synchronous ? {
supportedUploadMechanism: [
'SYNCHRONOUS_UPLOAD',
],
} : {}),
},
},
headers: {
Authorization: `Bearer ${tokenInfo.token}`,
'X-Restli-Protocol-Version': '2.0.0',
},
});
}
which returns the following
{
serviceErrorCode: 100,
message: 'Field Value validation failed in REQUEST_BODY: Data Processing Exception while processing fields [/registerUploadRequest/recipes/relationshipType]',
status: 403
}
This doesn't make sense to me since registerUploadRequest/recipes/relationshipType doesn't match the documented schema. Is there another way to register document assets for UGC posts?
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;
Hi I have been experimenting with webhooks and I'm wondering how do you send a normal message(not embeded) through a webhook with a custom avatar and name
const user = message.mentions.users.first() || client.users.cache.get(args[0]);
let announcement = args.slice(1).join(" ");
if(!announcement) return message.channel.send(`lol say something`)
const wc = new WebhookClient('id', 'token')
const embed = new MessageEmbed()
.setTitle("").setColor('GREEN').setTimestamp().setDescription(announcement)
wc.send({
username : user.username,
avatarURL : user.displayAvatarURL({ dynamic : true }),
embeds : [embed]
})
}
```
If you wish to send Discord webhooks you need to make a POST API request to the webhook url.
For that you can basically use any module you want however in this example I'll use node-fetch. Simply install it in your console
npm install node-fetch
and then require it where you need to use it
const fetch = require('node-fetch');
Now that we have what we need to make it work lets create the API request.
For that we start with the params variable. Here you set all the things that make the webhook look like you want it to look. Note: I also included how to send embeds just in case. If you want to see all options check here.
var params = {
username: "Your name",
avatar_url: "",
content: "Some message you want to send",
embeds: [
{
"title": "Some title",
"color": 15258703,
"thumbnail": {
"url": "",
},
"fields": [
{
"name": "Your fields here",
"value": "Whatever you wish to send",
"inline": true
}
]
}
]
}
Now that we have the params we can create the actual POST request. For that you simply call the fetch function and provide the webhook url.
First you specify the method you want to use. By default the method is GET. Next make sure to set the headers to 'Content-type': 'application/json', otherwise you'll get an error. Lastly include the params from earlier in the body. We use JSON.stringify() here to make it work.
fetch('URL', {
method: "POST",
headers: {
'Content-type': 'application/json'
},
body: JSON.stringify(params)
}).then(res => {
console.log(res);
})
At the end you have the option to catch any errors you might receive.
Im trying to update a distribution list by sending a put request, when I run this code and test it in postman by giving it a JSON body I get this error in my node.js terminal stating SyntaxError: Unexpected end of JSON input ... any idea what I should change?
My PUT API request
app.put("/api/Dls/Add/:groupId" , (req, res) => {
const response = {
success: false
};
if (Authorized.myToken) {
response.success = true;
response.data = {};
var options = {
method: 'PUT',
url: 'https://SomeAPI.com/' + req.params.groupId,
headers:
{
Accept: 'application/json',
Authorization: 'Bearer' + ' ' + Authorized.myToken
},
body: JSON.stringify(req.body)
};
request(options, function (error, response, body){
if (error) {
console.log(error);
return;
}
const data = response.body;
const dls = JSON.parse(data)
return res.json(dls);
});
}
});
JSON body I'm passing through postman to test the API call
{
"groupId": "123456789",
"SomeField1": null,
"SomeField2": "xxxxxxxxx",
"SomeField3": true,
"SomeField4": "xxxxxxxxx",
"SomeField5": "xxxxxxxxx",
"SomeField6": [
"xxxxxxxxx"
],
"SomeField7": "xxxxxxxxx",
"SomeField8": "xxxxxxxxx",
"SomeField9": "xxxxxxxxx",
"SomeField10": "xxxxxxxxx",
"SomeField11": [],
"SomeField12": "xxxxxxxxx",
"SomeField13": null,
"SomeField14": false,
"SomeField15": ["xxxxxxxxx"]
}
Any feedback is appreciated!
If the JSON that you posted here is the real one that you pass via postman then, it is not the valid JSON as you have the same name properties. When I say valid it means you get something like this after posting to the endpoint.
{
"groupId": "123456789",
"SomeField": [
"xxxxxxxxx"
]
}
Request npm package is also deprecated so it is better to not use it and replace it with something like Axios. TBH I did not see any error in the code that causes the error that you mentioned, do you have access to the API to check the logs? Maybe something went wrong on the https://SomeAPI.com/ endpoint.
I figured out what the issue was, I needed to add the .end to the return statement
ex. return res.status(200).end()
Currently checking out https://www.npmjs.com/package/swagger-client. The docs are a bit confusing to me.
I intend to hit a URL like www.mysite.com/topic/:topicName
I tried a few things like this:
const authHeaders = {
'X-Api-Key': 'mykey',
Authorization: `Bearer mytoken`,
};
const topic = await client.apis.Topic.getTopic({
headers: authHeaders,
parameters: {
topicName: 'myName'
}
});
I can't seem to figure the right way to send headers and fill in the variable from the swagger docs to form the URL. I'd seen examples where the headers are the first argument so I also had tried
const topic = await client.apis.Topic.getTopic(authHeaders, {
parameters: {
topicName: 'myName'
}
});
When I look at the docs for the word headers, they just talk about setting up the initial client. I figure making it send the auth headers every time is another good solution so I'm kind of looking for both ways (since either can make sense depending on the header).
Using the swagger-client is a little different that a regular http client because it follow exactly your swagger file, you will have to provide the parameters that your swagger spec describes.
for swagger client v3, this format works for me:
Swagger({
url: "www.example.org/swagger.json",
authorization: {
// This must be described in your swagger file, if not, will be ignored.
// See https://swagger.io/docs/specification/authentication/bearer-authentication/
bearerAuth: {type: 'apiKey', 'in': 'header', name: 'Authorization'}
}
}).then(client => {
client.apis.Topic.getTopic({
// The parameters need to be described in the swagger file, or will be ignored.
// Also make sure that the getTopic operation describes that uses the bearerAuth
// Or swagger-client will not send the Auth credentials.
topicName: "myName"
}).then(response => {
// Do magic.
})
});
The swagger portion for your getTopic operation should be similar to this:
{
"/rest/3/topic/{topicName}": {
"tags": ["topic"]
"operationId": "getTopic"
"get": {
"parameters": [
{
"name": "topicName", "in": "path", "required": true, "type": "string"
}
],
"security": { "basicAuth": "global" }
}
}
}