haskell-jp / questions #97 at 2021-07-01 14:58:14 +0900

どなたかservant-elmを使っている方はいらっしゃいますでしょうか?

servant-elmで生成したelmのエンコーダ、デコーダを使ってlocalhostでやりとりをしようとしていて困ったことがありました。

まず、servantで書いたサーバ側のURLが でelmで書いたクライアント側が なので、CORSが働いてうまく作用しないことがわかりました。(WebブラウザはSafariです)
そこで、サーバ側のHaskellコードでwai-corsライブラリを使ってCORSの設定としてSimpleCorsResoucePolicyを設定したところ、
GETメソッドは通るようになりましたが、なぜかPOSTメソッドが通らず、
Preflight response is not successful
XMLHttpRequest cannot load http://localhost:8080/xxx due to access control check
とエラーメッセージが表示されてどう対処していいのか分からない状態です。

一応、サーバにターミナルのcurlコマンドで直接アクセスするとPOSTメソッドもうまくいくので、サーバ内部で発生したエラーではなさそうです。
原因はおそらくCORS回りだと思うのですが、SimpleCorsResoucePolicyは"GET", "HEAD", "POST"メソッドを許容するような設定のはずなので、GETだけうまくいってPOSTがうまくいかない理由が分からないです。

何かアドバイスいただけないでしょうか?
僕はよく、Elm で生成した JS (と、その JS が操作するようの HTML)を Servant から返すようにしてます。なので、CORS の問題がないです。
(直接の解決になってないと思いますが。。。)
返答ありがとうございます。
なるほど、そういう回避手段もあるのですね。

ただ、せっかくここまで来たので、Elmで作成したサイトからアクセスできればなと考えています。
(servant-elm使っていません)
推測ですみませんが、POSTのときはrequest header増えてたりしませんか?
↑すみません、ちょっと修正します
返信ありがとうございます。
request headerをちゃんと理解していないのですが、自動生成されたエンコーダのheadersは空列になっているので、何も指定していないと思います。
これはGETも同様です。
Elmコードで申し訳ないですが、servant-elmによって自動生成されたものがこれです。
(関数名も自動生成なのでちょっと変ですが、そこは多めにみてください)
curlはブラウザーじゃないので、クロスオリジンかどうかは気にせず普通に通信します。普通クロスオリジンかどうかの判定をしてはじくのは通例ブラウザー自身ではないかと思います。なので、クライアント側の問題である可能性も十分あるかと
あまり正確なことを言う自信はないのですが、後できることは、開発者ツールなりFiddlerなりで、どんなリクエストヘッダーとレスポンスヘッダーが出ているか見て、ちゃんと https://developer.mozilla.org/ja/docs/Web/HTTP/CORS のルールを満たしているかチェックする、といったところでしょうか。
headersは空列になっているので、何も指定していないと思います。
igrepさんも仰ってますが、ブラウザの開発者ツールでrequest headerを確認して頂いたほうが良さそうです。
推測ですが、content-typeとか飛んでいる気がします。
ありがとうございます。
headerにcontent-typeを含んでいるものをCORSに許可したらPOSTでもちゃんと返してくれました。
Webアプリ開発は初めてだったもので、色々と知らなかった点が多いですが、皆さまのおかげでとても助かりました。
ありがとうございました。