LoginSignup
6
9

More than 5 years have passed since last update.

Redmine APIでPOST/PUTリクエストメソッドを送信できない時の(強引な)対処方法

Last updated at Posted at 2017-11-01

Redmineが好き過ぎてRedmineを題材にしたファンタジー小説書いてる8amjpです。

Redmine API

さて、Redmineは素晴らしいツールなんですが、画面がちょっと無機質で、初心者には取っ付きにくい……という印象があります。
そこで私は、もう少し取っ付きやすい画面を提供するため、Angularを使ってRedmine API経由でチケットの情報にアクセスするWebクライアントアプリを作ろうと考えました。
このRedmine API、とっても便利なんですよ。AngularのHTTPモジュールからGETメソッドでアクセスすれば、チケットの情報をJSONやXMLの形式で自由自在に取得できます。
さらには、POSTメソッドやPUTメソッドを使えば、チケットの作成や更新も簡単に……

……できないんですよ。
Redmine APIに、Chrome等のWebブラウザからPOST/PUTメソッドでリクエストを送信すると、必ずエラーになります。
えー。これじゃ読み取り専用じゃないですか。なんで?

なぜエラーになるのか

勉強してみましたよ。もう。

えーと、Redmine APIにアクセスする時など、別ドメインへのリクエストは、セキュリティ上の理由で厳しいルールが課せられます。
そのルールを規定したのがCross-Origin Resource Sharing、略してCORSと呼ばれるものです。
で、「シンプルではない」リクエスト(PUT等)の送信時は、安全性を確認するため、事前にOPTIONSメソッドでリクエストを送信し、正常な応答があれば続けてPUTメソッドを送信します。
これをプリフライトリクエストといって…………

と、頭の痛くなるような(でもセキュリティ上とても大事な)ルールに縛られながら、リクエストを送るわけなんですが。ここで大問題が発生です。

まず、ChromeやFirefoxといった主要なWebブラウザは、必ずプリフライトリクエストを送信します。仕様です。簡単にはオフにできません。
で、Redmine APIでは、このプリフライトリクエストに応答する術がありません。必ず404エラーを返します。
結果、POSTもPUTもできません。

どうせえっちゅうんだよーー!!
インターネットに公開されたサーバーでならわかるけどよー! イントラの内部でくらい自由にやらせてくれよーー!!
畜生めー!! ちくしょうめーーー!!!

解決方法

というわけで、Apacheにこの怒りをぶつけてやりましょう。
/apps/redmine/conf/ディレクトリにあるhttpd-app.confの末尾に、下記を追記します。

Header always set Access-Control-Allow-Origin "*" 
Header always set Access-Control-Allow-Methods "OPTIONS, PUT" 
Header always set Access-Control-Max-Age "60" 
Header always set Access-Control-Allow-Headers "Content-Type, X-Redmine-API-Key" 
RewriteEngine On 
RewriteCond %{REQUEST_METHOD} OPTIONS 
RewriteRule ^(.*)$ $1 [R=200,L] 

これでPOSTもPUTも送信し放題。いやー、嬉しくて何度POST/PUTしたことやら。

詳しいことはさっきのMDNのページに書いてありますが、一応さらりと解説しておきますね。

1行目は、どのドメインからのアクセスを許可するかを指定します。
ワイルドカードを指定すればすべてのアクセスを受け付けますが、セキュリティの事を考えるとちゃんと指定すべきです。わかっちゃいるけど。
2行目は、どのメソッドを許可するかを指定します。GET/HEAD/POSTメソッドは既に許可されてるっぽいので、OPTIONSとPUTメソッドを追加で指定します。
3行目は、プリフライトリクエストの有効期間です。とりあえず60秒にしました。深い根拠はありません。
4行目は、どのリクエストヘッダを許可するかを指定します。Redmine APIでは「Content-Type」と「X-Redmine-API-Key」ヘッダは必須なので、それを指定しています。
5-7行目は、OPTIONSメソッドのリクエストがあったらオウム返しにステータスコード200を返します。ゆるゆる門番。

これで、長らく頭を悩ませていた問題Issueが、力技とは言えやっと解決Resolvedになりました。良かった良かった。
ま、解決できたのは、本家Redmineサイトのフォーラム内のこの記事のおかげなんですけどね。ありがとうございます。

おわりに

「わざわざこんな事しなくても、こうすれば簡単にPOST/PUTできるよー」などという情報を御存知でしたらぜひ教えてください。

6
9
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
6
9