Skip to content

Instantly share code, notes, and snippets.

@dolmen
Created May 13, 2011 08:16
Show Gist options
  • Save dolmen/970190 to your computer and use it in GitHub Desktop.
Save dolmen/970190 to your computer and use it in GitHub Desktop.
Discovering PSGI: A proof of concept of a proxy that switches Google and Bing
# vim:set ft=perl:
use strict;
use warnings;
# plackup --port 8079 -s Twiggy -a GoogleBingProxy.psgi
# http_proxy=http://0.0.0.0:8079/ curl -i http://www.google.fr/
# Les lignes suivantes ne sont pas néccessaires, mais ça permet de
# spécifier plus clairement les dépendances pour ceux qui voudraient faire
# tourner l'exemple
require Twiggy;
require AnyEvent::HTTP;
require Plack::App::Proxy;
BEGIN { $ENV{PLACK_PROXY_BACKEND} = 'AnyEvent::HTTP' }
package Plack::Middleware::ClearCookies;
$INC{'Plack/Middleware/ClearCookies.pm'} = __FILE__;
use parent 'Plack::Middleware';
require Plack::Util;
sub call
{
my ($self, $env) = @_;
delete $env->{HTTP_COOKIE};
my $res = $self->app->($env);
Plack::Util::response_cb($res, sub {
my $res = shift;
my $headers = $res->[1];
for(my $i = $#{ $headers }-1; $i > 0; $i--) {
next unless $headers->[$i] =~ /^Set-Cookie$/i;
splice @$headers, $i, 2;
}
})
}
package Plack::Middleware::PrintCookies;
$INC{'Plack/Middleware/PrintCookies.pm'} = __FILE__;
use parent 'Plack::Middleware';
require Plack::Util;
sub call
{
my ($self, $env) = @_;
if (exists $env->{HTTP_COOKIE}) {
foreach my $cookie (split /\s*;\s*/, $env->{HTTP_COOKIE}) {
print "-> $cookie\n";
}
}
Plack::Util::response_cb($self->app->($env), sub {
my $res = shift;
my $headers = $res->[1];
for(my $i = $#{ $headers }-1; $i > 0; $i--) {
next unless $headers->[$i] =~ /^Set-Cookie$/i;
foreach my $cookie (split /\s*,\s*/, $headers->[$i+1]) {
print "<- $cookie\n";
}
}
})
}
package Plack::Middleware::BingGoogleProxy;
$INC{'Plack/Middleware/BingGoogleProxy.pm'} = __FILE__;
use parent 'Plack::Middleware';
sub call
{
my ($self, $env) = @_;
#print join(',', keys(%$env)), "\n";
print "Host: $env->{HTTP_HOST}\n" if exists $env->{HTTP_HOST};
print "URI: $env->{REQUEST_URI}\n";
my ($host, $path) = ($env->{REQUEST_URI} =~ m!http://([^/]*)(/?.*)$!);
my $host_orig = $host;
if ($host eq 'www.google.fr') {
$host = 'www.bing.com';
} elsif ($host eq 'www.bing.com') {
$host = 'www.google.fr';
}
if ($host ne $host_orig) {
$env->{HTTP_HOST} = $host;
$env->{REQUEST_URI} = 'http://'.$host.$path;
Plack::Middleware::ClearCookies->wrap($self->app)->($env);
} else {
$self->app->($env);
}
}
package Plack::App::BingGoogleProxy;
use Plack::App::Proxy;
my $proxy = Plack::App::Proxy->new->to_app;
my $app = sub($) {
my $env = shift;
# Forward
# TODO drop CONNECT, and non-http://
$env->{'plack.proxy.url'} = $env->{REQUEST_URI};
$env->{REQUEST_URI} =~ s!^http://[^/]*!!;
$proxy->($env)
};
use Plack::Builder;
builder {
enable 'Plack::Middleware::PrintCookies';
enable 'Plack::Middleware::BingGoogleProxy';
$app
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment