I have created a utility function which is supposed to be common for all the api requests in node.js express app.
function axiosCall(method, endpoint, body) {
let requestConfig = {
url: encodeURI(`${endpoint.host}:${endpoint.port}${endpoint.path}`),
method: method, //can be POST, GET, etc
proxy: false,
data: body,
headers: {
"x-access-token": token,
"X-Correlation-ID": correlationId,
"Content-Type": "application/json"
},
}
axios.request(requestConfig).then(response => {
return response.data;
}).catch((errorRes) => {
throw {
error: errorRes.message, status: errorRes?.response?.status || 500,
responseContent: errorRes?.response?.data || "Server Error"
};
})
}
it works fine for JSON responses, but does not give proper result for files, such as pdf.
the response which i got for a pdf file was like
{
"status": 200,
"statusText": "OK",
"headers": {
"server": "nginx/1.16.1",
"date": "Fri, 02 Sep 2022 07:39:44 GMT",
"content-type": "application/pdf",
"content-length": "47658",
"connection": "close",
},
"config": {...},
"request": {...},
"data": "%PDF-1.4\r\n%����\r\n1 0 obj\r\n<<\r\n/Type /Catalog\r\n/Pages 2 0 R\r\n/AcroForm 3 0 R\r\n>>\r\nendobj\r\n4 0 obj\r\n<<\r\n/�����M��0\u0010��B�C������\u0016�#?���`��\u0003�N���\u0012���~�L��\u001e| O2�y3���;�fP�o�\u0013\u000e�Ҹ�c��}����E�VuS\r�W��Vv�h�>=�\u0001oGwi�j�⯰�\u000f����=�,��5��]��g{�ŧ{���\rݠ\u0012\u0000U�%��Vv��\rUL5�c\u001d���1\u000f\u0015�'�\u001f\u001d*M��jk컲B_�+N�U�$\u0019\u0004�-L\"t��\u0001�s���Z��\t�*MA����\u0005a���h�4O�\u0006�)H�9\bm�j\u0001BkX-Ah-+��i�wm#h\u0017�� �KV{\u0010�\r�\u0003\b햔I#hw��a�嶍\u0006�=��#Xp^��c\u0016ܣ1 ,4+N�Xp^!#a���X�\u0005�c8Ob�Il薑:IC�᭟oJ�\u001e�3����އy�\t�A\u001aG�q(C�X��7��\u0000�t��\r\nendstream\r\nendobj\r\n26 0 obj\r\n<<\r\n/Type /Font\r\n/Subtype /CIDFontType2\r\n/BaseFont /GBMOJY+SymbolMT\r\n/CIDToGIDMap /Identity\r\n/DW 1000\r\n/FontDescriptor 31 0 R\r\n/CIDSystemInfo <<\r\n/Registry (Adobe)\r\n/Ordering (Identity)\r\n/Supplement 0\r\n>>\r\n\r\n/W [120 [459]]\r\n>>\r\nendobj\r\n27 0 obj\r\n<<\r\n/Filter /FlateDecode\r\n/Length 225\r\n>>\r\nstream\r\nx^m�ϊ�0\u0010��\u001c� �^�P\n�\"����\u0000i2-��$L�C�~�T\u0014\u0016\u000f\u0019\u0018~�\r_F��sE6��a�k\f�Z2��\u001bY#4�Y\u0012�\u001d\u0018�\u0003,]��W>\u00133]OC����AQ���t\b<��ø\u0006��\r17~��0CM`\u001f��+��W�la��B��6\u000f��6l�$�֥�n��J�K���S[~ݤ�\u0003�5�]}ր����TV���ճG��Di���xQa� ?�K��\r�����ސmT�}q��Ԙ��\u0019�֕�\u0018c�\u0001�\u001a|/}!��qfJў<y��\u0007c��y\t\u001c\b ks]v]Fmz弦o\u0019����u�v_�|�[_F>�G�w�m:n��.�m$�ZҨ�F-i�\u0014〯�o\u001c�\u00120fJ\u0012`��Oz��{rP�v\u0011\u0004�}�����\u001d�\u0016�L\\�\u000b�\u001d�n�C]�I�����MZ�~۷��Iu��\u0014�6o�?�����W��ꡦ#?ZXG��wL�\u0007���G\t���3�Y���DFl�����R� 34\r\n>>\r\n\r\nstartxref\r\n46886\r\n%%EOF\r\n"
}
I am unable to convert this response.data to pdf file.
Then i read about setting responseType: "arraybuffer", which gave the buffer[] and I can use it in code to generate the file. but on setting the responseType, the error was also of buffer type instead of json. which again required further processing to convert it to json format.
so, is there a way to get pdf file from axios, by converting the response.data, which I received with default responseType.
or can we set responseType dynamically after getting response from the server, as i get the content-type in headers. so as to make a utility function which can work with all kinds of responses.
As I didn't get a proper resolution i handled it manually by passing a flag to the axios utility function.
const customObjectify = (data) => {
try {
if(typeof data === "string"){
JSON.parse(data);
}
return data;
} catch (error) {
return data;
}
}
main block is below
//adding a default value false to parameter, so i don't need to change at all function calls.
function axiosCall(method, endpoint, body, isFileInResponse= false) {
let requestConfig = {
url: encodeURI(`${endpoint.host}:${endpoint.port}${endpoint.path}`),
method: method, //can be POST, GET, etc
proxy: false,
data: body,
headers: {
"x-access-token": token,
"X-Correlation-ID": correlationId,
"Content-Type": "application/json"
},
}
if(isFileInResponse){
requestConfig.responseType = "arraybuffer";
}
axios.request(requestConfig).then(response => {
return response.data;
}).catch((errorRes) => {
try {
let responseContent;
if(isFileInResponse) {
// arraybuffer error needs to be converted to json
responseContent = customObjectify(errorRes.response.data.toString());
} else {
responseContent = errorRes.response.data;
}
throw ({ error: errorRes.message, status: errorRes?.response?.status || 500, responseContent});
} catch (error) {
throw ({ error: errorRes.message, status: errorRes?.response?.status || 500, responseContent: "Server Error" });
}
throw {
error: errorRes.message, status: errorRes?.response?.status || 500,
responseContent: errorRes?.response?.data || "Server Error"
};
})
}
As mentioned in this question (https://stackoverflow.com/a/53230807/19179818) you could put code in your .then() to create an anchor tag on your page and click it automatically to download the file, and delete the tag afterwards. (posted as awnser instead of comment because of not enough reputation)
I am working with Office 365. I have used REST API for different types of operations. I can easily find list items in a folder in document library because they are files. I want the list items in a folder in custom list. For this I am not able to find any REST API. Can you please provide me any REST API which will be able to retrieve list items from folder in custom list ?
I got the answer. Following is the way
var camlQuery = {
'query': {
'__metadata': { 'type': 'SP.CamlQuery' },
'ViewXml': '<View><Query/></View>',
'FolderServerRelativeUrl': '/sites/EdvelopTest3/Lists/QuestionsList/test/test1'
}
};
var url = OEPContext.appWebUrl + "/_api/SP.AppContextSite(#target)/web/lists/getByTitle('OEPLMSQuestions')/getitems?$select=ID,Title&#target='" + OEPContext.hostWebUrl + "'";
jQuery.ajax({
async: false,
url: url,
type: "POST",
headers: {
"accept": "application/json;odata=verbose",
"content-type": "application/json;odata=verbose",
"X-RequestDigest": $("#__REQUESTDIGEST").val()
},
data: JSON.stringify(camlQuery),
success: function (data) {
var result = "success";
},
error: function (data, msg) {
var result = "Fail";
}
});
I am trying to modify the http status code of create.
POST /api/users
{
"lastname": "wqe",
"firstname": "qwe",
}
Returns 200 instead of 201
I can do something like that for errors:
var err = new Error();
err.statusCode = 406;
return callback(err, info);
But I can't find how to change status code for create.
I found the create method:
MySQL.prototype.create = function (model, data, callback) {
var fields = this.toFields(model, data);
var sql = 'INSERT INTO ' + this.tableEscaped(model);
if (fields) {
sql += ' SET ' + fields;
} else {
sql += ' VALUES ()';
}
this.query(sql, function (err, info) {
callback(err, info && info.insertId);
});
};
In your call to remoteMethod you can add a function to the response directly. This is accomplished with the rest.after option:
function responseStatus(status) {
return function(context, callback) {
var result = context.result;
if(testResult(result)) { // testResult is some method for checking that you have the correct return data
context.res.statusCode = status;
}
return callback();
}
}
MyModel.remoteMethod('create', {
description: 'Create a new object and persist it into the data source',
accepts: {arg: 'data', type: 'object', description: 'Model instance data', http: {source: 'body'}},
returns: {arg: 'data', type: mname, root: true},
http: {verb: 'post', path: '/'},
rest: {after: responseStatus(201) }
});
Note: It appears that strongloop will force a 204 "No Content" if the context.result value is falsey. To get around this I simply pass back an empty object {} with my desired status code.
You can specify a default success response code for a remote method in the http parameter.
MyModel.remoteMethod(
'create',
{
http: {path: '/', verb: 'post', status: 201},
...
}
);
For loopback verion 2 and 3+: you can also use afterRemote hook to modify the response:
module.exports = function(MyModel) {
MyModel.afterRemote('create', function(
context,
remoteMethodOutput,
next
) {
context.res.statusCode = 201;
next();
});
};
This way, you don't have to modify or touch original method or its signature. You can also customize the output along with the status code from this hook.
I have resource that has following fields:
description, picture
Is it possible to send that resource to URL as multipart/form, and if so, how?
I've tried putting:
app.factory('resource_name', ['$resource', function($resource) {
return $resource('<url> ',
{
<params_for_url>
},
save: {
method: "POST",
headers: {
"Content-Type": "multipart/form-data;"
}
},
but this doesn't get to the server as form-data. It goes like JSON with header just set:
{
description: "gtrdgf",
picture: {
lastModifiedDate:2013-11-26T20:42:13.000Z,
name: "suggested_pokes.png"
size: 32995
type: "image/png"
webkitRelativePath: ""
}
Did anyone met this requirement before? If this is possible at all...
Thanks!
I found solution for this one. You have to use FormData to submit it. You can use it as interceptor. I used it like this (this is my save method of ngResource)
save: {
method: 'POST',
transformRequest: formDataObject,
headers: {'Content-Type':undefined, enctype:'multipart/form-data'}
},
and here is transformer:
function formDataObject (data) {
var fd = new FormData();
angular.forEach(data, function(value, key) {
fd.append(key, value);
});
return fd;
}
In Node.js, other than using child process to make CURL call, is there a way to make CURL call to remote server REST API and get the return data?
I also need to set up the request header to the remote REST call, and also query string as well in GET (or POST).
I find this one: http://blog.nodejitsu.com/jsdom-jquery-in-5-lines-on-nodejs
but it doesn't show any way to POST query string.
Look at http.request
var options = {
host: url,
port: 80,
path: '/resource?id=foo&bar=baz',
method: 'POST'
};
http.request(options, function(res) {
console.log('STATUS: ' + res.statusCode);
console.log('HEADERS: ' + JSON.stringify(res.headers));
res.setEncoding('utf8');
res.on('data', function (chunk) {
console.log('BODY: ' + chunk);
});
}).end();
How about using Request — Simplified HTTP client.
Edit February 2020: Request has been deprecated so you probably shouldn't use it any more.
Here's a GET:
var request = require('request');
request('http://www.google.com', function (error, response, body) {
if (!error && response.statusCode === 200) {
console.log(body) // Print the google web page.
}
})
OP also wanted a POST:
request.post('http://service.com/upload', {form:{key:'value'}})
I use node-fetch because it uses the familiar (if you are a web developer) fetch() API. fetch() is the new way to make arbitrary HTTP requests from the browser.
Yes I know this is a node js question, but don't we want to reduce the number of API's developers have to memorize and understand, and improve re-useability of our javascript code? Fetch is a standard so how about we converge on that?
The other nice thing about fetch() is that it returns a javascript Promise, so you can write async code like this:
let fetch = require('node-fetch');
fetch('http://localhost', {
method: 'POST',
headers: {'Content-Type': 'application/json'},
body: '{}'
}).then(response => {
return response.json();
}).catch(err => {console.log(err);});
Fetch superseeds XMLHTTPRequest. Here's some more info.
Look at http://isolasoftware.it/2012/05/28/call-rest-api-with-node-js/
var https = require('https');
/**
* HOW TO Make an HTTP Call - GET
*/
// options for GET
var optionsget = {
host : 'graph.facebook.com', // here only the domain name
// (no http/https !)
port : 443,
path : '/youscada', // the rest of the url with parameters if needed
method : 'GET' // do GET
};
console.info('Options prepared:');
console.info(optionsget);
console.info('Do the GET call');
// do the GET request
var reqGet = https.request(optionsget, function(res) {
console.log("statusCode: ", res.statusCode);
// uncomment it for header details
// console.log("headers: ", res.headers);
res.on('data', function(d) {
console.info('GET result:\n');
process.stdout.write(d);
console.info('\n\nCall completed');
});
});
reqGet.end();
reqGet.on('error', function(e) {
console.error(e);
});
/**
* HOW TO Make an HTTP Call - POST
*/
// do a POST request
// create the JSON object
jsonObject = JSON.stringify({
"message" : "The web of things is approaching, let do some tests to be ready!",
"name" : "Test message posted with node.js",
"caption" : "Some tests with node.js",
"link" : "http://www.youscada.com",
"description" : "this is a description",
"picture" : "http://youscada.com/wp-content/uploads/2012/05/logo2.png",
"actions" : [ {
"name" : "youSCADA",
"link" : "http://www.youscada.com"
} ]
});
// prepare the header
var postheaders = {
'Content-Type' : 'application/json',
'Content-Length' : Buffer.byteLength(jsonObject, 'utf8')
};
// the post options
var optionspost = {
host : 'graph.facebook.com',
port : 443,
path : '/youscada/feed?access_token=your_api_key',
method : 'POST',
headers : postheaders
};
console.info('Options prepared:');
console.info(optionspost);
console.info('Do the POST call');
// do the POST call
var reqPost = https.request(optionspost, function(res) {
console.log("statusCode: ", res.statusCode);
// uncomment it for header details
// console.log("headers: ", res.headers);
res.on('data', function(d) {
console.info('POST result:\n');
process.stdout.write(d);
console.info('\n\nPOST completed');
});
});
// write the json data
reqPost.write(jsonObject);
reqPost.end();
reqPost.on('error', function(e) {
console.error(e);
});
/**
* Get Message - GET
*/
// options for GET
var optionsgetmsg = {
host : 'graph.facebook.com', // here only the domain name
// (no http/https !)
port : 443,
path : '/youscada/feed?access_token=you_api_key', // the rest of the url with parameters if needed
method : 'GET' // do GET
};
console.info('Options prepared:');
console.info(optionsgetmsg);
console.info('Do the GET call');
// do the GET request
var reqGet = https.request(optionsgetmsg, function(res) {
console.log("statusCode: ", res.statusCode);
// uncomment it for header details
// console.log("headers: ", res.headers);
res.on('data', function(d) {
console.info('GET result after POST:\n');
process.stdout.write(d);
console.info('\n\nCall completed');
});
});
reqGet.end();
reqGet.on('error', function(e) {
console.error(e);
});
Axios
An example (axios_example.js) using Axios in Node.js:
const axios = require('axios');
const express = require('express');
const app = express();
const port = process.env.PORT || 5000;
app.get('/search', function(req, res) {
let query = req.query.queryStr;
let url = `https://your.service.org?query=${query}`;
axios({
method:'get',
url,
auth: {
username: 'the_username',
password: 'the_password'
}
})
.then(function (response) {
res.send(JSON.stringify(response.data));
})
.catch(function (error) {
console.log(error);
});
});
var server = app.listen(port);
Be sure in your project directory you do:
npm init
npm install express
npm install axios
node axios_example.js
You can then test the Node.js REST API using your browser at: http://localhost:5000/search?queryStr=xxxxxxxxx
Similarly you can do post, such as:
axios({
method: 'post',
url: 'https://your.service.org/user/12345',
data: {
firstName: 'Fred',
lastName: 'Flintstone'
}
});
SuperAgent
Similarly you can use SuperAgent.
superagent.get('https://your.service.org?query=xxxx')
.end((err, response) => {
if (err) { return console.log(err); }
res.send(JSON.stringify(response.body));
});
And if you want to do basic authentication:
superagent.get('https://your.service.org?query=xxxx')
.auth('the_username', 'the_password')
.end((err, response) => {
if (err) { return console.log(err); }
res.send(JSON.stringify(response.body));
});
Ref:
https://github.com/axios/axios
https://www.twilio.com/blog/2017/08/http-requests-in-node-js.html
I have been using restler for making webservices call, works like charm and is pretty neat.
To use latest Async/Await features
https://www.npmjs.com/package/request-promise-native
npm install --save request
npm install --save request-promise-native
//code
async function getData (){
try{
var rp = require ('request-promise-native');
var options = {
uri:'https://reqres.in/api/users/2',
json:true
};
var response = await rp(options);
return response;
}catch(error){
throw error;
}
}
try{
console.log(getData());
}catch(error){
console.log(error);
}
Warning: As of Feb 11th 2020, request is fully deprecated.
One another example - you need to install request module for that
var request = require('request');
function get_trustyou(trust_you_id, callback) {
var options = {
uri : 'https://api.trustyou.com/hotels/'+trust_you_id+'/seal.json',
method : 'GET'
};
var res = '';
request(options, function (error, response, body) {
if (!error && response.statusCode == 200) {
res = body;
}
else {
res = 'Not Found';
}
callback(res);
});
}
get_trustyou("674fa44c-1fbd-4275-aa72-a20f262372cd", function(resp){
console.log(resp);
});
const http = require('http');
const url = process.argv[2];
http.get(url, function(response) {
let finalData = "";
response.on("data", function (data) {
finalData += data.toString();
});
response.on("end", function() {
console.log(finalData.length);
console.log(finalData.toString());
});
});
I didn't find any with cURL so I wrote a wrapper around node-libcurl and can be found at https://www.npmjs.com/package/vps-rest-client.
To make a POST is like so:
var host = 'https://api.budgetvm.com/v2/dns/record';
var key = 'some___key';
var domain_id = 'some___id';
var rest = require('vps-rest-client');
var client = rest.createClient(key, {
verbose: false
});
var post = {
domain: domain_id,
record: 'test.example.net',
type: 'A',
content: '111.111.111.111'
};
client.post(host, post).then(function(resp) {
console.info(resp);
if (resp.success === true) {
// some action
}
client.close();
}).catch((err) => console.info(err));
If you have Node.js 4.4+, take a look at reqclient, it allows you to make calls and log the requests in cURL style, so you can easily check and reproduce the calls outside the application.
Returns Promise objects instead of pass simple callbacks, so you can handle the result in a more "fashion" way, chain the result easily, and handle errors in a standard way. Also removes a lot of boilerplate configurations on each request: base URL, time out, content type format, default headers, parameters and query binding in the URL, and basic cache features.
This is an example of how to initialize it, make a call and log the operation with curl style:
var RequestClient = require("reqclient").RequestClient;
var client = new RequestClient({
baseUrl:"http://baseurl.com/api/", debugRequest:true, debugResponse:true});
client.post("client/orders", {"client": 1234, "ref_id": "A987"},{"x-token": "AFF01XX"});
This will log in the console...
[Requesting client/orders]-> -X POST http://baseurl.com/api/client/orders -d '{"client": 1234, "ref_id": "A987"}' -H '{"x-token": "AFF01XX"}' -H Content-Type:application/json
And when the response is returned ...
[Response client/orders]<- Status 200 - {"orderId": 1320934}
This is an example of how to handle the response with the promise object:
client.get("reports/clients")
.then(function(response) {
// Do something with the result
}).catch(console.error); // In case of error ...
Of course, it can be installed with: npm install reqclient.
You can use curlrequest to easily set what time of request you want to do... you can even set headers in the options to "fake" a browser call.
Warning: As of Feb 11th 2020, request is fully deprecated.
If you implement with form-data, for more info (https://tanaikech.github.io/2017/07/27/multipart-post-request-using-node.js):
var fs = require('fs');
var request = require('request');
request.post({
url: 'https://slack.com/api/files.upload',
formData: {
file: fs.createReadStream('sample.zip'),
token: '### access token ###',
filetype: 'zip',
filename: 'samplefilename',
channels: 'sample',
title: 'sampletitle',
},
}, function (error, response, body) {
console.log(body);
});
I found superagent to be really useful,
it is very simple
for example
const superagent=require('superagent')
superagent
.get('google.com')
.set('Authorization','Authorization object')
.set('Accept','application/json')
Update from 2022:
from node.js version v18 on you can use the globally available fetch API (see https://nodejs.org/en/blog/announcements/v18-release-announce/)
There is also an example usage included on their announcement page:
const res = await fetch('https://nodejs.org/api/documentation.json');
if (res.ok) {
const data = await res.json();
console.log(data);
}