次のリクエストでは、localhost:3000から単純なcreate-react-appで生成されたプロジェクトから実行すると、405メソッドは許可されません。私は本当にこのアプリをドメインの外で実行する必要があります(分離)。これはクロスオリジンの問題に非常によく似ていますが、X-CSRF-TOKEN
ヘッダートークンと、ヘッダーを受け入れるように構成されたApacheがあります。
私が何を間違っているのかわからない...
Host: contenta.loc
Connection: keep-alive
Pragma: no-cache
Cache-Control: no-cache
Access-Control-Request-Method: GET
Origin: http://localhost:3000
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_13_1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/63.0.3239.84 Safari/537.36
Access-Control-Request-Headers: authorization,x-csrf-token
Accept: */*
Accept-Encoding: gzip, deflate
Accept-Language: en-US,en;q=0.9
ただし、同じドメインのカスタムモジュール内から同じコードを実行すると、期待どおりに実行されます。
import React, { Component } from 'react';
import axios from 'axios';
import Querystring from 'query-string';
import SubRequests from 'd8-subrequests';
const URL = 'http://contenta.loc';
class App extends Component {
state = {
csrfToken: '',
oauthToken: {}
};
constructor(props){
super(props);
this.initializeCsrfToken();
this.initializeOauthToken();
}
initializeCsrfToken(){
axios.get(URL + '/session/token')
.then(response => {
this.setState({csrfToken: response.data});
})
.catch((error) => {
console.log('error ' + error);
});
}
initializeOauthToken(){
const data = {
grant_type: 'password',
client_id: '77e40506-4b2a-4317-b6c0-5ed5b27ce886',
client_secret: 'test1123',
username: 'test',
password: 'test'
};
axios.post(URL + '/oauth/token', Querystring.stringify(data))
.then(response => {
this.setState({oauthToken: response.data.access_token});
})
.catch((error) => {
console.log('error ' + error);
});
}
fetchSubrequests() {
const subrequests = new SubRequests(URL + '/subrequests?_format=json');
const AuthStr = 'Bearer '.concat(this.state.oauthToken);
subrequests.add({
uri: '/api/categories'
});
subrequests.add({
uri: '/api/tags'
});
subrequests.add({
uri: '/api/menus'
});
axios.get(subrequests.getUrl(), {
headers: {
Authorization: AuthStr,
'X-CSRF-Token': this.state.csrfToken,
}
}).then(dataresponse => {
console.log(dataresponse);
})
}
render = () => {
return (
<button >
<div onClick ={
() => {this.fetchSubrequests()}
} > Fetch Subrequests</div>
</button>
)
}
}
export default App;
更新:
これが私のservices.yml
cors.configは次のようになりました:(THIS IS WRONG ???)
# Configure Cross-Site HTTP requests (CORS).
# Read https://developer.mozilla.org/en-US/docs/Web/HTTP/Access_control_CORS
# for more information about the topic in general.
# Note: By default the configuration is disabled.
cors.config:
enabled: true
# Specify allowed headers, like 'x-allowed-header'.
allowedHeaders: ['x-csrf-token,authorization,content-type,accept,Origin,x-requested-with']
# Specify allowed request methods, specify ['*'] to allow all possible ones.
allowedMethods: ['POST, GET, OPTIONS, DELETE, PUT']
# Configure requests allowed from specific origins.
allowedOrigins: ['*']
# Sets the Access-Control-Expose-Headers header.
exposedHeaders: true
# Sets the Access-Control-Max-Age header.
maxAge: false
# Sets the Access-Control-Allow-Credentials header.
supportsCredentials: false
これが機能するためには、cors.configが必要です。
cors.config:
enabled: true
# Specify allowed headers, like 'x-allowed-header'.
# ['x-csrf-token,authorization,content-type,accept,Origin,x-requested-with']
allowedHeaders: ['*']
# - '*'
# Specify allowed request methods, specify ['*'] to allow all possible ones.
# ['POST, GET, OPTIONS, DELETE, PUT']
allowedMethods: ['*']
# - '*'
# Configure requests allowed from specific origins.
allowedOrigins: ['*']
# Sets the Access-Control-Expose-Headers header.
exposedHeaders: true
# Sets the Access-Control-Max-Age header.
maxAge: false
# Sets the Access-Control-Allow-Credentials header.
supportsCredentials: false
これが私のApache.conf
は次のようになります。
<VirtualHost *:80>
ServerName loc
DocumentRoot /Users/justinwinter/Sites
VirtualDocumentRoot /Users/justinwinter/Sites/%-2/docroot
UseCanonicalName Off
Header set Access-Control-Allow-Origin "http://localhost:3000"
Header set Access-Control-Allow-Credentials true
Header always set Access-Control-Allow-Methods "POST, GET, OPTIONS, PATCH, DELETE"
Header always set Access-Control-Allow-Headers: "Accept, Content-Type, Content-Length, Accept-Encoding, X-CSRF-Token, Authorization"
<Directory "/Users/justinwinter/Sites/*/docroot">
AllowOverride All
Order allow,deny
Allow from all
Require all granted
</Directory>
AddType application/x-httpd-php .php
</VirtualHost>
個別のJS REACTアプリからは機能しません
次のスクリーンショットは、contenta.locドメイン(エンドポイントと同じサーバー)内から同じJSを実行した結果を示しています
カスタムモジュール内からの作業
次のスクリーンショットは、create-react-app nodejs localhostサーバー内からJSを実行したときのエラーを示しています。
CORSサポートを有効にして、sites/default/services.ymlファイルを変更できます。
cors.config:
enabled: true
allowedHeaders:
- '*'
allowedMethods:
- '*'
allowedOrigins:
# Note: you need to specify the Host + port where your app will run.
- localhost:8000
exposedHeaders: false
maxAge: false
supportsCredentials: false
たぶん['x-csrf-token', 'authorization', 'content-type', 'accept', 'Origin', 'x-requested-with']
代わりに。
local.services.yml
フォルダーに配置できるsites/
ファイルの作業例を次に示します。
# Local development services.
#
# To activate this feature, follow the instructions at the top of the
# 'example.settings.local.php' file, which sits next to this file.
parameters:
http.response.debug_cacheability_headers: true
cors.config:
enabled: true
# Specify allowed headers, like 'x-allowed-header'.
allowedHeaders: ['*']
# Specify allowed request methods, specify ['*'] to allow all possible ones.
allowedMethods: ['*']
# Configure requests allowed from specific origins.
allowedOrigins: ['*']
# Sets the Access-Control-Expose-Headers header.
exposedHeaders: false
# Sets the Access-Control-Max-Age header.
maxAge: false
# Sets the Access-Control-Allow-Credentials header.
supportsCredentials: false
services:
cache.backend.null:
class: Drupal\Core\Cache\NullBackendFactory
たとえば sites/default/default.services.yml
を確認してください。以下も確認してください: オプトインCORSサポート 。
ファイルは、設定ファイルからロードする必要があります。
/**
* Enable local development services.
*/
$settings['container_yamls'][] = DRUPAL_ROOT . '/sites/local.services.yml';
Apacheを使用している場合は、 CORS on Apache も確認してください。