简体   繁体   English

为什么从 React 子组件发布时 Axios 不包括 XSRF-TOKEN?

[英]Why is Axios not including XSRF-TOKEN when POSTing from React sub-component?

I have a Laravel 6.x app that I'm working on.我有一个正在开发的 Laravel 6.x 应用程序。 Axios seems to not be consistent about when it sends XSRF-TOKEN headers. Axios 似乎在发送 XSRF-TOKEN 标头时不一致。

Then I have two pages within the app that need to do axios posts.然后我在应用程序中有两个页面需要做 axios 帖子。 One of which works correctly, the other - which does the actual post from a Component included within a Component - excludes the header and fails.其中一个工作正常,另一个 - 从组件中包含的组件执行实际发布 - 排除 header 并失败。

The common files are常见的文件是

js/app.js js/app.js

require('./bootstrap');

js/bootstrap.js js/bootstrap.js

window.axios = require('axios');
//snip
let token = document.head.querySelector('meta[name="csrf-token"]');

if (token) {
    window.axios.defaults.headers.common['X-CSRF-TOKEN'] = token.content;
} else {
    console.error('CSRF token not found: https://laravel.com/docs/csrf#csrf-x-csrf-token');
}

layouts/reactapp.blade.php布局/reactapp.blade.php

<!DOCTYPE html>
<html lang="{{ app()->getLocale() }}">
<head>
    <meta name="csrf-token" content="{{ csrf_token() }}">
</head>
<body>
    @yield('reactContainer')
    <script src="{{ asset('js/app.js') }}"></script>
    @yield('components')
</body>
</html>

The working page is orders/create.blade.php工作页面是 orders/create.blade.php

@extends('layouts.reactapp')

@section('reactContainer')
    <div id='orders-create'></div>
@endsection

@section('components')
    <script src="{{ asset('js/components/Orders.js') }}"></script>
@endsection

js/components/Orders.js js/components/Orders.js

import React, { Component } from 'react';
import {Page} from '@shopify/polaris';
import ReactDOM from 'react-dom';

export default class Orders extends Component {
    constructor(props) {
        super(props);
        this.onFormSubmit = this.onFormSubmit.bind(this);
        this.handleFileUpload = this.handleFileUpload.bind(this);
    }
    render() {
        return (
            <Page
                title="Orders"
                primaryAction={{
                    content: 'Submit',
                    onAction: this.onFormSubmit,
                }}
            ><!-- snip --></Page>
        );
    }
    onFormSubmit() {
        this.handleFileUpload().then((response) => { /*snip*/ });
    }
    handleFileUpload() {
        return window.axios.post(url, formData, config);
    }
};
if (document.getElementById('orders-create')) {
    ReactDOM.render(<Orders />, document.getElementById('orders-create'));
}

The non-working page is shopify/settings.blade.php非工作页面是 shopify/settings.blade.php

@extends('layouts.reactapp')

@section('reactContainer')
    <div id='shopify-setting'></div>
@endsection

@section('components')
    <script src="{{ asset('js/components/Setting.js') }}"></script>
@endsection

js/components/Setting.js js/components/Setting.js

import React, { Component } from 'react';
import ReactDOM from 'react-dom';
import SettingCheckbox from './fields/SettingCheckbox.js';
export default class Setting extends Component {
    render() {
        return (
            return <SettingCheckbox
                setting={setting}
                key={setting.id}
            />
        );
    }
}
if (document.getElementById('shopify-setting')) {
    ReactDOM.render(<Setting />, document.getElementById('shopify-setting'));
}

js/component/SettingCheckbox.js js/组件/SettingCheckbox.js

import { Button } from '@shopify/polaris';
import React, { Component } from 'react';

export default class SettingCheckbox extends Component {
    constructor(props) {
        super(props);
        this.updateSetting = this.updateSetting.bind(this);
    }
    render() {
        return(
            <Button onclick={this.updateSetting}>Update</Button>
        );
    }
    updateSetting() {
        window.axios.patch(url, formData).then(/*snip*/);
    }
}

I don't see any critical difference between these two.我认为这两者之间没有任何关键区别。 It should be the same axios object either way, why would it behave any differently in a nested component?无论哪种方式,它都应该是相同的 axios object,为什么它在嵌套组件中的行为会有所不同?

I don't know how correct a solution this is, but setting axios.withCredentials globally ultimately did it.我不知道这是一个多么正确的解决方案,但是在全球范围内设置 axios.withCredentials 最终做到了。

js/bootstrap.js js/bootstrap.js

window.axios = require('axios');
window.axios.defaults.withCredentials = true;
//snip
let token = document.head.querySelector('meta[name="csrf-token"]');

if (token) {
    window.axios.defaults.headers.common['X-CSRF-TOKEN'] = token.content;
} else {
    console.error('CSRF token not found: https://laravel.com/docs/csrf#csrf-x-csrf-token');
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM