I'd like to specify config defaults that will be applied to every request:
const csrfToken = document.querySelector("meta[name=csrf-token]").content
axios.defaults.headers.common[鈥榅-CSRF-Token鈥橾 = csrfToken
Any suggestions how to accomplish this in a Webpacker 3.0.2 / React environment?
EDIT: See comment below for best answer
That looks right to me. I'd just make sure this code is called on every page before making requests.
// app/javascript/setupCSRFToken.js
import axios from 'axios'
export default function() {
const csrfToken = document.querySelector("meta[name=csrf-token]").content
axios.defaults.headers.common[鈥榅-CSRF-Token鈥橾 = csrfToken
}
// app/javascript/packs/application.js
import setupCSRFToken from '../setupCSRFToken'
setupCSRFToken()
// or
window.addEventListener('DOMContentLoaded', setupCSRFToken)
Thanks @rossta 馃憤
Kindly consider posting non-webpacker questions to SO. We are happy to help with webpack and webpacker related issues though
Just FYI: In Rails Test environments the csrf protection is disabled, thus the token not available and will result in errors such as:
Uncaught TypeError: Cannot read property 'getAttribute' of undefined
TypeError: document.querySelector(...) is null
jQuery.Deferred exception: Cannot read property 'getAttribute' of undefined
If using system/feature tests with capybara/chrome than the stacktraces and messages are not helpful, so one can waste some time for debugging.
So better to wrap that in an if:
export default function() {
const tokenDom = document.querySelector("meta[name=csrf-token]")
if (tokenDom) {
const csrfToken = tokenDom.content
axios.defaults.headers.common[鈥榅-CSRF-Token鈥橾 = csrfToken
}
}
Sorry to keep polluting this issue, but the above solutions won't work as new instances of the axios client won't have the header. For anyone still searching for a solution, try something like this to have the header set in future instances of the axios client.
packs/axios.js
//
// wrapper around axios to include Rails CSRF token
//
import axios from 'axios'
const token = document.querySelector('[name="csrf-token"]') || {content: 'no-csrf-token'}
const ax = axios.create({
headers: {
common: {
'X-CSRF-Token': token.content
}
}
})
export default ax
YourReactComponent.jsx
import React, { Component } from 'react'
import ax from 'packs/axios'
class YourComponent extends Component {
componentDidMount() {
ax
.get('/api/quotes')
.then(
(response) => {
this.setState({
quotes: response.data
})
}
)
}
}
Most helpful comment
EDIT: See comment below for best answer
That looks right to me. I'd just make sure this code is called on every page before making requests.