+++ date = "2023-07-08" tags = ["heroku"] title = "cors-originのerrorを回避するためのproxyを変えた" slug = "cors" +++ 今まで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内であることを偽装すれば回避できます。 ```js:vue.config.js module.exports = { devServer: { proxy: { "^/api*": { target: "https://api.example.com", pathRewrite: { "^/api": "" }, } } } } ``` ```js:src/App.vue 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を立てて経由することです。 ```js .get("https://proxy.heroku.com/https://api.example.com/test") ``` ent(ogent)でheaderを`Access-Control-Allow-Origin:"*"`にする方法ですが、一つずつ設定していくらしい。基本的にはupdate, deleteとかは使わないのでそれ以外のところに書きます。 ```go:ent/ogent/oas_response_encoders_gen.go w.Header().Set("Access-Control-Allow-Origin", "*") w.Header().Set("Content-Type", "application/json") ``` securityを考慮して特定のサイトのみを許可したほうがいいので、その場合は、vue-devserver-proxyと合わせて、以下のようにします。 ```go:ent/ogent/oas_response_encoders_gen.go func encodeReadUserResponse(response ReadUserRes, w http.ResponseWriter, span trace.Span) error { w.Header().Set("Access-Control-Allow-Origin", "https://example.com") } ``` ```js:src/App.vue 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)がいいと思います。 ```sh:/ent/systemd/system/cors.service [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 ``` ```sh $ git clone https://github.com/Rob--W/cors-anywhere $ npm i $ node server $ sudo systemctl start cors ``` ```sh # これでAccess-Control-Allow-Originが設定されてたらok $ curl --dump-header - 'https://api.example.com' -H 'Origin: https://example.com' ```