Skip to content

Instantly share code, notes, and snippets.

@xantus
Created August 5, 2010 21:55
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save xantus/5a5b4e0c12ee55a30263 to your computer and use it in GitHub Desktop.
Save xantus/5a5b4e0c12ee55a30263 to your computer and use it in GitHub Desktop.
Mojolicious Reverse Proxy Plugin
package Mojolicious::Plugin::ReverseProxy;
use strict;
use warnings;
use base 'Mojolicious::Plugin';
# ugh
$ENV{MOJO_MAX_MESSAGE_SIZE} = 5242880;
sub register {
my ( $plugin, $app, $cfg ) = @_;
die "route and url params are required" unless ref $cfg eq 'HASH' && @{$cfg}{qw( route url )};
$cfg->{url} = Mojo::URL->new( $cfg->{url} ) unless UNIVERSAL::isa( $cfg->{url}, 'Mojo::URL' );
my $cb = sub { $plugin->_proxy( @_, $cfg ) };
$app->routes->route( $cfg->{route}.'(*proxypath)' )->to({ cb => $cb, 'proxy.url' => $cfg->{url} });
$app->routes->route( $cfg->{route} )->to({ cb => $cb, 'proxy.url' => $cfg->{url} });
}
sub _proxy {
my ( $self, $c, $cfg ) = @_;
my $host = $c->req->headers->host;
my $tx = Mojo::Transaction::HTTP->new;
$tx->req( $c->req );
# fix up the request url
my $file = $c->stash( 'proxypath' ) || '/';
my $url = $c->stash( 'proxy.url' )->clone;
$url->path->append( grep { length $_ } split( '/', $file ) );
$url->path->trailing_slash(0) unless substr( $file, -1, 1 ) eq '/';
$tx->req->url( $url );
$tx->req->headers->header( 'X-Forwarded-For' => $c->tx->remote_address );
$tx->req->headers->header( 'X-Forwarded-Host' => $host ) if $host;
$tx->req->headers->header( 'Host' => $url->host . ( $url->port ? ':'.$url->port : '' ) );
# XXX X-Forwarded-Server
# TODO add a flag for this
if ( my $bigip = $c->req->headers->header( 'X-BIGIP-Client' ) && $cfg->{behind_bigip} ) {
$tx->req->headers->header( 'X-BIGIP-Client' => $bigip );
}
# make the request
$c->pause;
$c->client->async->process($tx => sub {
my ( $cli, $t ) = @_;
$c->render_data($t->res->body);
$c->res->headers->from_hash( {} ); # delete all current headers
$c->res->headers->from_hash( $t->res->headers->to_hash );
$c->finish;
})->process;
return;
};
1;
__END__
# example
use Mojolicious::Lite;
# auto daemon
@ARGV = qw( daemon ) unless @ARGV;
# proxy couchdb
app->plugin( 'reverse_proxy' => { route => '/', url => 'http://localhost:5984/' } );
app->start;
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment