1. Flask (フラスコ) をインストール
Linux の場合。
· コマンド pip は Windows でも同様の手順。(プロンプトは PS C:\Users\who> となる)
$ su # dnf install python3-pip -y # exit $ pip install flask flask_httpauth $ pip show flask flask_httpauth Name: Flask Version: 3.0.0 Summary: A simple framework for building complex web applications. Home-page: Author: Author-email: License: Location: /home/who/.local/lib/python3.9/site-packages Requires: click, Werkzeug, itsdangerous, Jinja2, blinker, importlib-metadata Required-by: Flask-HTTPAuth --- Name: Flask-HTTPAuth Version: 4.8.0 Summary: HTTP authentication for Flask routes Home-page: https://github.com/miguelgrinberg/flask-httpauth Author: Miguel Grinberg Author-email: miguel.grinberg@gmail.com License: Location: /home/who/.local/lib/python3.9/site-packages Requires: flask Required-by: $ which flask ~/.local/bin/flask $ flask --version Python 3.9.16 Flask 3.0.0 Werkzeug 3.0.1
· コマンド which は Windows には存在しない。
· コマンド flask は Windows 版にも存在し、
%USERPROFILE%\AppData\Local\Packages\PythonSoftwareFoundation.Python.3.11_不定文字列\LocalCache\local-packages\Python311\Scripts\flask.exe
をフルパスで指定すれば使えるが、ふつーはそこまでやらない。
2. 実装
2-1. GET で待ち受け
参照: 公式 Web ページのサンプル
*1 Flask をフロントエンドに使用せず、リバースプロキシ (waitress, gevent, nginx, Apache 等) の裏で使えと警告されている。
$ python << EOF from flask import Flask, request from markupsafe import escape app = Flask(__name__) @app.route('/', methods=['GET']) # methods=['GET','POST'] のように指定可能。省略すると GET のみになる。 def hello(): name = request.args.get('name', 'world') return f'Hello, {escape(name)}.\n' app.run(host='127.0.0.1', port=8080) # port は指定なしだと 5000 で待ち受ける。 EOFここから下はアクセスログが表示される。Ctrl + C で終了。
* Serving Flask app '<stdin>' * Debug mode: off WARNING: This is a development server. Do not use it in a production deployment. Use a production WSGI server instead. 警告: これは開発サーバです。本番環境で使用してはいけません。代わりに WSGI サーバを使用してください。*1 * Running on http://127.0.0.1:8080 Press CTRL+C to quit 127.0.0.1 - - [22/Dec/2023 15:26:07] "GET / HTTP/1.1" 200 - --- 下記 A の証跡 127.0.0.1 - - [22/Dec/2023 15:26:19] "GET /?name=Flask HTTP/1.1" 200 - --- 下記 B の証跡
(Flask はバージョン 1.0 からマルチスレッドがデフォルトだけど、内蔵の Werkzeug がサービスじゃないからか?)
別ウィンドウで動作テスト (GET)
$ curl localhost:8080 # --- A Hello, world. $ curl localhost:8080/?name=Flask # --- B Hello, Flask.
PoorShell だとこんな感じ。
*2なぜか PowerShell はリダイレクトとファイル出力でエンコードの指定方法が異なる。
>_ Windows PowerShell
Windows PowerShell Copyright (C) Microsoft Corporation. All rights reserved. 新しいクロスプラットフォームの PowerShell をお試しください https://aka.ms/pscore6 # Python で読み込むためリダイレクトの文字コードを UTF8 にする。*2 PS C:\Users\who> $OutputEncoding = [System.Text.Encoding]::GetEncoding('utf-8') PS C:\Users\who> @" from flask import Flask, request from markupsafe import escape app = Flask(__name__) @app.route('/', methods=['GET']) def hello(): name = request.args.get('name', 'world') return f'Hello, {escape(name)}.\n' app.run(host='127.0.0.1', port=8080) "@ | python
* Serving Flask app '<stdin>' * Debug mode: off WARNING: This is a development server. Do not use it in a production deployment. Use a production WSGI server instead. * Running on http://127.0.0.1:8080 Press CTRL+C to quit 127.0.0.1 - - [22/Dec/2023 15:30:19] "GET / HTTP/1.1" 200 - 127.0.0.1 - - [22/Dec/2023 15:30:48] "GET /?name=Flask HTTP/1.1" 200 -
別ウィンドウで動作テスト (GET)
コマンド長すぎ、センスダサすぎ。Microsoft は、この REPL が使いやすいと本気で思っているのだろうか。
>_ Windows PowerShell
Windows PowerShell Copyright (C) Microsoft Corporation. All rights reserved. 新しいクロスプラットフォームの PowerShell をお試しください https://aka.ms/pscore6 PS C:\Users\who> iwr http://localhost:8080 | select Content | ft -Wrap Content ------- Hello, world. PS C:\Users\who> iwr http://localhost:8080/?name=Flask | select Content | ft -Wrap Content ------- Hello, Flask. PS C:\Users\who>
登録済みの短縮名
· iwr : Invoke-WebRequest
· select : Select-Object
· ft : Format-Table
2-2. BASIC 認証で待ち受け
$ python << EOF from flask import Flask, request from markupsafe import escape from flask_httpauth import HTTPBasicAuth members = { 'user1':'pass', 'user2':'word', } app = Flask(__name__) auth = HTTPBasicAuth() @auth.get_password def member_auth(name): return members.get(name) # 平文のパスワードを返す。該当がなければ None を返す。 @app.route('/') @auth.login_required def hello(): name = auth.username() return f'Hello, {escape(name)}.\n' app.run(host='127.0.0.1', port=8080) EOF
* Serving Flask app '<stdin>' * Debug mode: off WARNING: This is a development server. Do not use it in a production deployment. Use a production WSGI server instead. * Running on http://127.0.0.1:8080 Press CTRL+C to quit 127.0.0.1 - - [22/Dec/2023 15:31:07] "GET / HTTP/1.1" 401 - 127.0.0.1 - - [22/Dec/2023 15:31:17] "GET / HTTP/1.1" 401 - 127.0.0.1 - - [22/Dec/2023 15:31:23] "GET / HTTP/1.1" 200 -
別ウィンドウで動作テスト (BASIC 認証)
$ curl localhost:8080 Unauthorized Access --- 不許可。 $ curl user1:word@localhost:8080 Unauthorized Access --- 不許可。 $ curl user1:pass@localhost:8080 Hello, user1. --- 許可された。
2-3. POST で待ち受け
$ python << EOF from flask import Flask, request app = Flask(__name__) @app.route('/', methods=['POST']) # methods= はタプルにできない。 def post(): values = {} names = request.form.keys() for name in names: values[name] = request.form[name] return values app.run(host='127.0.0.1', port=8080) EOF
* Serving Flask app '<stdin>' * Debug mode: off WARNING: This is a development server. Do not use it in a production deployment. Use a production WSGI server instead. * Running on http://127.0.0.1:8080 Press CTRL+C to quit 127.0.0.1 - - [22/Dec/2023 15:42:57] "POST / HTTP/1.1" 200 - 127.0.0.1 - - [22/Dec/2023 15:43:10] "GET /?data_a=data1 HTTP/1.1" 405 -
別ウィンドウで動作テスト (POST)
$ echo 'data_a=data1&data_b=data2' | curl localhost:8080 -X POST -d @- {"data_a":"data1","data_b":"data2"} $ curl localhost:8080/?data_a=data1 <!doctype html> <html lang=en> <title>405 Method Not Allowed</title> --- GET は許可してないので弾かれた。 <h1>Method Not Allowed</h1> <p>The method is not allowed for the requested URL.</p> この方法は要求された URL で許可されていません。
PoorShell だとこんな感じ。
>_ Windows PowerShell
Windows PowerShell Copyright (C) Microsoft Corporation. All rights reserved. 新しいクロスプラットフォームの PowerShell をお試しください https://aka.ms/pscore6 # Python で読み込むためリダイレクトの文字コードを UTF8 にする。 PS C:\Users\who> $OutputEncoding = [System.Text.Encoding]::GetEncoding('utf-8') PS C:\Users\who> @" from flask import Flask, request app = Flask(__name__) @app.route('/', methods=['POST']) def post(): values = {} names = request.form.keys() for name in names: values[name] = request.form[name] return values app.run(host='127.0.0.1', port=8080) "@ | python
* Serving Flask app '<stdin>' * Debug mode: off WARNING: This is a development server. Do not use it in a production deployment. Use a production WSGI server instead. * Running on http://127.0.0.1:8080 Press CTRL+C to quit 127.0.0.1 - - [22/Dec/2023 16:00:36] "POST / HTTP/1.1" 200 -
別ウィンドウで動作テスト (POST)
コマンド長すぎ、センス··· (省略)。
>_ Windows PowerShell
Windows PowerShell Copyright (C) Microsoft Corporation. All rights reserved. 新しいクロスプラットフォームの PowerShell をお試しください https://aka.ms/pscore6 PS C:\Users\who> echo "data_a=data1&data_b=data2" | iwr -Method POST http://localhost:8080 | select Content | ft -Wrap Content ------- {"data_a":"data1","data_b":"data2"} PS C:\Users\who>
2-4. 動的 URL で待ち受け
$ python << EOF from flask import Flask from markupsafe import escape app = Flask(__name__) @app.route('/function/<name>') # --- C def function(name): return f'Function {escape(name)}\n' @app.route('/function/<name>/') # --- D def directory(name): return f'Directory {escape(name)}\n' @app.route('/function/<name>/<func>') # --- E def dir_and_func(name,func): return f'Directory,Function {escape(name)},{escape(func)}\n' app.run(host='127.0.0.1', port=8080) EOF
* Serving Flask app '<stdin>' * Debug mode: off WARNING: This is a development server. Do not use it in a production deployment. Use a production WSGI server instead. * Running on http://127.0.0.1:8080 Press CTRL+C to quit 127.0.0.1 - - [22/Dec/2023 16:06:36] "GET /function/aaa HTTP/1.1" 200 - 127.0.0.1 - - [22/Dec/2023 16:06:41] "GET /function/bbb HTTP/1.1" 200 - 127.0.0.1 - - [22/Dec/2023 16:06:47] "GET /function/ccc/ HTTP/1.1" 200 - 127.0.0.1 - - [22/Dec/2023 16:06:55] "GET /function/ccc/ddd HTTP/1.1" 200 - 127.0.0.1 - - [22/Dec/2023 16:07:03] "GET /function/ccc/ddd/ HTTP/1.1" 404 -
別ウィンドウで動作テスト (動的 URL)
$ curl localhost:8080/function/aaa Function aaa --- 定義に適合した。(上記 C) $ curl localhost:8080/function/bbb Function bbb --- 定義に適合した。(上記 C) $ curl localhost:8080/function/ccc/ Directory ccc --- 定義に適合した。(上記 D) $ curl localhost:8080/function/ccc/ddd Directory,Function ccc,ddd --- 定義に適合した。(上記 E) $ curl localhost:8080/function/ccc/ddd/ <!doctype html> <html lang=en> <title>404 Not Found</title> --- 適合する定義が無かった。 <h1>Not Found</h1> <p>The requested URL was not found on the server. If you entered the URL manually please check your spelling and try again.</p> 要求された URL がサーバ上に見つかりません。 URL を手動で入力した場合は、綴りを確認して再試行してください。
3. おまけ
Flask を WSGI に対応させるには、mod_wsgi が必要になる。
WSGI の導入は、こちら を参照のこと。
(Django 用の記述なので、適宜読み替えることが必要)