FlaskでREST APIを構成し、jQueryのAjaxよりアクセスする方法

FlaskはPythonの軽量Webフレームワークであり、ちょっとしたWebアプリケーションやWeb APIを作るには重宝しています。最近では、RESTful APIが利用されるケースが多いですが、FlaskでもRESTful APIを作ることは容易です。しかし注意しないといけない点があるので、今回はFlaskでREST APIを構成するPythonのパッケージを紹介します。またjQueryのAjaxよりアクセスしてみましょう。

今回の構成

  • Google App Engine
  • Python 2.7
  • Flask 1.0.2

REST API

FlaskだけでもREST APIを構成できますが、Flask-RESTfulを利用するとキレイにまとめることができます。Flask-RESTfulは、Python 2.7およびPython 3.4以上に対応しています。 Flask-RESTful https://flask-restful.readthedocs.io/en/latest/ Flask-RESTfulのインストールは下記で行えます。
pip install flask-restful
使い方は簡単です。それぞれのHTTPメソッドに対してPythonのメソッドを用意します。
  • POST … post()
  • GET … get()
  • PUT … put()
  • DELETE … delete()
HTTPメソッドとPythonのメソッドが一致しているので、一目瞭然ですね。 サンプルとして次のようなコードを用意しました。main.pyを次のように修正してください。GETリクエストに対して、「Hello World」と返す内容となっています。
# coding: UTF-8
from flask import Flask
from flask_restful import Resource, Api


app = Flask(__name__)
api = Api(app)


class HelloWorld(Resource):
    def get(self):
        return {'hello': 'world'}


api.add_resource(HelloWorld, '/')
それではjQueryのAjaxからWeb APIを呼び出してみましょう。HTMLは次のように準備しました。
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Flask Test</title>
</head>
<body>

<script src="https://code.jquery.com/jquery-3.3.1.min.js"></script>
<script>
    $.ajax({
        url: 'http://127.0.0.1:8080',
        type: 'GET'
    })
        .done((data, textStatus, jqXHR) => {
            console.log(data);
        })
        .fail((jqXHR, textStatus, errorThrown) => {
            console.log(jqXHR.status);
        })
</script>
</body>
</html>
jQueryのAjaxとしては一般的な書き方です。html表示時にAjaxによりFlaskで用意したGETメソッドを呼び出しています。しかし実行するとWeb API呼び出しのタイミングで、次のようなエラーが発生しました。

CORS対応

このエラーはブラウザにおけるセキュリティによるものであり、今回の場合 HTML のあるドメインから、別のドメインにある Web APIを呼び出しているため発生しています。これを解消するには 、Web APIを配置してある Flask 側で対応するのが最も簡単です。 それでは次のパッケージを利用し、Flaskを拡張しましょう。 Flask-CORS https://flask-cors.readthedocs.io/en/latest/ Flask-CORSは、Flask-RESTfulと同じくPython 2.7およびPython 3.4以上に対応しています。 インストールは次のコマンドを利用します。
pip install flask-cors
使い方はいたって簡単です。最小でたった2行追加するだけです。次のように main.py を修正してください。
# coding: UTF-8
from flask import Flask
from flask_restful import Resource, Api
from flask_cors import CORS


app = Flask(__name__)
api = Api(app)
CORS(app)


class HelloWorld(Resource):
    def get(self):
        return {'hello': 'world'}


api.add_resource(HelloWorld, '/')
4行目と9行目が追加されただけですね。実際には、CORS対応するメソッドを選択できるなどもっと細かな設定を行うこともできます。 では再度jQueryのAjaxによりアクセスしてみましょう。 正しい結果が得られましたね。

HTTP認証

Web APIがオープンなものであれば、これまでの内容だけで問題ないですが、特定のユーザのみに提供するWeb APIであれば、ユーザ認証の方法が必要になります。もちろん、その仕組みをWeb APIで吸収することもできますが、より簡単に実装するには Flask-HTTPAuth を利用すると便利でしょう。Flask-HTTPAuthにより一般的なHTTP認証である、BASIC認証やDIGEST認証を行うことができます。Flask-HTTPAuthは対応しているPythonのバージョンが明記されていませんが、2013年より開発が進められていますので最近のバージョンには対応しているものと思われます。 ここではより一般的に利用されるBASIC認証を紹介します。ただしBASIC認証は平文で通信されるため、セキュリティ上盗聴される恐れがありますが、そのパスワードをMD5化するなどの対応を行うといいでしょう。 Flask-HTTPAuth https://flask-httpauth.readthedocs.io/en/latest/ まずは Flask-HTTPAuth をインストールします。
pip install flask-httpauth
BASIC認証の実装の仕方は、下記のとおりです。
  • パスワード取得処理
  • 認証が必要なメソッドに「@auth.login_required」を記述
具体的には、main.py を次のように修正しました。
# coding: UTF-8
from flask import Flask
from flask_restful import Resource, Api
from flask_cors import CORS
from flask_httpauth import HTTPBasicAuth


app = Flask(__name__)
api = Api(app)
CORS(app)


class HelloWorld(Resource):
    auth = HTTPBasicAuth()

    @auth.verify_password
    def verify_password(username, password):
        if (username == 'user' and password == 'pass'):
            return True
        else:
            return False

    @auth.login_required
    def get(self):
        return {'hello': 'world'}


api.add_resource(HelloWorld, '/')
一方、Ajax側もBASIC認証の対応が必要です。HTMLを次のように修正してください。
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Flask Test</title>
</head>
<body>

<script src="https://code.jquery.com/jquery-3.3.1.min.js"></script>
<script>
    $.ajax({
        beforeSend: function (xhr) {
            xhr.setRequestHeader ("Authorization", "Basic " + btoa('user:pass'));
        },
        url: 'http://127.0.0.1:8080',
        type: 'GET'
    })
        .done((data, textStatus, jqXHR) => {
            console.log(data);

        })
        .fail((jqXHR, textStatus, errorThrown) => {
            console.log(jqXHR.status);
        })
</script>
</body>
</html>
こちらもBASIC認証を行うために、AjaxにbeforeSendメソッドを追加しています。実際にはパスワードをMD5化するなどしてください。

まとめ

今回は、FlaskでREST APIを作成するために必要なパッケージを紹介しました。ただでさえ軽量なFlaskが、3つのパッケージを追加するだけでより簡単にREST APIを構築できることが判っていただけたかと思います。もちろんGoogle App Engineでも利用可能ですし、Google App Engineであれば標準でSSL対応されているのでセキュリティ面で更に安心ですね。
» エンジニア登録はこちら