Karan Kumar
Karan Kumar

Reputation: 3176

React w/ Kubernetes deployed API giving cors error

This is different from other cors related questions

I am running my node backend-api on microservices on kubernetes deployed on Digitalocean. I have literally read all the blogs/forums related to this issue and haven't found any solution (specifically the ones related to Digitalocean).

I am unable to connect to the cluster via React application running on 'localhost:3000' or anywhere outside the kubernetes cluster.

It is giving me below error:

Access to XMLHttpRequest at 'http://cultor.dev/api/users/signin' 
from origin 'http://localhost:3000' has been blocked by 
CORS policy: Response to preflight request doesn't pass access 
control check: Redirect is not allowed for a preflight request.

The kubernetes cluster's loadbalancer is listening on "cultor.dev" which is set as a local domain in /etc/hosts. I am able to make it work using Postman!

NOTE: I have tried using cors package as well, it won't help. Also, it works fine if I run this react app inside of the kubernetes cluster which I do not want.

Ingress nginx config (tried using annotations mentioned on the official website):

apiVersion: extensions/v1beta1
kind: Ingress
metadata: 
    name: ingress-service 
    ## this tells ingress to pick up the routing rules mentioned in this config
    annotations: 
        nginx.ingress.kubernetes.io/default-backend: ingress-nginx-controller
        kubernetes.io/ingress.class: nginx 
        ## tells ingress to check for regex in the config file
        nginx.ingress.kubernetes.io/use-regex: 'true'
        # nginx.ingress.kubernetes.io/enable-cors: 'true'
        # nginx.ingress.kubernetes.io/cors-allow-methods: "PUT, GET, POST, OPTIONS"
        # nginx.ingress.kubernetes.io/cors-allow-origin: "*"
        # nginx.ingress.kubernetes.io/cors-max-age: 600
        # certmanager.k8s.io/cluster-issuer: letsencrypt
        # kubernetes.io/ingress.class: nginx
        # service.beta.kubernetes.io/do-loadbalancer-enable-proxy-protocol: "true"

One of the microservices config (tried cors package as well):

// APP SETTINGS
app.set('trust proxy', true);
app.use(json());
app.use((req, res, next) => {
  res.header('Access-Control-Allow-Origin', '*');
  res.header('Access-Control-Allow-Headers', '*');
  res.header('Access-Control-Request-Headers', '*');
  if (req.method === "OPTIONS") {
    res.header('Access-Control-Allow-Methods', '*');
    return res.status(200).json({});
  }
  next();
});

Upvotes: 9

Views: 14294

Answers (4)

Karan Kumar
Karan Kumar

Reputation: 3176

Okay, after alot of research and with the help of the other answers I did the following:

  1. I changed the request to the backend (from the client side) to https instead of http. This fixed the error Redirect is not allowed for a preflight request
  2. I changed the config ingress nginx config to get rid of the error multiple values in Access-Control-Allow-Origin :
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
  name: ingress-service
  annotations:
    nginx.ingress.kubernetes.io/default-backend: ingress-nginx-controller
    kubernetes.io/ingress.class: nginx
    ## tells ingress to check for regex in the config file
    nginx.ingress.kubernetes.io/use-regex: "true"
    nginx.ingress.kubernetes.io/configuration-snippet: |
      add_header Access-Control-Allow-Methods "POST, GET, OPTIONS";
      add_header Access-Control-Allow-Credentials true;
    nginx.ingress.kubernetes.io/enable-cors: "true"
    nginx.ingress.kubernetes.io/cors-allow-methods: "PUT, GET, POST, OPTIONS"

I hope it helps others as well.

Upvotes: 11

louisbuchbinder
louisbuchbinder

Reputation: 179

CORS policy: Response to preflight request doesn't pass access 
control check: Redirect is not allowed for a preflight request.

The preflight CORS request is actually a separate request that the browser makes to your server to check if the access control headers sent back in the response will accept the main request. The preflight request uses the HTTP OPTIONS method. I bet if you log the req.method for incoming requests you will see the OPTIONS requests coming in.

When you receive one of these preflight requests you should respond with the appropriate Access-Control-Allow-Origin and Access-Control-Allow-Headers response headers.

Upvotes: 0

Code
Code

Reputation: 6251

Redirect is not allowed for a preflight request.

Seems like there is a redirect happening. There isn't enough information to conclude where. My guess is that you have TLS set up on your Ingress and http://cultor.dev/api/users/signin is being automatically redirected to https.

Upvotes: 0

Someone Special
Someone Special

Reputation: 13588

Why are the cors settings commented?

nginx.ingress.kubernetes.io/configuration-snippet: |
  add_header Access-Control-Allow-Origin $http_origin;
  add_header Access-Control-Allow-Methods "POST, GET, OPTIONS";
  add_header Access-Control-Allow-Credentials true;

Same issue on GitHub

Upvotes: 5

Related Questions