【ぷよぷよ#1】GTRができるまで
まずは鉤積み
http://www.puyop.com/s/=41100001504241212445144225142114122554558442524512124512112451824512
土台に着目
土台を変形 (折り返し部分を平らにする①)
土台を変形 (折り返し部分を平らにする②)
または
土台の上に座布団が敷けるようにする
このままだと4列目の紫のせいで座布団が敷けない。
座布団が敷けるように連鎖尾を鉤積みの形から変形する。
Next step
多重折り返しを入れたり、連鎖尾を改善・追加したりする。
CORSの設定をしているはずなのにCloudFrontでCORSエラーが発生してしまう場合の対処法を調べてみた
CORSの設定をしているはずなのにエラーが発生してしまうという事象に出くわしました。
Access to XMLHttpRequest at 'https://example.com/xxx/yyy/zzz' from origin 'http://localhost:8000' has been blocked by CORS policy: Response to preflight request doesn't pass access control check: No 'Access-Control-Allow-Origin' header is present on the requested resource.
CloudFront および S3 には次のような設定をしていました。
- CloudFront のキャッシュポリシーには、マネージドポリシーの
ChachingOptimezed
をアタッチ - CloudFront のオリジンリクエストポリシーには、マネージドポリシーの
CORS-S3Origin
をアタッチ - CloudFront のレスポンスヘッダーポリシーには、マネージドポリシーの
CORS-and-SecurityHeadersPolicy
をアタッチ - S3 バケットのアクセス許可で CORS の設定を記述(内容は以下)
[ { "AllowedHeaders": [ "*" ], "AllowedMethods": [ "GET", "HEAD" ], "AllowedOrigins": [ "*" ], "ExposeHeaders": [], "MaxAgeSeconds": 3000 } ]
追記 1
検証を進めたところ、レスポンスヘッダーポリシーの CORS 設定の挙動の認識に誤りがあることがわかりました。
オーバーライド設定を OFF にする場合には、S3 バケットのアクセス許可で CORS 設定の欄を空にする必要がありました。「S3 からのレスポンスのヘッダーに項目がなかったら」ヘッダーを追加するものと思っていましたが、実際の挙動としては「S3 に CORS 設定がなかったら」ヘッダーを追加なようでした。
CloudFront のレスポンスヘッダーポリシーで、マネージドポリシーを利用して CORS 設定を行う場合には、S3 側では CORS 設定を空にする必要がありそうです。
解決策(結論)
初めに結論を書いておきます。
CloudFront のレスポンスヘッダーポリシーには、マネージドポリシーの CORS-and-SecurityHeadersPolicy
ではなく、自前で定義するカスタムポリシーを使うことにより、エラー発生を防ぐことができるようになりました。
ポイントは、Access-Control-Allow-Origin のルールでオリジンのオーバーライドを有効にすることです。マネージドポリシーの CORS-and-SecurityHeadersPolicy
ではオリジンのオーバーライドが無効になっています。
CORS エラーの再現方法
では次に、どのようなケースで初めに提示した CORS 設定でもエラーが発生してしまうのかを見ていきます。
次のような手順を踏むことで CORS エラーを再現できます。
- 対象オブジェクトのキャッシュを削除する(CloudFront > ディストリビューション > キャッシュ削除)
- 対象オブジェクトに CloudFront 経由で no-cors リクエストする
- 対象オブジェクトに CloudFront 経由で cors リクエストする
ポイントは、no-cors リクエスト時のレスポンスを CloudFront にキャッシュさせることです。このキャッシュデータに cors でアクセスを試みるとエラーが発生します。
cors と no-cors
cors リクエストと no-cors リクエストの違いは、リクエストヘッダーに Origin ヘッダー(Origin: <scheme>://<hostname>:<port>
)が含まれているか否かです。Origin ヘッダーが含まれていれば cors リクエストです。
※ 厳密には、Origin ヘッダーを含み、且つリクエスト先とリクエスト元の Origin が異なる場合に Cross Origin なリクエストとなります。
cors リクエストの送り方
ブラウザはリクエスト時に自動で Origin ヘッダーを付与する仕組みになっているので、Web アプリケーションで img タグや fetch API を通してリソースへアクセスを試みると CORS リクエストとなります。
もしくは、curl などの HTTP クライアントで Origin ヘッダーを明示的に付与することでも CORS リクエストを作成できます。
no-cors リクエストの送り方
リクエストヘッダーに Origin が含まれなければいいので、次のような方法だと no-cors リクエストになります。
- HTTP クライアントから Origin ヘッダーを付与せずにリクエストする
- ブラウザのアドレスバーに URL を直接入力してアクセスする
CORS エラーが発生する仕組み
S3 に対して no-cors リクエストが届くと、S3 はレスポンスに CORS ヘッダー(Access-Control-Allow-Origin
)を含まずにオブジェクトを返却します。CloudFront も、この CORS ヘッダーを含まないレスポンスをキャッシュします。
この状態で今度は cors リクエストが届くと、CloudFront は Access-Control-Allow-Origin
が無いレスポンスを返却します。すると、ブラウザは「CORS アクセスが許可されていないリソース」と判断し、データへのアクセスを中止します。
CORS-and-SecurityHeadersPolicy が問題?
ここで疑問となるのが、CloudFront のレスポンスヘッダーポリシーにアタッチしたはずの CORS-and-SecurityHeadersPolicy
です。
このポリシーは、S3 から返却されたレスポンスに Access-Control-Allow-Origin
ヘッダーが存在しない場合に、Access-Control-Allow-Origin: *
を付与し直してクライアントへ返却する設定になっています。
しかしながら、今回の再現手順を踏むと、どういう訳か Access-Control-Allow-Origin
が付与されないままレスポンスが返されてしまっていました。
カスタムポリシーを作成して解決する
レスポンスヘッダーポリシーは、デフォルトで準備されているマネージドポリシーの他に、自前でルールを定義して適用することもできます。
カスタムルールを作成するには次のように操作します。
[CloudFront] > [ポリシー] > [レスポンスヘッダー] > [カスタムポリシー] > [レスポンスヘッダーポリシーを作成]
内容は下記のとおりです。
詳細: 名前: My-CORS-and-SecurityHeadersPolicy クロスオリジンリソース共有(CORS): CORS を設定: ON Access-Control-Allow-Origin: All origins Access-Control-Allow-Headers: All headers Access-Control-Allow-Methods: Customize: - GET - HEAD Access-Control-Expose-Headers: なし Access-Control-Max-Age: 3000 Access-Cpntrol-Allow-Credentials: OFF オリジンのオーバーライド: ON セキュリティヘッダー: Strict-Transport-Security: 最大経過時間: 31536000 オリジンのオーバーライド: ON X-Content-Type-Options: オリジンのオーバーライド: ON X-Frame-Options: オリジン: SAMEORIGIN オリジンのオーバーライド: ON X-XSS-Protection: X-XSS-Protection: 有効 ブロック: ON オリジンのオーバーライド: ON Referrer-Policy: Referrer-Policy: strict-origin-when-cross-origin オリジンのオーバーライド: ON Content-Security-Policy: OFF
作成したら CloudFront にアタッチします。
[CloudFront] > [ディストリビューション] > [ビヘイビア] > [編集] > [レスポンスヘッダーポリシー] > [My-CORS-and-SecurityHeadersPolicy]
カスタムポリシーのアタッチが完了すると、先のエラー手順を再現しても、cors リクエスト時には Access-Control-Allow-Origin: *
ヘッダーが返却され、CORS エラーが発生しなくなりました。
もう一つの解決策(キャッシュポリシーを変更する)
今回は採用を見送りましたが、キャッシュポリシーを変更することでも CORS エラーの発生を防ぐことができます。
具体的には、キャッシュポリシーを ChachingOptimezed
から Managed-Elemental-MediaPackage
に変更するという方法です。
Managed-Elemental-MediaPackage
はキャッシュキーとして Origin ヘッダーを含む設定になっています。要するに、リクエスト元の Origin が異なればキャッシュにはヒットせず S3 へのリクエストが発生するということです。
この挙動のおかげで、Access-Control-Allow-Origin ヘッダーを含まない no-cors リクエスト(Origin: なし)の結果を CloudFront がキャッシュしたとしても、次に cors リクエストを送った場合にはこのキャッシュにはヒットせず、Access-Control-Allow-Origin ヘッダーを含む新たなレスポンスを取得することが可能になります。
ただし、この挙動だと複数ドメインからリソースを取得するようなケースでキャッシュヒット率が低くなってしまいます(localhost
, www.example.com
, admin.example.com
など複数 Origin からアクセスする場合)。
こういった理由で、今回はこの方法は採用を見送りました。
Apache / mod_wsgi / virtualenv で Python / Flask アプリケーションを動かしてみた【EC2 / Amazon Linux 2】
Apach, mod_wsgi で Flask アプリケーションを動かしてみたのでその記録です。Python の実行環境として仮想環境を作成する方針で進めていきます。
作業手順
WIP
作業ログ
# ------------------------------------------------------------ # Apacheのデフォルトページを表示する # ------------------------------------------------------------ # rootユーザーで作業 sudo su - # タイムゾーンの設定 date timedatectl status timedatectl set-timezone Asia/Tokyo # Apacheのインストール yum list installed yum list installed | grep httpd yum -y install httpd httpd-devel httpd -v yum info httpd # Apacheの起動・停止・ステータス service httpd start service httpd status service httpd stop service httpd restart # ログの確認 tail -f -n 10 /etc/httpd/logs/access_log tail -f -n 10 /etc/httpd/logs/error_log # ここで http://<EC2のパブリックIP>:80/ にアクセスして確認する # ------------------------------------------------------------ # 最小構成のWSGIアプリケーションでHello World # ------------------------------------------------------------ # Pythonの依存モジュールのインストール yum -y install \ git \ gcc \ make \ zlib-devel \ bzip2 \ bzip2-devel \ readline \ readline-devel \ sqlite \ sqlite-devel \ openssl \ tk-devel \ libffi-devel \ xz-devel \ openssl-devel # pyenvのインストール git clone https://github.com/pyenv/pyenv.git /usr/local/pyenv (cd /usr/local/pyenv/ && src/configure && make -C src) echo 'export PYENV_ROOT="/usr/local/pyenv"' >> /etc/profile.d/pyenv.sh echo 'command -v pyenv >/dev/null || export PATH="$PYENV_ROOT/bin:$PATH"' >> /etc/profile.d/pyenv.sh echo 'eval "$(pyenv init - --no-rehash)"' >> /etc/profile.d/pyenv.sh exec $SHELL -l which pyenv # Pythonのインストール pyenv install 3.9.16 pyenv global 3.9.16 python --version which python # poetryのインストール curl -sSL https://install.python-poetry.org | POETRY_HOME=/usr/local/poetry python3 - echo 'export POETRY_HOME="/usr/local/poetry"' >> /etc/profile.d/poetry.sh echo 'export PATH="$POETRY_HOME/bin:$PATH"' >> /etc/profile.d/poetry.sh exec $SHELL -l which poetry # virtualenvのインストール pip install virtualenv # アプリケーションのデプロイ先ディレクトリの作成 mkdir app chmod 755 /app chown root:root /app # プロジェクトの作成 mkdir /app/myapp touch /app/myapp/wsgi.py touch /app/myapp/vhost.conf # 仮想環境の作成とmod_wsgiのインストール cd /app/myapp/ virtualenv venv . venv/bin/activate which python python --version python -c 'import sys; print(sys.prefix)' pip install mod_wsgi # wsgiファイルの編集 vi /app/myapp/wsgi.py # apache設定ファイルの編集 mod_wsgi-express module-config vi /app/myapp/vhost.conf # 権限の編集 chmod -R 755 /app/myapp find /app/myapp -type f -exec chmod 644 {} + # apacheの設定変更・再起動 cp /app/myapp/vhost.conf /etc/httpd/conf.d/ httpd -t service httpd restart # ログの確認 tail -f -n 10 /etc/httpd/logs/access_log tail -f -n 10 /etc/httpd/logs/error_log # ここで http://<EC2のパブリックIP>:80/ にアクセスして確認する # ここで http://<EC2のパブリックIP>:8000/ にアクセスして確認する # ------------------------------------------------------------ # FlaskアプリケーションでHello World # ------------------------------------------------------------ # Flaskアプリケーションのファクトリを定義する vi /app/myapp/myapp/__init__.py # wsgiファイルを編集してFlaskアプリケーションを読み込む vi /app/myapp/wsgi.py # apacheの設定変更・再起動 service httpd restart # ログの確認 tail -f -n 10 /etc/httpd/logs/access_log tail -f -n 10 /etc/httpd/logs/error_log # ここで http://<EC2のパブリックIP>:8000/ にアクセスして確認する
wsgi.py
import os import sys project_root = os.path.dirname(__file__) python_home = os.path.join(project_root, "venv") activate_this = os.path.join(python_home, "bin", "activate_this.py") print('---------------------------------------------') print('project_root', project_root) print('python_home', python_home) print('activate_this', activate_this) print('---------------------------------------------') print('---------------------------------------------') print('sys.prefix', sys.prefix) print('sys.path', sys.path) print('---------------------------------------------') with open(activate_this) as file_: exec(file_.read(), dict(__file__=activate_this)) sys.path.insert(0, project_root) print('---------------------------------------------') print('sys.prefix', sys.prefix) print('sys.path', sys.path) print('---------------------------------------------') def application(environ, start_response): status = "200 OK" output = b"Hello World!" response_headers = [("Content-type", "text/plain"), ("Content-Length", str(len(output)))] start_response(status, response_headers) return [output] # from myapp import create_app # print('---------------------------------------------') # print('create_app', create_app) # print('---------------------------------------------') # application = create_app()
vhost.conf
Listen 8000 <VirtualHost *:8000> LoadModule wsgi_module "/app/myapp/venv/lib/python3.9/site-packages/mod_wsgi/server/mod_wsgi-py39.cpython-39-x86_64-linux-gnu.so" ServerName myapp.com LogLevel info WSGIDaemonProcess myapp user=apache group=apache # WSGIDaemonProcess myapp user=apache group=apache python-home=/app/myapp/venv WSGIProcessGroup myapp WSGIApplicationGroup %{GLOBAL} WSGIScriptAlias / /app/myapp/wsgi.py WSGIScriptReloading On <Directory /app/myapp> Require all granted </Directory> </VirtualHost>
myapp/__init__.py
from flask import Flask def create_app() -> Flask: app = Flask(__name__) @app.route("/hello") def hello() -> str: print('=========================================') print('hello') print('=========================================') return "Hello, World!" return app
vhost.sample.conf
<IfModule !version_module> LoadModule version_module '${MOD_WSGI_MODULES_DIRECTORY}/mod_version.so' </IfModule> ServerName localhost ServerRoot '/tmp/mod_wsgi-localhost:8000:1000' PidFile '/tmp/mod_wsgi-localhost:8000:1000/httpd.pid' <IfVersion >= 2.4> Defaul RuntimeDir '/tmp/mod_wsgi-localhost:8000:1000' </IfVersion> ServerTokens ProductOnly ServerSignature Off <IfDefine !MOD_WSGI_MPM_ENABLE_WINNT_MODULE> User ${MOD_WSGI_USER} Group ${MOD_WSGI_GROUP} </IfDefine> <IfDefine MOD_WSGI_WITH_LISTENER_HOST> Listen localhost:8000 </IfDefine> <IfDefine !MOD_WSGI_WITH_LISTENER_HOST> Listen 8000 </IfDefine> <IfVersion < 2.4> LockFile '/tmp/mod_wsgi-localhost:8000:1000/accept.lock' </IfVersion> <IfVersion >= 2.4> <IfDefine MOD_WSGI_WITH_PHP5> <IfModule !mpm_event_module> <IfModule !mpm_worker_module> <IfModule !mpm_prefork_module> <IfDefine MOD_WSGI_MPM_EXISTS_PREFORK_MODULE> LoadModule mpm_prefork_module '${MOD_WSGI_MODULES_DIRECTORY}/mod_mpm_prefork.so' </IfDefine> </IfModule> </IfModule> </IfModule> </IfDefine> </IfVersion> <IfVersion >= 2.4> <IfModule !mpm_event_module> <IfModule !mpm_worker_module> <IfModule !mpm_prefork_module> <IfDefine MOD_WSGI_MPM_ENABLE_EVENT_MODULE> LoadModule mpm_event_module '${MOD_WSGI_MODULES_DIRECTORY}/mod_mpm_event.so' </IfDefine> <IfDefine MOD_WSGI_MPM_ENABLE_WORKER_MODULE> LoadModule mpm_worker_module '${MOD_WSGI_MODULES_DIRECTORY}/mod_mpm_worker.so' </IfDefine> <IfDefine MOD_WSGI_MPM_ENABLE_PREFORK_MODULE> LoadModule mpm_prefork_module '${MOD_WSGI_MODULES_DIRECTORY}/mod_mpm_prefork.so' </IfDefine> </IfModule> </IfModule> </IfModule> </IfVersion> <IfDefine MOD_WSGI_WITH_HTTP2> LoadModule http2_module '${MOD_WSGI_MODULES_DIRECTORY}/mod_http2.so' </IfDefine> <IfVersion >= 2.4> <IfModule !access_compat_module> LoadModule access_compat_module '${MOD_WSGI_MODULES_DIRECTORY}/mod_access_compat.so' </IfModule> <IfDefine !MOD_WSGI_MPM_ENABLE_WINNT_MODULE> <IfModule !unixd_module> LoadModule unixd_module '${MOD_WSGI_MODULES_DIRECTORY}/mod_unixd.so' </IfModule> </IfDefine> <IfModule !authn_core_module> LoadModule authn_core_module '${MOD_WSGI_MODULES_DIRECTORY}/mod_authn_core.so' </IfModule> <IfModule !authz_core_module> LoadModule authz_core_module '${MOD_WSGI_MODULES_DIRECTORY}/mod_authz_core.so' </IfModule> </IfVersion> <IfModule !authz_host_module> LoadModule authz_host_module '${MOD_WSGI_MODULES_DIRECTORY}/mod_authz_host.so' </IfModule> <IfModule !mime_module> LoadModule mime_module '${MOD_WSGI_MODULES_DIRECTORY}/mod_mime.so' </IfModule> <IfModule !rewrite_module> LoadModule rewrite_module '${MOD_WSGI_MODULES_DIRECTORY}/mod_rewrite.so' </IfModule> <IfModule !alias_module> LoadModule alias_module '${MOD_WSGI_MODULES_DIRECTORY}/mod_alias.so' </IfModule> <IfModule !dir_module> LoadModule dir_module '${MOD_WSGI_MODULES_DIRECTORY}/mod_dir.so' </IfModule> <IfModule !env_module> LoadModule env_module '${MOD_WSGI_MODULES_DIRECTORY}/mod_env.so' </IfModule> <IfModule !headers_module> LoadModule headers_module '${MOD_WSGI_MODULES_DIRECTORY}/mod_headers.so' </IfModule> <IfModule !filter_module> LoadModule filter_module '${MOD_WSGI_MODULES_DIRECTORY}/mod_filter.so' </IfModule> <IfDefine MOD_WSGI_DIRECTORY_LISTING> <IfModule !autoindex_module> LoadModule autoindex_module '${MOD_WSGI_MODULES_DIRECTORY}/mod_autoindex.so' </IfModule> </IfDefine> <IfVersion >= 2.2.15> <IfModule !reqtimeout_module> LoadModule reqtimeout_module '${MOD_WSGI_MODULES_DIRECTORY}/mod_reqtimeout.so' </IfModule> </IfVersion> <IfDefine MOD_WSGI_COMPRESS_RESPONSES> <IfModule !deflate_module> LoadModule deflate_module '${MOD_WSGI_MODULES_DIRECTORY}/mod_deflate.so' </IfModule> </IfDefine> <IfDefine MOD_WSGI_AUTH_USER> <IfModule !auth_basic_module> LoadModule auth_basic_module '${MOD_WSGI_MODULES_DIRECTORY}/mod_auth_basic.so' </IfModule> <IfModule !auth_digest_module> LoadModule auth_digest_module '${MOD_WSGI_MODULES_DIRECTORY}/mod_auth_digest.so' </IfModule> <IfModule !authz_user_module> LoadModule authz_user_module '${MOD_WSGI_MODULES_DIRECTORY}/mod_authz_user.so' </IfModule> </IfDefine> <IfDefine MOD_WSGI_WITH_PROXY> <IfModule !proxy_module> LoadModule proxy_module ${MOD_WSGI_MODULES_DIRECTORY}/mod_proxy.so </IfModule> <IfModule !proxy_http_module> LoadModule proxy_http_module ${MOD_WSGI_MODULES_DIRECTORY}/mod_proxy_http.so </IfModule> </IfDefine> <IfModule mpm_prefork_module> <IfDefine MOD_WSGI_WITH_PHP5> <IfModule !php5_module> Loadmodule php5_module '${MOD_WSGI_MODULES_DIRECTORY}/libphp5.so' </IfModule> AddHandler application/x-httpd-php .php </IfDefine> </IfModule> <IfDefine MOD_WSGI_LOAD_PYTHON_DYLIB> LoadFile '' </IfDefine> LoadModule wsgi_module '/app/myapp/venv/lib/python3.9/site-packages/mod_wsgi/server/mod_wsgi-py39.cpython-39-x86_64-linux-gnu.so' <IfDefine MOD_WSGI_SERVER_METRICS> <IfModule !status_module> LoadModule status_module '${MOD_WSGI_MODULES_DIRECTORY}/mod_status.so' </IfModule> </IfDefine> <IfDefine MOD_WSGI_CGID_SCRIPT> <IfModule !cgid_module> LoadModule cgid_module '${MOD_WSGI_MODULES_DIRECTORY}/mod_cgid.so' </IfModule> </IfDefine> <IfDefine MOD_WSGI_CGI_SCRIPT> <IfModule !cgi_module> LoadModule cgi_module '${MOD_WSGI_MODULES_DIRECTORY}/mod_cgi.so' </IfModule> </IfDefine> <IfVersion < 2.4> DefaultType text/plain </IfVersion> TypesConfig '/etc/mime.types' HostnameLookups Off MaxMemFree 64 Timeout 60 ListenBacklog 500 <IfDefine MOD_WSGI_WITH_HTTP2> Protocols h2 h2c http/1.1 </IfDefine> <IfVersion >= 2.2.15> RequestReadTimeout header=15-30,MinRate=500 body=15,MinRate=500 </IfVersion> LimitRequestBody 10485760 <Directory /> AllowOverride None <IfVersion < 2.4> Order deny,allow Deny from all </IfVersion> <IfVersion >= 2.4> Require all denied </IfVersion> </Directory> WSGIPythonHome '/app/myapp/venv' WSGIVerboseDebugging 'Off' <IfDefine !MOD_WSGI_MPM_ENABLE_WINNT_MODULE> <IfDefine MOD_WSGI_WITH_SOCKET_PREFIX> WSGISocketPrefix None/wsgi </IfDefine> <IfDefine !MOD_WSGI_WITH_SOCKET_PREFIX> WSGISocketPrefix /tmp/mod_wsgi-localhost:8000:1000/wsgi </IfDefine> WSGISocketRotation Off </IfDefine> <IfDefine EMBEDDED_MODE> MaxConnectionsPerChild 0 </IfDefine> <IfDefine ORPHAN_INTERPRETER> WSGIDestroyInterpreter Off </IfDefine> <IfDefine !ORPHAN_INTERPRETER> WSGIDestroyInterpreter On </IfDefine> <IfDefine !ONE_PROCESS> <IfDefine !EMBEDDED_MODE> WSGIRestrictEmbedded On <IfDefine MOD_WSGI_MULTIPROCESS> WSGIDaemonProcess localhost:8000 \ display-name='(wsgi:localhost:8000:1000)' \ home='/app/myapp' \ processes=1 \ threads=5 \ maximum-requests=0 \ python-path='' \ python-eggs='/tmp/mod_wsgi-localhost:8000:1000/python-eggs' \ lang='en_US.UTF-8' \ locale='en_US.UTF-8' \ listen-backlog=100 \ queue-timeout=45 \ socket-timeout=60 \ connect-timeout=15 \ request-timeout=60 \ inactivity-timeout=0 \ startup-timeout=15 \ deadlock-timeout=60 \ graceful-timeout=15 \ eviction-timeout=0 \ restart-interval=0 \ cpu-time-limit=0 \ shutdown-timeout=5 \ send-buffer-size=0 \ receive-buffer-size=0 \ header-buffer-size=0 \ response-buffer-size=0 \ response-socket-timeout=0 \ server-metrics=Off </IfDefine> <IfDefine !MOD_WSGI_MULTIPROCESS> WSGIDaemonProcess localhost:8000 \ display-name='(wsgi:localhost:8000:1000)' \ home='/app/myapp' \ threads=5 \ maximum-requests=0 \ python-path='' \ python-eggs='/tmp/mod_wsgi-localhost:8000:1000/python-eggs' \ lang='en_US.UTF-8' \ locale='en_US.UTF-8' \ listen-backlog=100 \ queue-timeout=45 \ socket-timeout=60 \ connect-timeout=15 \ request-timeout=60 \ inactivity-timeout=0 \ startup-timeout=15 \ deadlock-timeout=60 \ graceful-timeout=15 \ eviction-timeout=0 \ restart-interval=0 \ cpu-time-limit=0 \ shutdown-timeout=5 \ send-buffer-size=0 \ receive-buffer-size=0 \ response-buffer-size=0 \ response-socket-timeout=0 \ server-metrics=Off </IfDefine> </IfDefine> </IfDefine> WSGICallableObject 'application' WSGIPassAuthorization On WSGIMapHEADToGET Auto <IfDefine MOD_WSGI_DISABLE_RELOADING> WSGIScriptReloading Off </IfDefine> <IfDefine EMBEDDED_MODE> <IfDefine MOD_WSGI_WITH_PYTHON_PATH> WSGIPythonPath '' </IfDefine> </IfDefine> <IfDefine ONE_PROCESS> WSGIRestrictStdin Off <IfDefine MOD_WSGI_WITH_PYTHON_PATH> WSGIPythonPath '' </IfDefine> </IfDefine> <IfDefine MOD_WSGI_SERVER_METRICS> ExtendedStatus On </IfDefine> WSGIServerMetrics Off <IfDefine MOD_WSGI_SERVER_STATUS> <Location /server-status> SetHandler server-status <IfVersion < 2.4> Order deny,allow Deny from all Allow from localhost </IfVersion> <IfVersion >= 2.4> Require all denied Require host localhost </IfVersion> </Location> </IfDefine> <IfDefine MOD_WSGI_KEEP_ALIVE> KeepAlive On KeepAliveTimeout 2 </IfDefine> <IfDefine !MOD_WSGI_KEEP_ALIVE> KeepAlive Off </IfDefine> <IfDefine MOD_WSGI_ENABLE_SENDFILE> EnableSendfile On WSGIEnableSendfile On </IfDefine> <IfDefine MOD_WSGI_COMPRESS_RESPONSES> AddOutputFilterByType DEFLATE text/plain AddOutputFilterByType DEFLATE text/html AddOutputFilterByType DEFLATE text/xml AddOutputFilterByType DEFLATE text/css AddOutputFilterByType DEFLATE text/javascript AddOutputFilterByType DEFLATE application/xhtml+xml AddOutputFilterByType DEFLATE application/javascript AddOutputFilterByType DEFLATE application/json </IfDefine> <IfDefine MOD_WSGI_ROTATE_LOGS> ErrorLog "|/usr/sbin/rotatelogs \ /tmp/mod_wsgi-localhost:8000:1000/error_log.%Y-%m-%d-%H_%M_%S 5M" </IfDefine> <IfDefine !MOD_WSGI_ROTATE_LOGS> ErrorLog "/tmp/mod_wsgi-localhost:8000:1000/error_log" </IfDefine> LogLevel warn <IfDefine MOD_WSGI_ERROR_LOG_FORMAT> ErrorLogFormat "None" </IfDefine> <IfDefine MOD_WSGI_ACCESS_LOG> <IfModule !log_config_module> LoadModule log_config_module ${MOD_WSGI_MODULES_DIRECTORY}/mod_log_config.so </IfModule> LogFormat "%h %l %u %t \"%r\" %>s %b" common LogFormat "%h %l %u %t \"%r\" %>s %b \"%{Referer}i\" \"%{User-agent}i\"" combined LogFormat "undefined" custom <IfDefine MOD_WSGI_ROTATE_LOGS> CustomLog "|/usr/sbin/rotatelogs \ /tmp/mod_wsgi-localhost:8000:1000/access_log.%Y-%m-%d-%H_%M_%S 5M" common </IfDefine> <IfDefine !MOD_WSGI_ROTATE_LOGS> CustomLog "/tmp/mod_wsgi-localhost:8000:1000/access_log" common </IfDefine> </IfDefine> <IfDefine MOD_WSGI_CHUNKED_REQUEST> WSGIChunkedRequest On </IfDefine> <IfDefine MOD_WSGI_WITH_PROXY_HEADERS> WSGITrustedProxyHeaders </IfDefine> <IfDefine MOD_WSGI_WITH_TRUSTED_PROXIES> WSGITrustedProxies </IfDefine> <IfDefine MOD_WSGI_WITH_HTTPS> <IfModule !ssl_module> LoadModule ssl_module ${MOD_WSGI_MODULES_DIRECTORY}/mod_ssl.so </IfModule> </IfDefine> <IfModule mpm_prefork_module> <IfDefine !ONE_PROCESS> ServerLimit 20 StartServers 1 MaxClients 20 MinSpareServers 1 MaxSpareServers 2 </IfDefine> <IfDefine ONE_PROCESS> ServerLimit 1 StartServers 1 MaxClients 1 MinSpareServers 1 MaxSpareServers 1 </IfDefine> MaxRequestsPerChild 0 </IfModule> <IfModule mpm_worker_module> <IfDefine !ONE_PROCESS> ServerLimit 2 ThreadLimit 10 StartServers 1 MaxClients 20 MinSpareThreads 10 MaxSpareThreads 10 ThreadsPerChild 10 </IfDefine> <IfDefine ONE_PROCESS> ServerLimit 1 ThreadLimit 1 StartServers 1 MaxClients 1 MinSpareThreads 1 MaxSpareThreads 1 ThreadsPerChild 1 </IfDefine> MaxRequestsPerChild 0 ThreadStackSize 262144 </IfModule> <IfModule mpm_event_module> <IfDefine !ONE_PROCESS> ServerLimit 2 ThreadLimit 10 StartServers 1 MaxClients 20 MinSpareThreads 10 MaxSpareThreads 10 ThreadsPerChild 10 </IfDefine> <IfDefine ONE_PROCESS> ServerLimit 1 ThreadLimit 1 StartServers 1 MaxClients 1 MinSpareThreads 1 MaxSpareThreads 1 ThreadsPerChild 1 </IfDefine> MaxRequestsPerChild 0 ThreadStackSize 262144 </IfModule> <IfDefine !MOD_WSGI_VIRTUAL_HOST> <IfVersion < 2.4> NameVirtualHost *:8000 </IfVersion> <VirtualHost _default_:8000> </VirtualHost> </IfDefine> <IfDefine MOD_WSGI_VIRTUAL_HOST> <IfVersion < 2.4> NameVirtualHost *:8000 </IfVersion> <VirtualHost _default_:8000> <Location /> <IfVersion < 2.4> Order deny,allow Deny from all </IfVersion> <IfVersion >= 2.4> Require all denied </IfVersion> <IfDefine MOD_WSGI_ALLOW_LOCALHOST> Allow from localhost </IfDefine> </Location> </VirtualHost> <IfDefine !MOD_WSGI_HTTPS_ONLY> <VirtualHost *:8000> ServerName None <IfDefine MOD_WSGI_SERVER_ALIAS> ServerAlias None </IfDefine> </VirtualHost> <IfDefine MOD_WSGI_REDIRECT_WWW> <VirtualHost *:8000> ServerName unspecified Redirect permanent / http://None:8000/ </VirtualHost> </IfDefine> </IfDefine> <IfDefine MOD_WSGI_HTTPS_ONLY> <VirtualHost *:8000> ServerName None <IfDefine MOD_WSGI_SERVER_ALIAS> ServerAlias None </IfDefine> RewriteEngine On RewriteCond %{HTTPS} off RewriteRule (.*) https://None:None%{REQUEST_URI} </VirtualHost> <IfDefine MOD_WSGI_REDIRECT_WWW> <VirtualHost *:8000> ServerName unspecified RewriteEngine On RewriteCond %{HTTPS} off RewriteRule (.*) https://None:None%{REQUEST_URI} </VirtualHost> </IfDefine> </IfDefine> </IfDefine> <IfDefine MOD_WSGI_VIRTUAL_HOST> <IfDefine MOD_WSGI_WITH_HTTPS> <IfDefine MOD_WSGI_WITH_LISTENER_HOST> Listen localhost:None </IfDefine> <IfDefine !MOD_WSGI_WITH_LISTENER_HOST> Listen None </IfDefine> <IfVersion < 2.4> NameVirtualHost *:None </IfVersion> <VirtualHost _default_:None> <Location /> <IfVersion < 2.4> Order deny,allow Deny from all </IfVersion> <IfVersion >= 2.4> Require all denied </IfVersion> <IfDefine MOD_WSGI_ALLOW_LOCALHOST> Allow from localhost </IfDefine> </Location> SSLEngine On SSLCertificateFile None SSLCertificateKeyFile None <IfDefine MOD_WSGI_VERIFY_CLIENT> SSLCACertificateFile None SSLVerifyClient none </IfDefine> <IfDefine MOD_WSGI_CERTIFICATE_CHAIN> SSLCertificateChainFile None </IfDefine> </VirtualHost> <VirtualHost *:None> ServerName None <IfDefine MOD_WSGI_SERVER_ALIAS> ServerAlias None </IfDefine> SSLEngine On SSLCertificateFile None SSLCertificateKeyFile None <IfDefine MOD_WSGI_VERIFY_CLIENT> SSLCACertificateFile None SSLVerifyClient none </IfDefine> <IfDefine MOD_WSGI_CERTIFICATE_CHAIN> S SLCertificateChainFile None </IfDefine> <IfDefine MOD_WSGI_HTTPS_ONLY> <IfDefine MOD_WSGI_HSTS_POLICY> Header set Strict-Transport-Security None </IfDefine> </IfDefine> <IfDefine MOD_WSGI_SSL_ENVIRONMENT> SSLOptions +StdEnvVars </IfDefine> </VirtualHost> <IfDefine MOD_WSGI_REDIRECT_WWW> <VirtualHost *:None> ServerName unspecified Redirect permanent / https://None:None/ SSLEngine On SSLCertificateFile None SSLCertificateKeyFile None <IfDefine MOD_WSGI_VERIFY_CLIENT> SSLCACertificateFile None SSLVerifyClient none </IfDefine> <IfDefine MOD_WSGI_CERTIFICATE_CHAIN> SSLCertificateChainFile None </IfDefine> </VirtualHost> </IfDefine> </IfDefine> </IfDefine> DocumentRoot '/tmp/mod_wsgi-localhost:8000:1000/htdocs' AccessFileName .htaccess <Directory '/tmp/mod_wsgi-localhost:8000:1000'> AllowOverride None <Files handler.wsgi> <IfVersion < 2.4> Order allow,deny Allow from all </IfVersion> <IfVersion >= 2.4> Require all granted </IfVersion> </Files> </Directory> <Directory '/tmp/mod_wsgi-localhost:8000:1000/htdocs'> AllowOverride None <IfDefine MOD_WSGI_DIRECTORY_INDEX> DirectoryIndex None </IfDefine> <IfDefine MOD_WSGI_DIRECTORY_LISTING> Options +Indexes </IfDefine> <IfDefine MOD_WSGI_CGI_SCRIPT> Options +ExecCGI </IfDefine> <IfDefine MOD_WSGI_CGID_SCRIPT> Options +ExecCGI </IfDefine> RewriteEngine On Include /tmp/mod_wsgi-localhost:8000:1000/rewrite.conf <IfVersion < 2.4> Order allow,deny Allow from all </IfVersion> <IfVersion >= 2.4> Require all granted </IfVersion> </Directory> <Directory '/tmp/mod_wsgi-localhost:8000:1000/htdocs/'> <IfDefine !MOD_WSGI_STATIC_ONLY> RewriteCond %{REQUEST_FILENAME} !-f <IfDefine MOD_WSGI_DIRECTORY_INDEX> RewriteCond %{REQUEST_FILENAME} !-d </IfDefine> <IfDefine MOD_WSGI_SERVER_STATUS> RewriteCond %{REQUEST_URI} !/server-status </IfDefine> RewriteRule .* - [H=wsgi-handler] </IfDefine> </Directory> <IfDefine MOD_WSGI_ERROR_OVERRIDE> WSGIErrorOverride On </IfDefine> <IfDefine MOD_WSGI_HOST_ACCESS> <Location /> WSGIAccessScript 'None' </Location> </IfDefine> <IfDefine MOD_WSGI_AUTH_USER> <Location /> AuthType Basic AuthName 'localhost:8000' AuthBasicProvider wsgi WSGIAuthUserScript 'None' <IfDefine MOD_WSGI_AUTH_GROUP> WSGIAuthGroupScript 'None' </IfDefine> <IfVersion < 2.4> Require valid-user <IfDefine MOD_WSGI_AUTH_GROUP> Require wsgi-group 'wsgi' </IfDefine> </IfVersion> <IfVersion >= 2.4> <RequireAll> Require valid-user <IfDefine MOD_WSGI_AUTH_GROUP> Require wsgi-group 'wsgi' </IfDefine> </RequireAll> </IfVersion> </Location> </IfDefine> <IfDefine !ONE_PROCESS> <IfDefine !EMBEDDED_MODE> WSGIHandlerScript wsgi-handler '/tmp/mod_wsgi-localhost:8000:1000/handler.wsgi' \ process-group='localhost:8000' application-group=%{GLOBAL} WSGIImportScript '/tmp/mod_wsgi-localhost:8000:1000/handler.wsgi' \ process-group='localhost:8000' application-group=%{GLOBAL} </IfDefine> </IfDefine> <IfDefine EMBEDDED_MODE> WSGIHandlerScript wsgi-handler '/tmp/mod_wsgi-localhost:8000:1000/handler.wsgi' \ process-group='%{GLOBAL}' application-group=%{GLOBAL} WSGIImportScript '/tmp/mod_wsgi-localhost:8000:1000/handler.wsgi' \ process-group='%{GLOBAL}' application-group=%{GLOBAL} </IfDefine> <IfDefine ONE_PROCESS> <IfDefine !MOD_WSGI_MPM_ENABLE_WINNT_MODULE> WSGIHandlerScript wsgi-handler '/tmp/mod_wsgi-localhost:8000:1000/handler.wsgi' \ process-group='%{GLOBAL}' application-group=%{GLOBAL} WSGIImportScript '/tmp/mod_wsgi-localhost:8000:1000/handler.wsgi' \ process-group='%{GLOBAL}' application-group=%{GLOBAL} </IfDefine> <IfDefine MOD_WSGI_MPM_ENABLE_WINNT_MODULE> WSGIHandlerScript wsgi-handler '/tmp/mod_wsgi-localhost:8000:1000/handler.wsgi' \ application-group=%{GLOBAL} WSGIImportScript '/tmp/mod_wsgi-localhost:8000:1000/handler.wsgi' \ application-group=%{GLOBAL} </IfDefine> </IfDefine> <IfDefine MOD_WSGI_VERIFY_CLIENT> <Location '/'> SSLVerifyClient require SSLVerifyDepth 1 </Location> </IfDefine>
pip で mod_wsgi のインストールを試みたらエラーが発生した
環境
実行コマンド
pip install mod_wsgi
エラー
RuntimeError: The 'apxs' command appears not to be installed or is not executable. Please check the list of prerequisites in the documentation for this package and install any missing Apache httpd server packages.
原因
apxs
コマンドがないことが原因。
解決
mod_wsgi のインストールの前に apxs コマンドを含むパッケージをインストールする。
yum info httpd-devel
The httpd-devel package contains the APXS binary (以下略)
sudo yum -y install httpd-devel
pip install mod_wsgi