2023-07-08 / @syui

heroku

cors-originのerrorを回避するためのproxyを変えた

今までherokuでcors-originのerrorを回避するためにproxy-serverを立ててたんだけど、やめた。これ一つのために$7かかってた。

Access to fetch at ‘http://localhost:3000/’ from origin ‘http://127.0.0.1:8080’ has been blocked by CORS policy: No ‘Access-Control-Allow-Origin’ header is present on the requested resource. If an opaque response serves your needs, set the request’s mode to ’no-cors’ to fetch the resource with CORS disabled.

https://developer.mozilla.org/ja/docs/Web/HTTP/CORS/Errors/CORSMissingAllowOrigin

このerrorは、例えば、apiのgetが同一のurlで行われていないことが要因です。

ですから、vueなら以下のようにproxyで同一url内であることを偽装すれば回避できます。

module.exports = {
	devServer: {
		proxy: {
			"^/api*": {
				target: "https://api.example.com",
				pathRewrite: { "^/api": "" },
			}
		}
	}
}
axios
    .get("/api/test")
    //.get("https://api.example.com/test")
    .then(response => (this.data = response));

ただし、この回避方法はあくまでlocal, previewのみであり、$ yarn buildなどの./dist出力には適用されません。

これを解決する方法としては、apiにAccess-Control-Allow-Origin:"*"を設定すること、あるいはproxy-serverを立てて経由することです。

.get("https://proxy.heroku.com/https://api.example.com/test")

ent(ogent)でheaderをAccess-Control-Allow-Origin:"*"にする方法ですが、一つずつ設定していくらしい。基本的にはupdate, deleteとかは使わないのでそれ以外のところに書きます。

w.Header().Set("Access-Control-Allow-Origin", "*")
w.Header().Set("Content-Type", "application/json")

securityを考慮して特定のサイトのみを許可したほうがいいので、その場合は、vue-devserver-proxyと合わせて、以下のようにします。

func encodeReadUserResponse(response ReadUserRes, w http.ResponseWriter, span trace.Span) error {
    w.Header().Set("Access-Control-Allow-Origin", "https://example.com")
}
data () {
    return {
          api_url: null,
    }
},
mounted() {
    if (window.location.host === "localhost:8080") {
        this.api_url = "/api/";
    } else {
        this.api_url = "https://api.example.com/";
    }
    let url = this.api_url + "users";
    axios.get(url,{ crossdomain: true })
        .then(response => (this.data = response));
}

もし自前で運用するなら費用のかからないcloudflare zero-turst(tunnel)がいいと思います。

[Unit]
Description=cors service
Documentation=https://github.com/Rob--W/cors-anywhere

[Service]
Type=oneshot
RemainAfterExit=yes
WorkingDirectory=/home/syui/github/cors-anywhere
ExecStart=/usr/bin/node server.js
ExecStop=/usr/bin/pkill node
[Install]
WantedBy=default.target
$ git clone https://github.com/Rob--W/cors-anywhere
$ npm i
$ node server

$ sudo systemctl start cors
# これでAccess-Control-Allow-Originが設定されてたらok
$ curl --dump-header - 'https://api.example.com' -H 'Origin: https://example.com'