https://github.com/catamphetamine/cors-proxy-node
cors-proxy-node
https://github.com/catamphetamine/cors-proxy-node
Last synced: 3 months ago
JSON representation
cors-proxy-node
- Host: GitHub
- URL: https://github.com/catamphetamine/cors-proxy-node
- Owner: catamphetamine
- Created: 2024-04-22T10:45:02.000Z (over 1 year ago)
- Default Branch: main
- Last Pushed: 2024-05-29T18:35:06.000Z (over 1 year ago)
- Last Synced: 2025-01-11T01:48:45.436Z (12 months ago)
- Language: JavaScript
- Size: 32.2 KB
- Stars: 0
- Watchers: 1
- Forks: 0
- Open Issues: 0
-
Metadata Files:
- Readme: README.md
Awesome Lists containing this project
README
# CORS Proxy
This is a simple CORS proxy that was originally developed for [anychan](https://gitlab.com/catamphetamine/anychan) web application.
Based on [`cors-anywhere`](https://github.com/Rob--W/cors-anywhere) with some changes.
## Use
Create a new folder. Go into it. Initialize a new Node.js project in it:
```
npm init
```
Call your project any name. Answer the questions it asks.
After it finishes setting up the project, install `cors-proxy-node` dependency:
```
npm install cors-proxy-node --save
```
Create a new file `index.js`:
```js
import corsProxy from 'cors-proxy-node'
corsProxy({
host: '0.0.0.0',
port: 8080
})
```
In `package.json`, add a new `script` called `start`:
```js
"scripts": {
"start": "node index.js"
}
```
Start the proxy using the command:
```
npm start
```
To proxy a URL through the CORS proxy, one could send an HTTP request to:
* `/`
* `/?url=`
For example, if `host` is set to `"0.0.0.0"` and `port` is set to `8080`, then to proxy `https://google.com` URL through the CORS proxy, one could send an HTTP request to:
* `http://my-cors-proxy.com:8080/https://google.com`
* `http://my-cors-proxy.com:8080/?url=https%3A%2F%2Fgoogle.com`
## Configuration
Configuration is very simple and should be specified in `config.json` file.
* `host: string` — The hostname to listen on. The simplest value that always works is [`"0.0.0.0"`](https://www.howtogeek.com/225487/what-is-the-difference-between-127.0.0.1-and-0.0.0.0/) which means "listen on all possible host names for this host". This parameter is ignored when `HOST` environment variable is set.
* `port: number` — The port to listen on. Example: `8080`. This parameter is ignored when `PORT` environment variable is set.
* `fromOriginWhitelist?: string[]` — An explicit "whitelist" of allowed HTTP origins to accept proxy requests from. If this configuration parameter is specified then only those HTTP origins will be allowed to send HTTP requests to this proxy server. Otherwise, all incoming HTTP requests are allowed, regardless of the HTTP origin they came from.
* `toOriginWhitelist?: string[]` — An explicit "whitelist" of allowed HTTP origins to accept proxy requests towards. If this configuration parameter is specified then any incoming HTTP requests towards those destination origins are allowed, regardless of the `fromOriginWhitelist` setting.
* `cookies?: boolean` — Set to `true` to enable cookies. Cookies are disabled by default. Enabling cookies requires setting both `fromOriginWhitelist` and `shareCookiesBetweenOriginsInFromOriginWhitelist` parameters. Enabling cookies is required when calling [`fetch()`](https://developer.mozilla.org/en-US/docs/Web/API/Fetch_API/Using_Fetch) with `credentials: "include"` parameter.
* `shareCookiesBetweenOriginsInFromOriginWhitelist?: boolean` — An explicit "opt-in" flag that is required to be set to `true` when enabling cookies. The only purpose of this flag is to make it explicit that, when enabled, cookies are shared between all originas in `fromOriginWhitelist` because not everyone realizes that. I myself didn't realize it.
### Request Headers
#### `x-cookie`
Web browsers [don't allow](https://developer.mozilla.org/en-US/docs/Web/API/Headers/getSetCookie) client-side javascript code to set the value of the `cookie` header of an HTTP request. To work around that, there's an `x-cookie` header: if specified, the contents of `x-cookie` request header will be appended to the `cookie` request header using `"; "` as a separator. This is a way to add any additional cookies to a proxied HTTP request.
#### `x-set-cookies`
Web browsers [don't expose](https://developer.mozilla.org/en-US/docs/Web/API/Headers/getSetCookie) `set-cookie` headers of an HTTP response to client-side javascript code. To work around that limitation and see what cookies exactly have been set by the server, one could pass an HTTP request header called `x-set-cookies` with value `true`. In that case, the HTTP response is gonna contain a header called `x-set-cookies` whose value is gonna be a stringified JSON array of all `set-cookies` headers' values, if there were any in the server's response.
Trivia: There can be several `set-cookie` headers in a given HTTP response: one for each cookie. That's how it's defined in the HTTP specification.
#### `x-redirect-status`
When specified, replaces status `30x` in HTTP response with the value of this header. This allows to bypass the weird behavior of the [`fetch()`](https://developer.mozilla.org/en-US/docs/Web/API/Fetch_API/Using_Fetch) function: otherwise, when it receives HTTP response status `302` in CORS mode, it doesn't allow the application to look into the response details and instead sets `response.status` to `0` and `response.headers` to empty headers. [Issue](https://github.com/denoland/deno/issues/4389). Replacing response status `302` with something else like `200` allows a developer to bypass that weird behavior and examine the status and headers of the response.
#### `x-follow-redirect`
Redirects are automatically followed unless the request header `x-follow-redirect` is explicitly set to `false`.
When automatically "following" a chain of redirects, it must concatenate all `set-cookie` response headers in the chain and output the result in `set-cookie` header of the final response.
### Respose Headers
#### `x-set-cookies`
See the description of the `x-set-cookies` request header.
#### `x-redirect-status`
When passing `x-redirect-status` header in request to override a redirect status, in case of a redirect, it will add an `x-redirect-status` header in response with the value of the original response status (before the override).
#### `x-redirect-n`
For debugging purposes, each followed redirect results in the addition of an `x-redirect-n` response header, where `n` starts at `1`. The value of each such header is comprised of the redirect status code and the redirect URL separated by a whitespace.
After 5 redirects, redirects are not followed any more. The redirect response is sent back to the browser, which can choose to follow the redirect (handled automatically by the browser).
#### `x-request-url`
The requested URL.
#### `x-final-url`
The final URL, after following all redirects.
## Hosting
### An example of setting up a free CORS proxy at Vercel
[Original article](https://geshan.com.np/blog/2021/01/free-nodejs-hosting/)
* Create a repo on GitLab or GitHub with the contents of the proxy folder.
* Create `vercel.json` file in the repo. It sets up Vercel hosting for the repo:
```js
{
"version": 2,
"name": "nodejs-mysql",
"builds": [
{ "src": "index.js", "use": "@vercel/node" }
],
"routes": [
{ "src": "/(.*)", "dest": "/index.js" }
]
}
```
* Push the changes to the repo.
* Login to [Vercel](https://vercel.com/) using your GitLab or GitHub account.
* Click "Add New" → "Project".
* Choose "GitLab" or "GitHub".
* Find the repo in the list and click the "Import" button next it.
* After the project has been deployed, it will show the website URL for it. Use it as a proxy server URL. Example: `https://my-cors-proxy.vercel.app?url={urlEncoded}`.
## Restrictions
To prevent the use of the proxy for casual browsing, the proxy requires one of the following request headers to be present:
* `origin`
* `x-requested-with`
## Stats
There's a basic "stats" page available at `/stats` URL. It displays a list of the most recent requests to the proxy: date, time, user subnet's IP address hash (in a form of a single unicode character) and the proxied URL.
When running in a containerized environment like Vercel, the proxy instance might be stopped when it doesn't receive incoming HTTP requests and then started again when an incoming HTTP request arrives. Any stats will be naturally cleared during such restart.