Skip to content

Instantly share code, notes, and snippets.

@hayajo hayajo/MyApp.pm
Last active Dec 28, 2015

Embed
What would you like to do?
「MojoliciousでHTTP(S)の振り分けをリバースプロキシのバックエンドでも出来るようにしてみる」の例(Apache + mod_proxy)
<VirtualHost _default_:443>
ServerName localhost.myapp
... ssl conf ...
<Proxy *>
Order deny,allow
Allow from all
</Proxy>
ProxyRequests Off
ProxyPreserveHost On
ProxyPass / http://localhost:8080/
ProxyPassReverse / http://localhost:8080/
RequestHeader set X-Forwarded-HTTPS "1"
# 環境に応じて適宜設定
SetEnv proxy-initial-not-pooled 1
SetEnv force-proxy-request-1.0 1
SetEnv proxy-nokeepalive 1
</VirtualHost>
<VirtualHost *:80>
ServerName localhost.myapp
<Proxy *>
Order deny,allow
Allow from all
</Proxy>
ProxyRequests Off
ProxyPreserveHost On
ProxyPass / http://localhost:8080/
ProxyPassReverse / http://localhost:8080/
RequestHeader set X-Forwarded-HTTPS "0"
# 環境に応じて適宜設定
SetEnv proxy-initial-not-pooled 1
SetEnv force-proxy-request-1.0 1
SetEnv proxy-nokeepalive 1
</VirtualHost>
package MyApp;
use Mojo::Base 'Mojolicious';
# This method will run once at server start
sub startup {
my $self = shift;
# Router
my $r = $self->routes;
# https onry
my $ssl_r = $r->under(
sub {
my $self = shift;
return 1 if $self->req->is_secure;
$self->redirect_to($self->req->url->to_abs->scheme('https'));
}
);
# http onry
my $not_ssl_r = $r->under(
sub {
my $self = shift;
return 1 unless $self->req->is_secure;
$self->redirect_to($self->req->url->to_abs->scheme('http'));
}
);
$r->get('/')->to('example#index')->name('index');
$not_ssl_r->get('/not_ssl')->to('example#not_ssl')->name('not_ssl');
$ssl_r->get('/ssl')->to('example#ssl')->name('ssl');
}
1;
package MyApp::Example;
use Mojo::Base 'Mojolicious::Controller';
# This action will render a template
sub index {}
sub not_ssl { $_[0]->render('example/index') }
sub ssl { $_[0]->render('example/index') }
1;
upstream app {
server localhost:8080;
}
server {
listen 80;
listen 443 ssl;
server_name localhost.proxy;
ssl on;
ssl_certificate /etc/ssl/certs/ssl-cert-snakeoil.pem;
ssl_certificate_key /etc/ssl/private/ssl-cert-snakeoil.key;
ssl_session_timeout 5m;
ssl_protocols SSLv3 TLSv1;
ssl_ciphers ALL:!ADH:!EXPORT56:RC4+RSA:+HIGH:+MEDIUM:+LOW:+SSLv3:+EXP;
ssl_prefer_server_ciphers on;
location / {
proxy_pass http://app;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
proxy_set_header Host $host;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
set $mode 0;
if ($scheme = "https") {
set $mode 1;
}
proxy_set_header X-Forwarded-HTTPS $mode;
}
}
% layout 'default';
% title 'SSL/NOT_SSL ROUTE - Mojolicious ' . $Mojolicious::VERSION;
<h2><%= $self->req->url->to_abs %></h2>
<ul>
<li>
<a href="<%= url_for('not_ssl') %>">not_ssl</a>
</li>
<li>
<a href="<%= url_for('ssl') %>">ssl</a>
</li>
</ul>
<pre><%= dumper $self->req->headers->to_hash %></pre>
@hayajo

This comment has been minimized.

Copy link
Owner Author

hayajo commented Nov 12, 2013

ディレクトリセパレータは「_」(アンダースコア)どす。

@hayajo

This comment has been minimized.

Copy link
Owner Author

hayajo commented Nov 12, 2013

ちょいと修正

@hayajo

This comment has been minimized.

Copy link
Owner Author

hayajo commented Nov 13, 2013

Apache 2.2.22-6ubuntu2 + Mojolicious 3.97, 4.28, 4.57 の morbo と hypnotoad で動作確認

@hayajo

This comment has been minimized.

Copy link
Owner Author

hayajo commented Nov 15, 2013

Nginx 1.2.1-2.2ubuntu でも動作確認

@clicktx

This comment has been minimized.

Copy link

clicktx commented Nov 15, 2013

自分の不具合は

proxy_set_header Host $host;

が設定していなかったからのようでした。

ちなみに、

server {
    listen       80;
    listen       443 ssl;
    server_name  localhost.proxy;

    ... ssl conf ...

    location / {
        proxy_pass http://app;
        proxy_http_version 1.1;
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection "upgrade";
        proxy_set_header Host $host;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;

        #set $mode 0;
        if ($scheme = "https"){
          set $mode "on";
        }
        proxy_set_header X-Forwarded-HTTPS $mode;
    }
}

とconfigをまとめた場合でも動作確認出来ました!感謝!

@hayajo

This comment has been minimized.

Copy link
Owner Author

hayajo commented Nov 15, 2013

@clicktx コメントありがとうございます。まとめたほうがスッキリして良いですね。参考にさせていただきます。

@hayajo

This comment has been minimized.

Copy link
Owner Author

hayajo commented Nov 18, 2013

MOJO_REVERSE_PROXY=1 して起動すること。

じゃないと HTTPS リクエストの場合に req->base->scheme が https にならないよ。

# e.g.
MOJO_REVERSE_PROXY=1 hypnotoad script/my_app

リバースプロキシを利用したときにホスト名、ポート番号、パスが正しく認識されるようにする / Mojoliciousリファレンス - サンプルコードによるPerl入門

@clicktx

This comment has been minimized.

Copy link

clicktx commented Sep 8, 2014

http://mojolicio.us/perldoc/Mojolicious/Guides/Cookbook#Nginx
にあるように、

proxy_set_header X-Forwarded-Proto "http";

と、最近のmojolicious(v5.35時点)では proxy_set_header X-Forwarded-Proto で検知するように仕様変更された(?)のでしょうか。

nginxの設定で言うと、

server {
    listen       80;
    listen       443 ssl;
    server_name  localhost.proxy;

    ... ssl conf ...

    location / {
        proxy_pass http://app;
        proxy_http_version 1.1;
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection "upgrade";
        proxy_set_header Host $host;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;

        #set $mode 0; ← 不要
        #if ($scheme = "https"){ ← 不要
        #  set $mode "on"; ← 不要
        #} ← 不要
        #proxy_set_header X-Forwarded-HTTPS $mode; ← 不要
        proxy_set_header X-Forwarded-Proto $scheme;  ←追加
    }
}

でうごくようになりました。

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.
You signed in with another tab or window. Reload to refresh your session. You signed out in another tab or window. Reload to refresh your session.