How to set HTTP headers win axios.interceptors? - axios

I copied the following code from Amazon Cognito Vuex Module examples to my Vue.js app:
axios.interceptors.request.use(async config => {
const response = await store.dispatch('getUserSession');
if (response && response.accessToken && response.accessToken.jwtToken) {
config.headers.awsToken = response.accessToken.jwtToken;
}
return config;
});
and expected to see in the request headers something like
awsToken: AzWDF....
, but actually I am getting:
Why 'awstoken' goes to 'Access-Control-Request-Headers' and why it does not have a value?
I also tried
config.headers.common['awsToken'] = response.accessToken.jwtToken;
but with the same result.
It is not a problem of AWS, because response.accessToken.jwtToken has a valid non-empty value.
EDIT1: and even this example does not work in my app and gives the same result:
axios.interceptors.request.use(config => {
config.headers['Authorization'] = 'Bearer XYZ';
return Promise.resolve(config);
},
(error) => {
return Promise.reject(error);
});
EDIT2: I found similar post.

Related

Cannot read property 'Authorization' of undefined with Nuxt Auth & Axios

I have been using nuxt/auth-next and axios modules with nuxt project since last 3-4 months, everything was working fine since yesterday but now whenever I try to send axios request to public APIs without passing Authorization in headers, I get this error
Cannot read property 'Authorization' of undefined with Nuxt Auth & Axios
Attached is a screenshot of the page
below is my code in index.js store file
export const actions = {
async nuxtServerInit({ commit }, context) {
// Public profile
if (context.route.params && context.route.params.subdomain) {
context.$axios.onRequest((config) => {
config.progress = false
})
let { data } = await context.$axios.get(
`users/get_user_data_using_subdomain/${context.route.params.subdomain}`,
{
headers: {
'Content-Type': 'multipart/form-data',
},
}
)
await context.store.dispatch('artists/setPublicProfile', data.user_data)
}
},
}
This happend to me to when I was using context.app.$axios instead of context.$axios within a injection
Nuxt server is looking for config.headers.common.Authorization.
The example below is a quick win for you:
let { data } = await context.$axios.get(
`users/get_user_data_using_subdomain/${context.route.params.subdomain}`,
{
headers: {
common: null, // or something like this: context.$axios.defaults.headers?.common
'Content-Type': 'multipart/form-data',
},
}
)

Unable to get Moxios stubRequest to work

I'm having issues getting stubRequest to work properly. Here's my code:
it('should stub my request', (done) => {
moxios.stubRequest('/authenticate', {
status: 200
})
//here a call to /authenticate is being made
SessionService.login('foo', 'bar')
moxios.wait(() => {
expect(something).toHaveHappened()
done()
})
})
This works fine:
it('should stub my request', (done) => {
SessionService.login('foo', 'bar')
moxios.wait(async () => {
let request = moxios.requests.mostRecent()
await request.respondWith({
status: 200
})
expect(something).toHaveHappened()
done()
})
})
The second method just get's the last call though, and I'd really like to be able to explicitely stub certain requests.
I'm running Jest with Vue.
I landed here with a similar goal and eventually solved it using a different approach that may be helpful to others:
moxios.requests has a method .get() (source code) that lets you grab a specific request from moxios.requests based on the url. This way, if you have multiple requests, your tests don't require the requests to occur in a specific order to work.
Here's what it looks like:
moxios.wait(() => {
// Grab a specific API request based on the URL
const request = moxios.requests.get('get', 'endpoint/to/stub');
// Stub the response with whatever you would like
request.respondWith(yourStubbedResponseHere)
.then(() => {
// Your assertions go here
done();
});
});
NOTE:
The name of the method .get() is a bit misleading. It can handle different types of HTTP requests. The type is passed as the first parameter like: moxios.requests.get(requestType, url)
it would be nice if you show us the service. Service call must be inside the moxios wait func and outside must be the axios call alone. I have pasted a simplified with stubRequest
describe('Fetch a product action', () => {
let onFulfilled;
let onRejected;
beforeEach(() => {
moxios.install();
store = mockStore({});
onFulfilled = sinon.spy();
onRejected = sinon.spy();
});
afterEach(() => {
moxios.uninstall();
});
it('can fetch the product successfully', done => {
const API_URL = `http://localhost:3000/products/`;
moxios.stubRequest(API_URL, {
status: 200,
response: mockDataSingleProduct
});
axios.get(API_URL, mockDataSingleProduct).then(onFulfilled);
const expectedActions = [
{
type: ACTION.FETCH_PRODUCT,
payload: mockDataSingleProduct
}
];
moxios.wait(function() {
const response = onFulfilled.getCall(0).args[0];
expect(onFulfilled.calledOnce).toBe(true);
expect(response.status).toBe(200);
expect(response.data).toEqual(mockDataSingleProduct);
return store.dispatch(fetchProduct(mockDataSingleProduct.id))
.then(() => {
var actions = store.getActions();
expect(actions.length).toBe(1);
expect(actions[0].type).toBe(ACTION.FETCH_PRODUCT);
expect(actions[0].payload).not.toBe(null || undefined);
expect(actions[0].payload).toEqual(mockDataSingleProduct);
expect(actions).toEqual(expectedActions);
done();
});
});
});
})

