Fetch GET Request with custom headers ReactJS

2019-02-09 18:30发布

问题:

I am trying to send a GET request to a API but when i add custom headers in the code somthing strange happens. Somewhere the request method changes to OPTIONS when it reaches the web server.

But when i do the same without headers it will be a GET type. When i use the application postman (API development tool) the request works fine!

request code:

    let token = this.generateClientToken(privateKey, message);

    let myheaders = {
      "appID": appID,
      "authorizationkey": token
    }

    fetch('http://localhost:8080/api/app/postman', {
      method: "GET",
      // body: JSON.stringify(''),
      headers: myheaders
    }).then(function(response) {
      console.log(response.status);     //=> number 100–599
      console.log(response.statusText); //=> String
      console.log(response.headers);    //=> Headers
      console.log(response.url);        //=> String

      return response.text()
    }, function(error) {
      console.log(error.message); //=> String
    })
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react-dom.min.js"></script>

Server log ouput (with headers):

worker_1  | 172.18.0.4 -  17/Mar/2017:15:47:44 +0000 "OPTIONS /index.php" 403
web_1     | 172.18.0.1 - - [17/Mar/2017:15:47:44 +0000] "OPTIONS /api/app/postman HTTP/1.1" 403 5 "-" "Mozilla/5.0 (Macintosh; Intel Mac OS X 10.12; rv:54.0) Gecko/20100101 Firefox/54.0" "-"

Server log output (without headers):

worker_1  | 172.18.0.4 -  17/Mar/2017:16:01:49 +0000 "GET /index.php" 403
web_1     | 172.18.0.1 - - [17/Mar/2017:16:01:49 +0000] "GET /api/app/postman HTTP/1.1" 403 5 "http://localhost:3000/" "Mozilla/5.0 (Macintosh; Intel Mac OS X 10.12; rv:54.0) Gecko/20100101 Firefox/54.0" "-"

Added the NPM modules for fetch support in extra browsers:
https://github.com/github/fetch#obtaining-the-response-url
https://github.com/taylorhakes/promise-polyfill

What am i missing here? It all looks correct to me.

I am using firefox development edition to test the Reactjs app by running it with NPM start

回答1:

You probably want to install the cors npm package https://www.npmjs.com/package/cors on the server where you have your http://localhost:8080/api/app Node app running.

https://developer.mozilla.org/en-US/docs/Web/HTTP/Access_control_CORS#Preflighted_requests has details about what’s happening here: Your appID and authorizationkey request headers are triggering your browser to send a CORS preflight OPTIONS request before sending the GET.

To handle that OPTIONS request, you can install the cors npm package and follow the instructions at https://www.npmjs.com/package/cors#enabling-cors-pre-flight to configure it:

var express = require('express')
  , cors = require('cors')
  , app = express();
app.options('*', cors()); // include before other routes
app.listen(80, function(){
  console.log('CORS-enabled web server listening on port 80');
});


回答2:

The accepted answer game me the solution, i am not using a nodeJS backend but plain Nginx with php-fpm.

But the answer explains how a request with custom header wil always first do a OPTIONS request to verify the acceptance of the set header names, so i had to change the response in the webserver to give a 204 code back with te right headers included. without it would hit my PHP code where authentication would fail and result in a 403 code because of the absence of the headers with the content and request method used.

This is what i added to the Nginx host to make it work:

location ~ \.php$ {
             add_header 'Access-Control-Allow-Origin' "*";
             add_header 'Access-Control-Allow-Methods' 'GET, POST, OPTIONS, DELETE, PUT';
             add_header 'Access-Control-Allow-Headers' 'appID,authorizationkey';

             if ($request_method = 'OPTIONS') {
                return 204;
             }
}

I know that its far from perfect but for now it made it work. and again thanks for pointing me into the right direction.