見出し画像

[Python] Flaskアプリケーション開発 APIエンドポイント開発

APIとは

WebアプリケーションではURLのことをAPI(アプリケーションインターフェース)とも呼びます。

インタフェースとは何が接するところという意味です。
キーボードはコンピュータと人間の入力が接するインターフェースですし、ディスプレイもコンピュータと人間の視覚情報が接するインターフェースです。

Webブラウザとアプリケーションを繋げるのがURL(APIエンドポイント)になります。

例えばnoteではURLに応じて返ってくる画面が異なります
・note.com           → noteのトップページ
・note.com/notes         → 自分の作成記事の一覧
・note.com/notes/purchased    → 自分の購入記事の一覧

noteというアプリケーションでは、URL(各APIエンドポイント)に対応して、異なる処理をしているわけです。

では、Flask を使ったアプリケーションで、どのようにAPIエンドポイントを作成して、異なる処理をさせるか、みていきましょう。

もう少し厳密に説明すると
WebブラウザとWebサーバーアプリケーションはHTTPという規約に従って通信しています。
WebブラウザはHTTPリクエストをURLに対して送信し、Webサーバーアプリケーションは受信したリクエストに対してHTTPレスポンスを返信します。
そして、Webブラウザはレスポンスを解釈して画面として表示します。

APIエンドポイントの追加

前回のFlaskアプリケーションのサンプルコードに対して
APIエンドポイントを追加します。

# hello.py
from flask import Flask

app = Flask(__name__)

@app.route('/')
def index():
   return '<h1>Hello World!</h1>'

# 追加コード   
@app.route('/greeting')
def greeting():
   return '<h1>こんにちは!</h1>'

アプリケーションを起動して(デバックモードがONになっていれば、リロードされているはず)今度はhttp://127.0.0.1:5000/greetingにアクセスしてみましょう

画像1

http://127.0.0.1:5000/ とは違う画面が表示されました

curlで確認

コマンドラインから簡単にHTTPリクエストを投げられるcurlを使っても確認してみましょう

> curl http://127.0.0.1:5000/
<h1>Hello World!</h1>

> curl http://127.0.0.1:5000/greeting
<h1>こんにちは!</h1>

routeとview関数

@app.routeについて説明します。
app.route('/パス名')でURLとview関数を結びつけています。

@app.route('/')
def index():
   return '<h1>Hello World!</h1>'
   
@app.route('/greeting')
def greeting():
   return '<h1>こんにちは!</h1>'
/(ルート)にアクセス → index()を実行
/greeting   にアクセス→ greeting()を実行

routeデコレータを使用してURLとview関数を結びつけると
特定のURLにアクセスに対応して、特定のレスポンスを返すことができます


動的なAPIエンドポイント

route()に渡すURL文字列に<変数名>のようにすることで、URLに変数を追加し、view関数で受け取ることができます。
同じview関数で変数部分に対応したレスポンスを返すことができます。
以下のコードを追加して動作確認してみましょう

@app.route('/user/<name>')
def user(name):
   return f'こんにちは {name}さん!'
> curl http://127.0.0.1:5000/user/Bob
こんにちは Bobさん!

> curl http://127.0.0.1:5000/user/Alice
こんにちは Aliceさん!

URLの<name>に応じて異なるレスポンスが返ってきました!

動的なAPIエンドポイントの実用例

上記のエンドポイントはあまり実用的でない例ですが、実際のアプリケーションでは、<変数>にIDなどを指定して、データベースからIDのデータを取得して返すことが多いです。

@app.route('/users/<user_id>')
def user(user_id):
   user = get_user_from_database(user_id) # データベースからユーザ情報を取得
   
   # userがいない場合、ステータスコード404(not found)を返す
   if user is not None:
       abort(404)
   
   return {'id': user.id, 'name': user.name, 'age': user.age}

HTTPメソッドを処理するAPIエンドポイント

HTTPではリソースに対して実行したいアクションをHTTPメソッドとして定義しています。今まで作成したAPIはURLリソースを取得するGETメソッドの例でした。
リソースに対してのアクションとしては他にも、リソース作成(たとえば新しいブログ投稿など)、リソース更新(ブログ編集)、リソース削除(ブログ削除)などがあります。
これらはCRUD(create, read, update, delete)と呼ばれ、対応するHTTPメソッドとしてPOST, GET, PUT, DELETEが定義されています。

routeデコレータで指定したURLはデフォルトでGETメソッドしか受け取れません。GET以外のHTTPメソッドを処理するにはmethods引数を使用する必要があります。methods引数を指定して、HTTPメソッドごとにレスポンスするview関数を定義してみましょう

@app.route('/method', methods=['GET'])
def method():
    return 'GETメソッド'

@app.route('/method', methods=['POST'])
def method():
    return 'POSTメソッド'
    
@app.route('/method', methods=['PUT'])
def method():
    return 'PUTメソッド'

HTTPメソッドごとにリクエストしてみます

# curl -X メソッド URL でHTTPメソッドごとに同じURLにアクセス
> curl -X GET http://127.0.0.1:5000/method
GETメソッド

> curl -X POST http://127.0.0.1:5000/method
POSTメソッド

> curl -X PUT  http://127.0.0.1:5000/method
PUTメソッド

# DELETEメソッドを受け付けるAPIはないためエラーが返ってくる
> curl -X DELETE http://127.0.0.1:5000/method
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2 Final//EN">
<title>405 Method Not Allowed</title>
<h1>Method Not Allowed</h1>
<p>The method is not allowed for the requested URL.</p>

 ​methods引数で受け付けるHTTPメソッドを指定することで、URL(リソース)に対して実行したいアクション(HTTPメソッド)ごとにAPIを提供することができるようになりました。

APIを設計する際には、URLを中心としたHTTPメソッドごとにAPIを提供するRESTと呼ばれる設計原則に基づくとシンプルで良い設計になるされています

今回学んだこと

・FlaskアプリケーションにおけるURL(APIエンドポイント)の作成方法
・エンドポイントとview関数の関係
・動的なエンドポイントの作成方法
・HTTメソッドごとにAPIを定義する方法


参考
クイックスタート経路設定
HTTP リクエストメソッド
0からREST APIについて調べてみた



この記事が気に入ったらサポートをしてみませんか?