Validate Request Body variables through Swagger and Express - node.js

I am currently using Swagger (2.0) on Node.js. My YAML file validates correctly and the requests are going through. My particular call has a request body using the following format -
{
"postalCode": "invalidpostalcode",
"phone": "invalidnumber",
"website": "invalidwebsite"
}
I would like to validate each body variable before continuing to the next piece of code. To accomplish validating the data I would like to use validator.js.
Now my basic validation code looks something like that -
if(!validator.isURL(req.body.website)){
var tmp = {
"message": req.__('error.url', {
field: req.body.website
})
}
res.status(400).json(tmp);
return;
}
if(!validator.isPostalCode(req.body.postalCode,'any')){
var tmp = {
"message": req.__('error.postalCode', {
field: req.body.postalCode
})
}
res.status(400).json(tmp);
return;
}
Is there there any better way to validate data sent in through the API that would require less code? For example by using a function to control the majority of the logic?
while this is one example of the endpoint I will have some in the future that will require upwards of 20 body parameters.
I have tried create a function that will return the response code. However, that returns an error Cannot set headers after they are sent to the client.

Related

Node.js Soap method params parsed as string instead of related object

I'm using node-soap to consume a WebService. I've used this library and consumed this service many times before, but this time I'm having the following situation.
I create the client using the WSDL that contains the methods, inputs etc:
const soap = require("soap");
const url = "https://servintp.latinoseguros.com.mx:8071/wsCotizadorAutos/cotizador/CotizadorLatino.svc?wsdl";
soap.createClient(url, {}, (error, client) => {
if (error) {
callback(error);
} else {
const describe = client.describe()["CotizadorLatino"]["BasicHttpBinding_ICotizadorLatino"];
console.log(describe["ObtenerMarcas"])
}
});
The request is successful and the client is created, but when I describe the method "ObtenerMarcas" I receive the following object:
{
input: { datos: 'q17:DatosRequeridos' },
output: { ObtenerMarcasResult: 'q18:ListMarca' }
}
Whose only input param shows as only a String, while it should be an object whith different objects and attributes.
When using Soap Client and inputing the exact same WSDL endpoint, the method is described as it should, with all the children and attributes that are expected to be passed:
Soap Client Screenshot
Which makes me believe that this has something to do with the client configuration or probably something very basic that I'm not taking into account.
Can anybody point me on what I'm doing wrong?
Thanks!

Modiy axios request 'data' field into 'body'

I'm trying to create a POST request using axios to a Notification API. So this Notification API have been developed before thus I cannot change anything related to it.
It accepts the request more or less like below.
I need to have the request body in the field called body as shown below. However, axios sends the request body in the field called data rather than body
Expected request
{
"head": {
...
},
"body":{
"publicUserId":"abcd",
"merchantId":"123888",
}
},
}
My request composed automatically by axios:
Axios request
{
"head": {
...
},
"data":{
"publicUserId":"abcd",
"merchantId":"123888",
}
},
}
I did try searching for how to alter the request body field name to body instead of data but I'm pretty sure I haven't found the solution. Maybe if anyone here has some workarounds, I'd be glad to try.
Should any details need to be provided, please tell me. Thank you.

Cannot fetch internet message headers for some emails

I'm using the Microsoft Graph Client for Node.js to fetch email messages. I'm only interested in the headers. The code is working, but recently I got some errors in fetching internetMessageHeaders via the API.
For some messages, the API doesn't return any data for this field (and the code wasn't checking for this, hence the errors).
I tried to manually run the queries using POSTMAN. Using ?$select=internetMessageHeaders as a query param to only fetch the headers. If I remove the query param, I can fetch the message normally (body, etc.).
I haven't been able to find anywhere in the docs why this would happen.
Any ideas on what it's happening?
Edit: Here is the node.js code I am using
const MicrosoftGraphClient = require("#microsoft/microsoft-graph-client").Client
async function fetchEmailMessageHeaders(id, credentials) {
let client = MicrosoftGraphClient.init({
authProvider: callback => callback(null, credentials.access_token)
});
let req = client.api(id).select("internetMessageHeaders");
let message = await req.get();
return message.internetMessageHeaders;
}
Sample output (value of message var):
{
"#odata.context": "https://graph.microsoft.com/v1.0/$metadata#users('156751349d3cc68b')/messages(internetMessageHeaders)/$entity",
"#odata.etag": "W/\"CQAAABYAAABcr9US8aH2RIGaOGQZwDg3AAKyfdpk\"",
"id": "AQMkADAwATM0MDAAMS1hZWIxLThjZmYALTAwAi0wMAoARgAAA3wcQrEUgfhHoZ0BD2jmyXYHAFyv1RLxofZEgZo4ZBnAODcAAAIBDAAAAFyv1RLxofZEgZo4ZBnAODcAArJaPEcAAAA=",
"internetMessageHeaders": [
{
"name": "Received",
"value": "from BY2NAM01HT225.eop-nam01.prod.protection.outlook.com (2603:10a6:803:118::39) by VI1PR0301MB2221.eurprd03.prod.outlook.com with HTTPS via VE1PR03CA0050.EURPRD03.PROD.OUTLOOK.COM; Wed, 10 Apr 2019 11:41:55 +0000"
}
...
]
}
The problem is that for some emails, the message does not contain internetMessageHeaders.
I am using an inbox subscription to receive events for new email messages from Outlook. When an event is received I use the API to retrieve the message and extract headers from it.
API reference here
Edit2:
Here is an example JSON output of an event that fails to also retrieve headers:
{
"#odata.context": "https://graph.microsoft.com/v1.0/$metadata#users('53e07bf4-bb6a-4a82-a724-37dadfb1cf11')/messages(internetMessageHeaders)/$entity",
"#odata.etag": "W/\"CQAAABQAAADdeU+v2VzbRpZMSJGral7kAAXJkA==\"",
"id": "AAMkADhmMmVmM2NjLWFhNGMtNDBlYy04NzBkLTg5MmU2OWI0ODU4MgBGAAAAAAALg6E-e6CxRLEbZfrhFaDBBwAzAAMgKF1iTp242t34rFy5AAAAAAAOAAB5l_O62bUUTqTLk6KYrl4sAAGrJcjfAAA="
}
It seems internetMessageHeaders are not set when an email is replied to using outlook.office365.com. I'm also not able to see message headers when inspecting the message using Outlook on Mac.

