简体   繁体   中英

Restricted by CORS policy even after enabling CORS on Express and Express gateway

I'm using Express Gateway to proxy my microservices. I'm hitting the gateway from my react app with Axios . However, the call gets restricted by the CORS Policy . I have enabled CORS in the express gateway and also on my authentication service. I followed the official documentation to enable the CORS from this link for Express Gateway and this link for authentication service(Express App). Here is how I have the code.

Express Gateway config.yml

policies:
  - log
  - proxy
  - jwt
  - rate-limit
  - request-transformer
  - cors

pipelines:
  authPipeline: 
    apiEndpoints: 
      - auth
    policies: 
      -
        cors:
          -
            action:
              origin: '*'
              methods: 'HEAD,PUT,PATCH,POST,DELETE'
              allowedHeaders: ['Content-Type', 'Authorization']
      - 
        log: 
          action:
            message: 'auth ${req.method}'
      - 
        proxy:
          action: 
            serviceEndpoint: di

Authentication Service app.js

const cors = require('cors');
// Enabling CORS
const corsOptions = {
  origin: '*',
  methods: ['POST', 'GET', 'PATCH', 'DELETE'],
  allowedHeaders: ['Content-Type', 'Authorization']
}
app.use(cors(corsOptions));

The Headers I get back from the server when I try with Insomnia (a client like Postman) can be seen in the below picture.

我从服务器获得的标头

I get this error in the browser console.

Access to XMLHttpRequest at 'http://127.0.0.1:8080/api/v1/users/login' from 
origin 'http://localhost:3000' has been blocked by CORS policy: Response to 
preflight request doesnt pass access control check: No 'Access-Control- 
Allow-Origin' header is present on the requested resource.

I'm not sure what I'm missing. Please let me know if you need anything else, I'd be quick to provide. Each and every attempt that tries to explain what's wrong with my case is really appreciated.

EDIT: Adding the API call snippet

const config = {
    headers: {
      'Content-Type': 'application/json',
    },
  };
const body = JSON.stringify({ email, password });
const res = await axios.post('http://127.0.0.1:8080/api/v1/users/login', body, config);

Your "methods" definition is incorrect. It needs to be in the form of a YAML array:

methods: [ "HEAD", "PUT", "PATCH", "POST", "DELETE" ]

Or

methods:
- "HEAD"
- "PUT"
- "PATCH"
- "POST"
- "DELETE"

Or

methods:
- HEAD
- PUT
- PATCH
- POST
- DELETE

Everything else looks okay, although you may want to add "origin" to the list of allowedHeaders.

Update I have done some further testing on this, using this mini express server, then run the API gateway and server on Docker (with appropriate hostname changes in gateway.config.yml), and everything works as I expect with testing via curl from localhost and also from the browser.

var express = require('express')
var app = express()

// Enabling CORS
const cors = require('cors');
const corsOptions = {
  origin: '*',
  methods: ['POST', 'GET', 'PATCH', 'DELETE'],
  allowedHeaders: ['Content-Type', 'Authorization']
}
app.use(cors(corsOptions));

function addPath(path) {
  app.use(path, function(req, res, next) {
    const response = `Hello from ${req.method} ${path}`;
    console.log(response);
    res.send(response);
  });
}

addPath('/api/v1/users/*');
addPath('/api/v1/*');

const port = 5000;
app.listen(port, function () {
  console.log(`Example app listening on port ${port}`)
})

The only other thing I can suggest is to add another log message before the cors policy entry in gateway.config.yml like this:

- log: action: message: "incoming (auth): ${req.method} ${req.path} requesting IP: ${req.ip} origin ${req.headers.origin}"

and check the value of origin. If it is not undefined, try adding the following response-transformer before the proxy policy (adding response-transformer to the list of available policies, of course). I have had to do this once or twice but I forget the circumstances where it was necessary, so this is a shot in the dark.

  - response-transformer:
    - condition:
        name: expression
        expression: 'typeof req.headers.origin !== "undefined" && req.headers.origin === "http://localhost"'
      action:
        headers:
          add:
            access-control-allow-origin: '"http://localhost"'

if you have methods in auth apiEndpoints then removed methods from apiEndpoints: auth ----methods: 'GET,POST,PUT' ---- and it worked for me..

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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