Last Updated: December 31, 2020
·
3.322K
· hernan604

Create a simple custom customizable http proxy that allows you to intercept and alter request/response content

If you ever needed to debug a JS or even CSS on a site you dont own, or maybe you must fix some JS script on production and the only way is with git commit (you dont have a dev ambient) and that might break something if not properly tested plus you dont want to make 100s of commits to debug live. Or maybe you want to map http://site.com/some/dir/* to /home/user/my/dir/* so every url matching that will open files in your disk respectively.

The main question is: When i tell my browser to open siteX.com, is there a way to intercept each external file the siteX and its scripts want to access ?
Simple answer: Yes, use a proxy
My answer: Yes, but i want some proxy i can customize alot and create plugins and allow others to build plugins for it.
This tool is very beta yet but i find it very interesting and really cool stuff because you can notice all the requests the browser is doing. Its like firebug is missing somehting.

Its here: https://github.com/hernan604/HTTP-Proxy-Interceptor

1 - quick steps to install

Install the perl dependencies

if you dont know what you are doing, open the terminal and make sure you see any perl version output by running the command: perl -v
and then when you make sure perl is installed you can execute those commands with sudo and everything will probably install without hassle:

curl -L http://cpanmin.us | perl - --sudo App::cpanminus
sudo cpanm Moose LWP::UserAgent Data::Printer Config::Any File::Slurp URI URI::QueryParam v5.10 Getopt::Long Net::Server

Create a config with the urls you want to intercept:

Create my_config.json (remove the comments):

{
"http://www.site.com.br/js/script.js?v=136" : { <-- open file content when browser opens that url
"file" : "/home/hernan/teste.js"
},
"http://www.site.com.br/some/c/coolscript.js?ABC=xyz" : { <- shows content from antother url
"url" : "http://www.outra-url.com.br/por-este-arquivo-no-lugar/novo_coolscripts.js?nome=maria",
"userandomvar" : false
},
"http://site.com/resources/(?<caminho>.+)" : { <- maps remote dir to local dir
"relative_path" : "/home/hernan/site.com/resources/"
}
}

or you can use perl syntax for config too, ie: my_config.pl

{
"http://www.site.com.br/js/script.js?v=136" => {
"file" => "/home/webdev/teste.js"
},
"http://www.site1.com.br/scripts.js" => {
"url" => "http://www.othersite.com.br/other-scripts.js",
"userandomvar" => false
},
"http://p1-cdn.trrsf.com/image/fget/cf/742/556/0/55/407/305/images.terra.com/2013/09/04/italianomortebrasileirafacereprod.jpg" => {
"url" => "http://h.imguol.com/1309/14beyonce23-gb.jpg"
},
"http://site.com/resources/(?<caminho>.+)" => {
"relativepath" => "/home/hernan/site.com/resources/"
},
"http://www.w3schools.com/" => {
"code" => sub {
my ( $self, $content ) = @
;
$content =~ s/Learn/CLICK FOR WRONG/gix;
return $content;
}
},

}

Start the proxy

perl proxy-sem-ssl.pl -config my_config.json -porta 9000

you should see output like this:

Plugin method add => replaceforrelativepath
Plugin method add => replaceurl
Plugin method add => abre
arquivo
2013/09/12-12:36:05 Meu::Proxy (type Net::Server) starting! pid(12566)
Resolved [*]:9876 to [0.0.0.0]:9876, IPv4
Binding to TCP port 9876 on host 0.0.0.0 with IPv4
Group Not Defined. Defaulting to EGID '1001 1001'
User Not Defined. Defaulting to EUID '1001'

2 - About the code and plugins

Its a very simple proxy done with perl. If take a look at "proxy-sem-ssl.pl" , you will notice its composed of 4 plugins:

Plugin::ContentModifier:
- allows you to modify the content of a request. Works per url.

Plugin::RelativePath
- allows you to map a remote path to a local path. Will open content from files locally as if they were served from the site.

Plugin::UrlReplacer
- It works per url and will get content from url2 when you request url1

Plugin::File
- It works per url and will show the contents of files locally when you try to open specific urls

The main loop that receves the browser request:

HTTP::URL::Intercept::Proxy;
- This loop here receives the requests from the browser... if you add the line:
warn p $lines
you will notice the http request that is coming... and you see how the rest works

And then you create your custom proxy like this:

package My::Custom::Proxy;
use Moose;

extend from the main class

extends qw/HTTP::URL::Intercept::Proxy/;

and use these plugins

with qw/
HTTP::URL::Intercept::Proxy::Plugin::RelativePath
HTTP::URL::Intercept::Proxy::Plugin::UrlReplacer
HTTP::URL::Intercept::Proxy::Plugin::File
/;

1;

my $proxy = My::Custom::Proxy->new();
My::Custom::Proxy->run( port => $proxy->porta );