Webpacker: Specify XSRF config defaults for axios

Created on 17 Nov 2017  路  4Comments  路  Source: rails/webpacker

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?

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.

// 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)

All 4 comments

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
          })
        }
      )
  }
}
Was this page helpful?
0 / 5 - 0 ratings

Related issues

Eearslya picture Eearslya  路  3Comments

ijdickinson picture ijdickinson  路  3Comments

suhomozgy-andrey picture suhomozgy-andrey  路  3Comments

inopinatus picture inopinatus  路  3Comments

iChip picture iChip  路  3Comments