Rob--W / cors-anywhere

CORS Anywhere is a NodeJS reverse proxy which adds CORS headers to the proxied request.
MIT License
8.62k stars 6.03k forks source link

Hello! How config to run in virtual directory? #143

Open hungud opened 5 years ago

hungud commented 5 years ago

Dear Mr.

How to config http proxy run on virtual directory. Eg: http://localhost:8080/cors-anywhere/

fdarveau commented 5 years ago

Making the service work from a virtual directory

I have managed to do it with Caddy. Here is the snippet from my Caddyfile :

proxy /cors-anywhere localhost:2000 {
    without /cors-anywhere
    websocket
}

Basically, you have to configure your host to remove the virtual directory part of the URL when it is redirecting the the cors-anywhere service.

The above snippet makes Caddy proxy the request https://localhost:8080/cors-anywhere/an_url as https://localhost:2000/an_url. Without the line without /cors-anywhere, it would instead proxy to https://localhost:8080/cors-anywhere/an_url

Making the service actually handle requests from a same origin app

Once your host is configured, you have another problem if your app is hosted in a virtual directory on the same server (in your case, on http://localhost:8080/app). Browsers generally don't put the Origin header since the host is the same. However, they still set the Referer header, though not all in the same way.

Here are 3 cases for headers for an app located at http://localhost:8080/app:

As you can see, Chrome and Edge have a different way of setting the Referer header and both are not the same as what the Origin header would be.

~~You would have to replace the line var origin = req.headers.origin || ''; with the following lines in the file lib\cors-anywhere.js : var origin = req.headers.origin || req.headers.referer || ''; origin = origin.replace(/^(https?:\/\/[^\/])(\/.)?$/, '$1'); // Only keep the host part of the origin/referer~~

Those lines make cors-anywhere take the referer is the origin is not set. It then strips everything but the host part (what the Origin header would be) by using a regex.

Since you are now looking for a Referer header, you would also need to add 'referer' to the requireHeader array of the server.js file.

I am currently working on a pull request to add the changes above so other people don't have the same trouble running it in a virtual directory (except configuring the host).

EDIT: Pull request now open (see below)

fdarveau commented 5 years ago

As per the discussion in the referenced PR, once the host is configured as mentioned in the comment above, you would need to set the X-Requested-With header when creating your request from your app to make CORS Anywhere accept the request.

Rob--W commented 5 years ago

Since I get mailed fairly often about this, here is a way to use CORS Anywhere in a virtual directory in Nginx. Change directory (e.g. "/cors/") , IP (e.g. 127.0.0.1) and port (e.g. 8080) as needed:

    location /cors/ {
      if ($request_uri ~ ^/cors/(.*) ) {
        set $cors_request_uri $1;
      }

      proxy_pass http://127.0.0.1:8080/$cors_request_uri;
      proxy_buffering off;
    }

It's important to use $request_uri instead of the more common $uri, because the latter is a normalized URL, which means that the URL is modified, and notably consecutive forward slashes are replaced with one (and a proxy request to http://example.com/ would be converted to the incorrect http:/example.com/).

If you use this Nginx config to proxy requests from the same server, e.g. using http://localhost/cors/ as a proxy at http://localhost/app/, then with the default CORS Anywhere configuration you will get the following response (error):

Missing required request header. Must specify one of: origin,x-requested-with

The reasoning behind this header requirement is explained at https://github.com/Rob--W/cors-anywhere/pull/145#issuecomment-450528241 . To avoid this error, set the X-Requested-With header from your client-side app code. Here is an example: https://github.com/Rob--W/cors-anywhere/issues/39#issuecomment-387690291