Using NestJS, Axios returns an Observable<AxiosResponse>.
How can I get the headers of a GET- or HEAD-Request?
Lets say I make a HEAD-request:
import { HttpService } from '#nestjs/axios';
const observable = this.httpService.head(uri);
How can I get the headers from the result?
Update:
I found a nice workaround that just works with a single line of code.
There is another library called https with is more powerful:
import http from "https";
await http.request(uri, { method: 'HEAD' }, (res) => {
console.log(res.headers);
}).on('error', (err) => {
console.error(err);
}).end();
The headers of the response are available in the subscribe callback with the headers property.
this.httpService.head(uri).subscribe(res => {
console.log(res.headers)
});
Playground
According to https://github.com/axios/axios#request-config:
For request headers you should use something like this:
this.httpService.axiosRef.interceptors.request.use(function (config) {
// Do something before request is sent
console.log(config);
return config;
}, function (error) {
// Do something with request error
return Promise.reject(error);
});
You should use it onModuleInit (to prevent working a few interceptors in a time)
Also you can make own module like in this answer: https://stackoverflow.com/a/72543771/4546382
For the response headers you can just use response.headers
Related
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',
},
}
)
Basically, my question is the exact one here https://github.com/axios/axios/issues/583. It can be done via throw new axios.Cancel('Operation canceled by the user.');.. But how can I do this in nuxt axios module?? I can not see it in the document and I tried $axios.Cancel('Error') but returned $axios.Cancel is not a constructor
Basically, the something like the snippet below is what I am looking for:
axios.interceptors.response.use(function (response) {
throw new axios.Cancel('Operation canceled by the user.');
}, function (error) {
return Promise.reject(error);
});
Emphasis on throw new axios.Cancel
While #nuxtjs/axios does not expose axios.Cancel, you could still import axios directly to get that symbol. Note axios is already a dependency of #nuxtjs/axios, so no extra dependency necessary.
Example (tested with #nuxtjs/axios v5.11.0):
// plugins/axios.js
import { Cancel } from 'axios'
export default function ({ $axios }) {
$axios.onResponse((response) => {
if (response.code !== 200){
throw new Cancel(response.msg)
}
})
}
With nuxt/axios v5.8.0 IsCancel available
v5.8.0 add CancelToken and isCancel to axios instance
Seems like nuxt-axios does not have any exact equivalent but I found a work around.
plugins/axios.js
export default function({ $axios, req, store, redirect, app }, inject) {
// const source = $axios.CancelToken.source()
const timeout = process.env.API_TIMEOUT || 10000
const errorHandling = function(error) {
console.log(`API ${error}`)
return new Promise(() => {})
}
$axios.onResponse((response) => {
// Any condition that could be considered an response based on standard response
if(response.code !== 200){
throw response.msg
}
})
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();
});
});
});
})
I'm new to vue2JS and currently I am trying to create my very first service in vue2 ever.
I've created basic file api.js with this code:
import axios from 'axios';
export default () => {
return axios.create({
baseURL: 'http://localhost:8080/',
timeout: 10000,
headers: {
'Accept': 'application/json',
'Content-Type': 'application/json',
}
})
}
Code above is basic axios configuration which will be used in every service across entire app.
I import this file into my service:
import api from '../api.js';
export default {
getLatest () {
return api().get(`http://localhost/obiezaca/ob_serwer/api/article/getLatest.php`, {
headers: {
'Content-Type': 'application/json'
}
})
.then(function (response) {
console.log(response.data);
})
.catch(function (error) {
console.log(error);
});
}
}
Code above is responsible for making http request to backend rest API which give JSON in response.
And then finally I want to use this service inside my component <script></script> tags:
<script>
import { getLatest } from '../../../services/articles/getLatest';
export default {
data () {
return {
articles: []
}
},
created () {
const getLatestService = new getLatest();
console.log(getLatestService);
}
}
</script>
Here I want to execute code from service and actually execute this http request then save response in getLatestService constant and then console.log it and I should be able to see JSON in my browser console.
This doesn't work and give me this error in chrome console:
[Vue warn]: Error in created hook: "TypeError: WEBPACK_IMPORTED_MODULE_0__services_articles_getLatest.a is not a constructor"
And this error in command line:
39:35-44 "export 'getLatest' was not found in '../../../services/articles/getLatest'
Please help me to solve this problem. Additionally I want to refactor my code from service (second one) to use async await but I just can't find good example which would show me way to accomplish that.
EDIT 22.11.17
I added error which show in command line and { } when importing in component. I still didn't solve the problem.
EDIT 24.11.17
Looking for an answer I add more explanation of code I've posted and screenshot of files structure if maybe it can help.
I have check your code and what i can see is, in your api.js you have used
baseURL: 'http://localhost:8080/',
and in your service file
return api().get(`http://localhost/obiezaca/ob_serwer/api/article/getLatest.php`
In your service file you have not define your localhost port, i think it should be like
return api().get(http://localhost:8080/obiezaca/ob_serwer/api/article/getLatest.php
If above is not an your issue then you should try
const getLatestService = getLatest();
Because getLatest() is a function and not an object.
This might solve your error issue.
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);
}
};
});
});