facebook messenger bot encoding error

I have written sample echo message bot using facebook messenger api and wit.ai actions.
My message from facebook page is received and the proper action function defined using wit api's is also getting called. However
while returning the response, i am getting followin error as -
Oops! An error occurred while forwarding the response to : Error: (#100) Param message[text] must be a UTF-8 encoded string
at fetch.then.then.json (/app/index.js:106:13)
at process._tickCallback (internal/process/next_tick.js:103:7)
Here is the function which is used to return the response -
const fbMessage = (id, text) => {
const body = JSON.stringify({
recipient: { id },
message: { text },
});
const qs = 'access_token=' + encodeURIComponent(FB_PAGE_ACCESS_TOKEN);
return fetch('https://graph.facebook.com/v2.6/me/messages?' + qs, {
method: 'POST',
headers: {'Content-Type': 'application/json; charset=UTF-8'},
body
})
.then(rsp => rsp.json())
.then(json => {
if (json.error && json.error.message) {
throw new Error(json.error.message);`enter code here`
}
return json;
});
};
I have copied this function from the messenger.js file from the documentation since i am just trying the POC.
I checked the values for text and id in this function and verified using console.log statements and those are coming properly.
Can some experts help me to solve this error?
Note - I tried encoding the text using text.toString("utf8"); but it returns the encoding string as [object object] and thats the
response i get from bot. so it doesnt work.
Get the latest code from node-wit, there is a change in facebook id usage,
According to Facebook:
On Tue May 17 format of user and page ids delivered via webhooks will
change from an int to a string to better support default json encoder
in js (that trims long ints). Please make sure your app works with
string ids returned from webhooks as well as with ints.
Still you are getting issue with the api try to add if(event.message && !event.message.is_echo) condition as shown in below code.
// Message handler
app.post('/webhook', (req, res) => {
const data = req.body;
if (data.object === 'page') {
data.entry.forEach(entry => {
entry.messaging.forEach(event => {
if (event.message && !event.message.is_echo) {
const sender = event.sender.id;
const sessionId = findOrCreateSession(sender);
const {text, attachments} = event.message;
if (attachments) {
fbMessage(sender, 'Sorry I can only process text messages for now.')
.catch(console.error);
} else if (text) {
wit.runActions(
sessionId, // the user's current session
text, // the user's message
sessions[sessionId].context // the user's current session state
).then((context) => {
console.log('Waiting for next user messages');
sessions[sessionId].context = context;
})
.catch((err) => {
console.error('Oops! Got an error from Wit: ', err.stack || err);
})
}
} else {
console.log('received event', JSON.stringify(event));
}
});
});
}
res.sendStatus(200);
});
Reference:
no matching user bug
no matching user fix

AngularJS ngResrouce REST Authentication

I'm trying to learn AngularJS. I'm try to make a simple authenticated get request to a REST api. At this point, i'm just trying to get a response back. I keep getting invalid key because I can't seem to send the headers properly.
angular.module('App', ['ngResource']);
function AppCtrl($scope, $resource){
$scope.app = $resource('https://theapiurl.com/parameter=:action',
{action:'My Parameter works fine!'},
{method: 'GET'},
{headers: 'auth-key' : 'key'});
$scope.app.get();
}
I just can't seem to get the header to send. Thanks for reading.
If you are using angular-resource 1.1.x+ the following should work:
angular.module('App', ['ngResource']);
function AppCtrl($scope, $resource){
$scope.app = $resource('https://theapiurl.com/parameter=:action',
{
action:'My Parameter works fine!'
},
{
get: {
method: 'GET',
headers : { 'auth-key' : 'key' }
}
});
$scope.app.get();
}
If you are using 1.0.x branch this won't work. I believe the only alternative is to set global default headers in $httpProvider, or to user $http directly (not using $resource). Here's how you would set the headers globally:
$httpProvider.defaults.headers.get['auth-key'] = 'key';
To avoid setting the header in every resource you could use an interceptor:
app.config(function($httpProvider) {
$httpProvider.interceptors.push(function($q) {
return {
'request': function(config) {
config.headers['auth-key'] = 'key';
return $q.when(config);
}
};
});
});

How to make remote REST call inside Node.js? any CURL?

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);
}