LoginSignup
5

More than 5 years have passed since last update.

Flaskがazure API AppsでRESTfulにできない

Last updated at Posted at 2017-09-14

はじめに

とにかくかんたんなWeb APIアプリケーションを書くのに、pythonは非常にお手軽。
このお手軽さに乗っかっていて、しかもpath routingも簡単にできるフレームワークがFlask。Azure App ServiceでAPI Appsをpythonで書く場合のサンプルもFlaskで用意されている
自分は仕事としてはjavaのほうがメインなんだけど、ほとんどの言語を制約されないプログラムはpythonで書いていて、同じノリでAPI AppsにFlask使ったAPIをデプロイしたら、これがうまく動かない。

問題点と対策

事象

何が動かなかったかというと、Flaskの@app.route()が動かなかった。
正確には、@app.route("/")は動くけど、@app.route("/user/<id>/status")みたいなやつが動かない。GET /user/1/status HTTP/1.1がIIS(?)の404で帰ってくる。
これは、何がまずいかというと、(多分だけど)Web AppsはIISがフロントに上がっていてpythonのFlaskにディスパッチしているところが、デフォルトでは"/"だけがFlaskに渡されていて、/user/1/statusみたいなパスは対象外になっているためだと思う1

方針

これがjavaなら、url-patternでどのServletに処理させるかをWeb Application Containerに登録して実現しているところで、cgiならHTTP ServerがRequest Handlerでマッピングを取ってるところ。なので、Web Appsに動き方を教えてあげてるところだろう、という想像がつく。
Azure App Service Web Apps による Python の構成によると、

サーバーによる要求の処理方法を指定するには、web.config ファイルを作成する必要があります。
リポジトリに web.x.y.config ファイルがある場合は (ここでは x.y は選択した Python ランタイム)、Azure が適切なファイルを web.config として自動的にコピーします。

とある。今回はpython3.4で実行しようとしてたので、web.3.4.configになにかしてやればよさそう。

解決策

まず、これを読んで実装してセキュリティがずるずるになっても責任は取れないから、問題ない内容かちゃんと各自で判断してくださいね(棒読み)

で、やり方なんですが、先ほどの記事にある通り、

web.3.4.config
<?xml version="1.0"?>
<configuration>
  <appSettings>
    <add key="WSGI_ALT_VIRTUALENV_HANDLER" value="app.wsgi_app" />
    <add key="WSGI_ALT_VIRTUALENV_ACTIVATE_THIS"
         value="D:\home\site\wwwroot\env\Scripts\python.exe" />
    <add key="WSGI_HANDLER"
         value="ptvs_virtualenv_proxy.get_venv_handler()" />
    <add key="PYTHONPATH" value="D:\home\site\wwwroot" />
  </appSettings>
  <system.web>
    <compilation debug="true" targetFramework="4.0" />
  </system.web>
  <system.webServer>
    <modules runAllManagedModulesForAllRequests="true" />
    <handlers>
      <remove name="Python27_via_FastCGI" />
      <remove name="Python34_via_FastCGI" />
      <add name="Python FastCGI"
           path="handler.fcgi"
           verb="*"
           modules="FastCgiModule"
           scriptProcessor="D:\Python34\python.exe|D:\Python34\Scripts\wfastcgi.py"
           resourceType="Unspecified"
           requireAccess="Script" />
    </handlers>
    <rewrite>
      <rules>
        <rule name="Static Files" stopProcessing="true">
          <conditions>
            <add input="true" pattern="false" />
          </conditions>
        </rule>
        <rule name="Configure Python" stopProcessing="true">
          <match url="(.*)" ignoreCase="false" />
          <conditions>
            <add input="{REQUEST_URI}" pattern="^/static/.*" ignoreCase="true" negate="true" />
          </conditions>
          <action type="Rewrite" url="handler.fcgi/{R:1}" appendQueryString="true" />
        </rule>
      </rules>
    </rewrite>
  </system.webServer>
</configuration>

になっていれば、ちゃんと@app.route("/user/<id>/status")みたいなroutingも機能するもよう2
<system.webServer>ほげほげほげ</system.webServer>の中の<rule name="Configure Python" stopProcessing="true">~</rule>ほうの定義がURLパターンを引っ掛けてpythonに渡そうとしているっぽいけど、動作は改めて調べようかと。
多分、IISのドキュメント読めば動作が分かるんだとおもうのだけれど。


  1. ログの見方もわかんないくらいazure App Service初心者なのだけど、ゴーストがそう囁く。 

  2. 当然ながら、静的コンテンツもFlaskにハンドルされる可能性があることを考慮する必要があります。 

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
5