111 lines
3.4 KiB
Markdown
111 lines
3.4 KiB
Markdown
|
+++
|
||
|
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'
|
||
|
```
|
||
|
|