how to disable prepareHeaders on specific endpoint?, for example, i dont need authorization header on login or register endpoint, but on some endpoint i need authorization headers.
export const backendService = createApi({
reducerPath: 'backend',
baseQuery: fetchBaseQuery({
baseUrl: `${Endpoint}`,
prepareHeaders: (headers, {getState}) => {
const token = getState().auth.token;
if (token) {
headers.set('authorization', `Bearer ${token}`);
}
headers.set('Access-Control-Allow-Origin', '*');
return headers;
},
}),
tagTypes: ['Question', 'Questions'],
endpoints: build => ({
registerUser: build.mutation({ <------ skip prepareHeaders in register
query: body => ({
url: 'auth/local/register',
method: 'POST',
body,
}),
}),
login: build.mutation({ <------- skip prepareHeaders on login
query: body => ({
url: 'auth/local',
method: 'POST',
body,
}),
}),
getCategories: build.query({ <------ apply prepareHeaders
query: () => {
return {
url: 'categories'
};
},
}),
}),
});
The current beta for RTK 1.7 passes the endpointname to prepareHeaders, so if you try that you should be able to work around that.
The BaseQueryApi and prepareheaders args now include fields for endpoint name, type to indicate if it's a query or mutation, and forced to indicate a re-fetch even if there was already a cache entry. These can be used to help determine headers like Cache-Control: no-cache.
Related
I have a POST request which returns a 302 when successful. I need to get the location response header which holds the url I'll need to redirect to. Currently I have this:
accountLogin: builder.mutation<any, any>({
query: (body) => ({
url: `/accounts/login`,
method: 'POST',
body,
responseHandler: (response) => {
console.log(response, response.headers);
return response.text();
},
}),
}),
If I look in the network tab of my browser the 302 is there, as is the location header with the proper URL. But the 'console.log' in responseHandler shows no headers. I can't find much about this in the documentation -- what am I missing?
to access status code you can use validateStatus something like this:
import { createApi, fetchBaseQuery } from '#reduxjs/toolkit/query'
export const customApi = createApi({
// Set the baseUrl for every endpoint below
baseQuery: fetchBaseQuery({ baseUrl: '/api/' }),
endpoints: (builder) => ({
getUsers: builder.query({
query: () => ({
url: `users`,
// Example: we have a backend API always returns a 200,
// but sets an `isError` property when there is an error.
validateStatus: (response, result) =>
response.status === 200 && !result.isError,
}),
}),
}),
})
or use transformResponse
transformResponse: (response, meta, arg) =>
response.some.deeply.nested.collection
I am using fetch to call backend API, th eprobelm is the backend security is a token, for security purpose we can not expose this token on public configuration.
I wanted to know if it is possible to put the token on server side params and then when we call fetch params is not visible in chrome debug and use only on NITRO following this text
Nitro allows 'direct' calling of routes via the globally-available $fetch helper. This will make an API call to the server if run on the browser, but will directly call the relevant function if run on the server, saving an additional API call.
$fetch API is using my fetch, with key features including:
This is my code
let recipientWebDTO = {};
recipientWebDTO.email = this.form.email;
recipientWebDTO.subscriptions = [{
"mailingListUnid": useRuntimeConfig().UNID
}];
const { status } = await $fetch
.raw(useRuntimeConfig().public.REST_API, {
method: "POST",
body: recipientWebDTO,
headers: {
"Content-Type": "application/json",
Authorization: useRuntimeConfig().TOKEN,
},
})
.then((response) => ({
status: response.status,
}))
.catch((error) => ({
status: error?.response?.status || 500,
}));
And my config file
export default defineNuxtConfig({
runtimeConfig: {
UNID: '58',
COMPANY_UNID: '3',
TOKEN: '78f77',
public: {
REST_API: process.env.REST_API || 'http://localhost:8080/rest/mailinglist/register/v1'
},
},
css: ["#/assets/_main.scss"],
vite: {
css: {
preprocessorOptions: {
scss: {
additionalData: '#use "#/assets/_colors.scss" as *;'
}
}
}
}
})
I want UNID, COMPANY_UNID, TOKEN to be visible only on server side, here it is just undefined, have I to create a middleware to handle it ? If yes, how I can use the same project to make it work ?
To manage to do it i added a server part as it is explained here:
Server api nuxtjs3 documentation
I created a directory server/api then my ts file with my proxy call where i use my token. Then in my vue i call my api. it means on browser the server file is invisible, and parameters and token nt accessibles.
in my vue:
const { status } = await $fetch.raw( '/api/newsletter', { method: "POST", body: this.form.email } )
in my server file:
export default defineEventHandler(async (event) => {
const runtimeConfig = useRuntimeConfig();
const subscriber = await readBody(event);
console.log("url used for rest call" + runtimeConfig.REST_API);
let recipientWebDTO = {
email: subscriber,
subscriptions: [{
"mailingListUnid": runtimeConfig.UNID
}]
};
const status = await $fetch.raw(runtimeConfig.REST_API, {
method: "POST",
body: recipientWebDTO,
headers: {
Authorization: runtimeConfig.TOKEN,
},
}).then((response) => ({
status: response.status,
}))
.catch((error) => ({
status: error?.response?.status || 500,
}));
return status;
})
The only complexity i have is i wanted to get a specific status but i always have the api call status, is 200 i wanted to simply forward the result but in NUXTJS is in WIP.
I set extraOptions in my endpoint like so :
const myApi = api.injectEndpoints({
endpoints: builder => ({
changePassowrd: builder.mutation({
query: (data) => ({
url: `${Config.BASE_URL}/users/${data.userId}`,
method: 'PATCH',
body: data,
}),
extraOptions: () => ({
myOption: 'Test Option',
}),
}),
})
})
And I try to read extraOptions in prepareHeaders like so:
const baseQuery = fetchBaseQuery({
baseUrl: Config.BASE_URL,
prepareHeaders: (headers, {getState, extra}) => {
console.log('Extra Stuff', extra); // undefined
return headers;
},
});
But I'm always getting undefined in the console after triggering the mutation, why is that? Am I using it wrong?
That's redux-thunk's extra, not the endpoint's extraOptions. It seems like fetchBaseQuery generally does not make use of extraOption - a pull request integrating that where necessary is highly welcome.
after sending in body "email" and "password" https://identitytoolkit.googleapis.com/ returns a few objects in the response.
One of them is "idToken": with a value of the token.
What do I need?
I need to get this token, store it in variable and reuse it in further tests.
So far I prepared something like this:
it("Get a fresh admin firebase token", () => {
cy.request({
method: "POST",
url: "https://identitytoolkit.googleapis.com/...",
body: {
"email": "myUsername",
"password": "myPassword",
"returnSecureToken": true
},
headers: {
accept: "application/json"
}
}).then((responseToLog) => {
cy.log(JSON.stringify(responseToLog.body))
}).then(($response) => {
expect($response.status).to.eq(200);
})
})
})```
Above code works, but cy.log() returns the whole body response. How can I separate only idToken and reuse it in my next API scenarios?
Considering that idToken in in response body so inside then() you can directly wrap the value and save it using an alias and then use it later.
it('Get a fresh admin firebase token', () => {
cy.request({
method: 'POST',
url: 'https://identitytoolkit.googleapis.com/...',
body: {
email: 'myUsername',
password: 'myPassword',
returnSecureToken: true,
},
headers: {
accept: 'application/json',
},
}).then((response) => {
cy.wrap(response.body.idToken).as('token')
})
})
cy.get('#token').then((token) => {
cy.log(token) //logs token or Do anything with token here
})
In case you want to use the token in a different it block you can:
describe('Test Suite', () => {
var token
it('Get a fresh admin firebase token', () => {
cy.request({
method: 'POST',
url: 'https://identitytoolkit.googleapis.com/...',
body: {
email: 'myUsername',
password: 'myPassword',
returnSecureToken: true,
},
headers: {
accept: 'application/json',
},
}).then((response) => {
token = response.body.idToken
})
})
it('Use the token here', () => {
cy.log(token) //prints token
//use token here
})
})
I have a couple of RSAA actions like so:
export const getUserById = id => ({
[RSAA]: {
endpoint: "...",
method: "GET",
headers: { "Content-Type": "application/json" },
credentials: "include",
types: [
GET_USER_BY_ID_REQUEST,
GET_USER_BY_ID_SUCCESS,
GET_USER_BY_ID_FAILURE
]
}
});
export const getUserPosts = id => ({
[RSAA]: {
endpoint: "...",
method: "GET",
headers: { "Content-Type": "application/json" },
credentials: "include",
types: [
GET_USER_POSTS_REQUEST,
GET_USER_POSTS_SUCCESS,
GET_USER_POSTS_FAILURE
]
}
});
What do I have to do to use thunk (I think) to chain these two actions?
I could create a third action called getUserThenPosts? But what would that look like?
Use redux-thunk and create a third action called getUserThenPosts.
export const getUserThenPosts = id => dispatch => {
return dispatch(getUserById(id))
.then((payload) => {
return dispatch(getUserPosts(payload.someIdFromUserPayload)));
};
};
I'm assuming that getUserPosts requires an argument from the user payload.