Node.js - Why does my HTTP GET Request return a 404 when I know the data is there # the URL I am using

I'm still new enough with Node that HTTP requests trip me up. I have checked all the answers to similar questions but none seem to address my issue.
I have been dealt a hand in the Wild of having to go after JSON files in an API. I then parse those JSON files to separate them out into rows that populate a SQL database. The API has one JSON file with an ID of 'keys.json' that looks like this:
{
"keys":["5sM5YLnnNMN_1540338527220.json","5sM5YLnnNMN_1540389571029.json","6tN6ZMooONO_1540389269289.json"]
}
Each array element in the keys property holds the value of one of the JSON data files in the API.
I am having problems getting either type of file returned to me, but I figure if I can learn what is wrong with the way I am trying to get 'keys.json', I can leverage that knowledge to get the individual JSON data files represented in the keys array.
I am using the npm modules 'request' and 'request-promise-native' as follows:
const request = require('request');
const rp = require('request-promise-native');
My URL is constructed with the following elements, as follows (I have used the ... to keep my client anonymous, but other than that it is a direct copy:
let baseURL = 'http://localhost:3000/Users/doug5solas/sandbox/.../server/.quizzes/'; // this is the development value only
let keysID = 'keys.json';
Clearly the localhost aspect will have to go away when we deploy but I am just testing now.
Here is my HTTP call:
let options = {
method: 'GET',
uri: baseURL + keysID,
headers: {
'User-Agent': 'Request-Promise'
},
json: true // Automatically parses the JSON string in the response
};
rp(options)
.then(function (res) {
jsonKeysList = res.keys;
console.log('Fetched', jsonKeysList);
})
.catch(function (err) {
// API call failed
let errMessage = err.options.uri + ' ' + err.statusCode + ' Not Found';
console.log(errMessage);
return errMessage;
});
Here is my console output:
http://localhost:3000/Users/doug5solas/sandbox/.../server/.quizzes/keys.json 404 Not Found
It is clear to me that the .catch() clause is being taken and not the .then() clause. But I do not know why that is because the data is there at that spot. I know it is because I placed it there manually.
Thanks to #Kevin B for the tip regarding serving of static files. I revamped the logic using express.static and served the file using that capability and everything worked as expected.

Shopify. Problems updating Metafields with shopify-node-api

I'm having difficulty in updating an existing metafield with Shopify API. Each time I receive an error, advising me that the variant already exists... so it must be thinking I'm trying to create a new one (and not update).
I thought this may be an issue with 'put' and 'post' - so changed my method to put, however the error persists. I've hardwired in all my variables to make it easier to test.
I'm working with Cloudinary. I'm using https://github.com/sinechris/shopify-node-api with Express.js
app.post('/upload', function(req, res){
// upload page... assume we have uploaded our image - but have hard-wired a local file in for now
cloudinary.uploader.upload('/Users/Rob/Pictures/testimg.jpg', function(savedImg) {
var imageURL = savedImg.url;
console.log(imageURL)
},
{
public_id: "testimg"
});
// the saved image is returned - so we add it to our updateMetafieldData json object
var updateMetafieldData = {
"variant": {
"id": '253818949',
"metafields": [
{
"key": "variant_image_0",
"value": 'testimg', // whatever the public id of our image is.
"value_type": "string",
"namespace": "variant_image"
}
]
}
}
// and post the result to shopify - then redirect to /getvariants
Shopify.put('/admin/variants/253818949.json', updateMetafieldData, function(data){
// res.redirect('/getvariants')
});
});
I actually created Shopify Node API and was just now happened upon this months later but thought I'd answer for anyone else coming along.
Take a look at the shopify API here: https://docs.shopify.com/api/metafield#update
You can update the metafield directly by performing a PUT request against the metafield resource instead of the variant like so:
/admin/metafields/#{id}.json
You would of course need to know the ID of the metafield first so that would require a call to the variant first or you could simply store the id in your local database for reference.

Resources