PythonのFlaskフレームワークでSERVER_NAMEドメイン名を設定するためのチュートリアル
FlaskのSERVER_NAMEは主に2つのことをします。
- アクティブなリクエスト(要求)に加えて、絶対的なURLを生成するためにFlaskを支援する(メールに埋め込まれたウェブサイトのURLなど)。
- サブドメイン対応について
この2つ以外のことができると勘違いしている人が多い。
一つ目、絶対URL
url_forはデフォルトで相対URLを生成することがわかっています。また、_externalというパラメータがあり、これをtrueに設定すると絶対URL(つまり、ドメイン名などの情報を含むHTTPの先頭)が生成されます。SERVER_NAMEが指定されない場合、デフォルトでは現在アクティブなリクエスト(request)を使ってURLが生成されます。
以下はデモの例です。
# filename myapp.py
from flask import Flask, url_for
app = Flask(__name__)
@app.route('/')
def index():
return 'hello flask'
@app.route('/test')
def test():
return url_for('index', _external=True)
if __name__ == '__main__':
app.run(debug=True)
1. [シナリオ1】ブラウザでアクセスする
アプリ実行後、ローカルで5000番ポートをリッスンします。
(env) F:\tmp>python myapp.py
* Running on http://127.0.0.1:5000/
* Restarting with reloader
ブラウザで http://127.0.0.1:5000/test にアクセスすると、返されるコンテンツは http://127.0.0.1:5000/ です。
ブラウザで http://localhost:5000/test にアクセスした場合、返されるのは http://localhost:5000/ です。
ご覧のように、SERVER_NAMEが設定されていない場合、url_forによって生成される絶対URLは要求されたURLに依存します。ブラウザからアクセスしない場合について見てみましょう。
2. [シナリオ2】ブラウザを使わないアクセス
このシナリオは、要求がない場合を指します。
これをPython Shellでシミュレーションすると、以下のようになります。
>>> from myapp import app
>>> with app.app_context():
... print url_for('index', _external=True)
...
Traceback (most recent call last):
File "<stdin>", line 2, in <module>
File "F:\tmp\env\lib\site-packages\flask\helpers.py", line 287, in url_for
raise RuntimeError('Application was not able to create a URL '
RuntimeError: Application was not able to create a URL adapter for request indep
You might be able to fix this by setting the SERVER_NAME
You might be able to fix this by setting the SERVER_NAME config variable.
上記は、アプリケーションがリクエストに関連しないURL生成のためのURLアダプタを作成できないことを意味し、これはSERVER_NAMEを設定することで解決できます。
よし、SERVER_NAMEに値を設定した上でもう一度試してみよう。
>>> app.config['SERVER_NAME'] = 'example.com'
>>> with app.app_context():
... print url_for('index', _external=True)
...
http://example.com/
追記:一般的にSERVER_NAMEはウェブサイトのドメイン名に設定されています。
Flask-Mailの関連記事の中に、こんな一節があります。
多くのFlask拡張機能は、アクティブなアプリケーションとリクエストのコンテキストで実行されていることを前提としています。Flask-Mail の send 関数は current_app コンテキストを使うので、mail.send() 関数がスレッドで実行されたときに人工的にコンテキストを作る必要があり、send_async_ app.app_context() で email でコンテキストを作っているのだそうです。
そのため、リクエストに依存しない絶対的なURLを生成する(例えば、非同期でメールを送信する際に、メール内にサイトのページのURLを生成する)には、SERVER_NAMEを設定する必要があります。
2つ目:サブドメインへの対応
SERVER_NAMEキーは、サブドメイン対応のためのものです。Flask は既存のサーバー名を知るまではサブドメイン部分を推測できないので、サブドメインを使用する場合はこのオプションが必要です。また、セッションクッキーにも使用されます。
サブドメインがわからないのはFlaskだけではなく、ブラウザにもこの問題があることを覚えておいてください。最近のウェブブラウザは、サーバー名にドットを含まないクロスサブドメインのクッキーを許可しないので、サーバー名が localhost の場合、localhost とそのすべてのサブドメインにクッキーを設定することはできません。myapplication.local」のような適切なサーバー名を選択し、サーバー名+サブドメインをホスト設定に追加するか、ローカルバインディングを設定してほしい旨を追加してください。
例
-------->http://book.muxistudio.com
||
http://muxistudio.com-------->http://blog.muxistudio.com
||
-------->http://share.muxistudio.com
1. ローカルテスト
etc/hosts ファイルを修正する
注意:ローカルテストでのみ動作します
使用する必要があるすべてのサブドメインを追加します。
127.0.0.1 flask.dev localhost # domain name
127.0.0.1 test.flask.dev localhost # subdomain
127.0.0.1 othertest.flask.dev localhost # subdomain
Flaskアプリの設定ファイルに'SERVER_NAME'を追加します。
アプリケーションの設定で、'SERVER_NAME' に指定したドメイン名とデフォルトのリスニングポートを設定します。
#...
app = Flask(__name__)
app.config['SERVER_NAME'] = 'flask.dev:5000'
#...
2. コンフィギュレーションブループリント
ブループリントのサブドメインはhostsファイルで追加したサブドメインです
#...
# Blueprint declaration
bp = Blueprint('subdomain', __name__, subdomain="<user>")
#...
# Register the blueprint into the application
app.register_blueprint(bp)
#...
3. サーバー側の設定
Flaskアプリの設定にある「SERVER_NAME」を、本番環境で登録したドメイン名に変更します。
flask.dev:5000 ----> muxistudio.com
4. Nginxの設定
リスニングポートを設定します。以下の例では、ユーザがアクセスするサブドメインを正規表現で取得しています。wwwについては、正規表現を取得した時点でフィルタリングし、ユーザーがアクセスした時点で www.yourdomain.com页面 にリダイレクトするようにしないと、wwwがサブドメインとして扱われることになります。
設定例です。
server {
listen 80;
listen 443 ssl;
ssl_certificate /usr/local/nginx/ssl/nginx.crt;
ssl_certificate_key /usr/local/nginx/ssl/nginx.key;
server_name ~^www\. (? <user>. +\.) ? markdownblog\.com$;
return 301 "$scheme://${user}markdownblog.com$request_uri";
}
server {
listen 80;
listen 443 ssl;
ssl_certificate /usr/local/nginx/ssl/nginx.crt;
ssl_certificate_key /usr/local/nginx/ssl/nginx.key;
server_name ~^. +\.markdownblog\.com$ markdownblog.com;
location / {
proxy_set_header Host $http_host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_pass http://127.0.0.1:8085;
}
}
関連
-
画像フィルターアルゴリズムコードのRuby実装
-
Rubyのデザインパターンプログラミングにおけるコマンドパターンの活用を徹底分析
-
Rubyのデザインパターン。アダプタパターン実践ガイド
-
デザインパターンのうち、ProxyパターンとDecorativeパターンを使ったRubyのコード例
-
RubyのSimple FactoryパターンとFactory Methodパターンを利用する
-
Rubyのデバッグツールruby-debug-base19のインストールと設定(Windows版
-
CentOS7でruby on railsの開発環境を構築する。
-
Ruby on Railsの基礎 - 新規プロジェクト
-
Ruby on RailsにおけるCucumberの活用を解説します。
-
Ruby on Railsのルーティング設定に関するいくつかのアドバイス
最新
-
nginxです。[emerg] 0.0.0.0:80 への bind() に失敗しました (98: アドレスは既に使用中です)
-
htmlページでギリシャ文字を使うには
-
ピュアhtml+cssでの要素読み込み効果
-
純粋なhtml + cssで五輪を実現するサンプルコード
-
ナビゲーションバー・ドロップダウンメニューのHTML+CSSサンプルコード
-
タイピング効果を実現するピュアhtml+css
-
htmlの選択ボックスのプレースホルダー作成に関する質問
-
html css3 伸縮しない 画像表示効果
-
トップナビゲーションバーメニュー作成用HTML+CSS
-
html+css 実装 サイバーパンク風ボタン
おすすめ
-
Rubyの二分探索(dichotomous search)アルゴリズムの簡単な例
-
Rubyの並列処理とグローバルロック
-
Windowsでrubyとrailsをインストールする際に発生する問題点まとめ
-
Rubyの文法と言語機能のまとめ
-
RubyおよびRuby on RailsでJSON形式のデータをパースするためのチュートリアルの例
-
RubyアプリケーションでHTTPベースのリクエストを送信する簡単な例
-
Rubyのインストールと操作
-
Rubyの4つの比較関数(equal?, eql?, ==, ===)について解説します。
-
Rubyの基本的な環境変数の設定と一般的なインタープリタコマンド
-
Rubyプログラミングにおけるアサインメント関連操作