Open bradjones1 opened 3 years ago
I would like to use axios for the http fetch, I am using @nuxt/axios
and @nuxt/auth
to make authenticated requests to my api. I can't figure out a way to set the Auth header for http fetch. I also need to use a CSRF token header.
@shadow81627 I can't speak to whether axios could be dropped in, instead of fetch - I think the public apis are interoperable, but I'm not an expert? Per my comment above, you can set default settings for the client a la
const jsonapi = new JsonApiSource({
schema,
name: 'remote',
host: jsonApiHost,
defaultFetchSettings: {
credentials: 'same-origin',
timeout: 10000,
headers:{
'x-csrf-token': Cookies.get('csrf_token'),
}
}
}
and while it's not super well documented, you can set Orbit.globals.fetch
to an instance of fetch, preconfigured with whatever you need. So at least this covers your default headers and other configuration for the client on the source config, but YMMV with using axios instead.
Future Brad here, clarifying that you probably actually want to set Orbit.fetch
, since the one in Orbit.globals
is the global one.
Also the CSRF token may change (depending on the server's implementation) so setting it statically here is probably not the best idea, either.
In case others run into this, it can be handled with a decorated fetch
function (as @bradjones1 alluded to). Here's roughly what I've come up with;
import { Orbit } from '@orbit/core';
import fetch from 'cross-fetch';
...
async _csrfAwareFetch(url, opts) {
const options = opts || {};
if (!options.method) options.method = 'GET';
const requestUrl = new URL(url, window.location.origin + window.customDrupalBasePath);
const isDrupalRequest = requestUrl.host === window.location.host && requestUrl.pathname.startsWith(window.customDrupalBasePath);
const isUnsafeMethod = !['HEAD', 'GET', 'OPTIONS', 'TRACE'].includes(options.method.toUpperCase());
const addAntiCsrfHeader = isDrupalRequest && isUnsafeMethod;
if (addAntiCsrfHeader) {
const tokenResponse = await fetch(createDrupalUrl('/session/token')).then(r => r.text());
// TODO: Consider caching the token
if (!options.headers) options.headers = {};
options.headers['X-CSRF-Token'] = tokenResponse;
}
return await fetch(url, options);
}
export default function createDrupalUrl(pathSuffix) {
return new URL(pathSuffix, window.location.origin + window.customDrupalBasePath);
}
...
Orbit.fetch = _csrfAwareFetch;
Axios will set a CSRF token header based on the contents of a cookie, in order to protect mutable operations:
https://github.com/axios/axios/blob/5bc9ea24dda14e74def0b8ae9cdb3fa1a0c77773/dist/axios.js#L929
This is easy enough to do with some custom source
defaultFetchSettings
, however adding native support would perhaps allow for runtime retrieval of the value (e.g., if the cookie is updated). I looked to see if there was any fetch middleware in the wild which would allow me to setOrbit.globals.fetch
with a wrapped fetch function, but didn't see anything.