web-dev-qa-db-fra.com

405 Méthode non autorisée Erreur lors de la demande d'API JSON à partir d'une simple application create-react

La demande suivante me donne une méthode 405 non autorisée lors de l'exécution à partir d'un projet généré par create-react-app simple à partir de localhost: 3000. J'ai vraiment besoin que cette application fonctionne en dehors du domaine (découplée). Cela ressemble beaucoup à un problème d'origine croisée, mais j'envoie le X-CSRF-TOKEN jeton d'en-tête et Apache configuré pour accepter également les en-têtes.

Aucune idée de ce que je fais mal ...

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

Cependant, l'exécution du même code à partir d'un module personnalisé sur le même domaine s'exécute comme prévu.

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;


MISE À JOUR:

Voici ce que mon services.yml cors.config ressemblait à: (CECI IS FAUX ???)

   # 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

C'est ce que mon cors.config doit être pour que ça marche !!

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

Voici ce que mon Apache.conf ressemble à:

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

NE FONCTIONNE PAS À PARTIR D'UNE APPLICATION JS REACT SÉPARÉE

La capture d'écran suivante montre le résultat de l'exécution du même JS à partir du domaine contenta.loc (même serveur que le point de terminaison)

Drupal Custom Module Implementation

TRAVAIL À PARTIR D'UN MODULE PERSONNALISÉ

La capture d'écran suivante montre l'erreur lors de l'exécution du JS à partir du serveur localhost create-react-app nodejs.

405 (Method Not Allowed)

4
Justin Levi Winter

Vous pouvez activer la prise en charge de CORS en modifiant le fichier 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
2
nuklive

Essayez peut-être ['x-csrf-token', 'authorization', 'content-type', 'accept', 'Origin', 'x-requested-with'] au lieu.

2
e0ipso

Voici l'exemple de travail de local.services.yml fichier qui peut être placé dans le sites/ dossier:

# 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

Vérifier sites/default/default.services.yml par exemple. Vérifiez également: prise en charge CORS opt-in .

Le fichier doit être chargé à partir de votre fichier de paramètres, par ex.

/**
 * Enable local development services.
 */
$settings['container_yamls'][] = DRUPAL_ROOT . '/sites/local.services.yml';

Si vous utilisez Apache, vérifiez également: CORS sur Apache .

1
kenorb