Here's a simple http proxy made with C++ and the Boost libraries. It's single threaded so you cant launch multiple connections on one server. This means that you won't be able to post on mpgh while you're loading a youtube video for example.
Point your browser to your ip address and port 4040 to test the server. Tested and working with firefox 10, youtube, mpgh, google everything (important) works.
Main.cpp
Code:
#define _WIN32_WINNT 0x0501
#include <iostream>
#include <istream>
#include <ostream>
#include <string>
#include <boost/optional.hpp>
#include <boost/array.hpp>
#include <boost/thread.hpp>
#include <boost/lexical_cast.hpp>
#include <boost/asio.hpp>
using boost::asio::ip::tcp;
boost::asio::io_service io_service;
tcp::resolver::iterator ResolveIp( std::string Host, int &Length ){
tcp::resolver resolver(io_service);
int Start = Host.find_first_of( ' ' ) + 1;
Length = Host.find_first_of( "\r\n" );
Length -= Start;
std::cout << "Connecting to: " << Host.substr( Start, Length ) << std::endl;
std::cout << "Full host path: " << Host << std::endl;
tcp::resolver::query query( Host.substr( 6, Length ), boost::lexical_cast<std::string>(80));
return resolver.resolve(query);
}
void handler( const boost::system::error_code& error, std::size_t bytes_transferred, std::size_t *pbytes_transferred ){
*pbytes_transferred = bytes_transferred;
if( error && pbytes_transferred ) *pbytes_transferred = 0;
}
bool Read_with_timeout( tcp::socket &Socket, boost::asio::streambuf& Buffer, std::size_t& bytes_transferred ){
try{
std::size_t Transfered;
std::ostream response_stream( &Buffer );
unsigned char tmpBuffer[512];
Socket.async_read_some( boost::asio::buffer(tmpBuffer, 512), boost::bind(handler, boost::asio::placeholders::error, boost::asio::placeholders::bytes_transferred, &Transfered ) );
Socket.get_io_service().reset();
while( Socket.get_io_service().run_one() ){
if( Transfered )
response_stream.write( (char*) &tmpBuffer[0], Transfered );
else
return false;
}
} catch (std::exception& e){
std::cout << "Exception: " << e.what() << "\n";
return false;
}
return true;
}
void TransparantHttpProxy( boost::shared_ptr< tcp::socket > LocalSocket, std::string LocalRequest, std::string Host ){
try{
int HostLenght = 0;
boost::asio::streambuf RemoteRequest;
boost::asio::streambuf RemoteResponse;
boost::system::error_code error;
std::ostream request_stream( &RemoteRequest );
std::ostream response_stream( &RemoteResponse );
tcp::socket RemoteSocket(io_service);
tcp::resolver::iterator endpoint_iterator = ResolveIp( Host, HostLenght );
boost::asio::connect(RemoteSocket, endpoint_iterator );
request_stream << LocalRequest << "\n" ;
request_stream << Host << "\n" ;
request_stream << "Accept: */*\r\n";
request_stream << "Connection: close\r\n\r\n";
boost::asio::write( RemoteSocket, RemoteRequest );
std::size_t asd;
while( Read_with_timeout( RemoteSocket, RemoteResponse, asd ) ){
boost::asio::write( *LocalSocket, RemoteResponse, boost::asio::transfer_all() );
}
} catch (std::exception& e){
std::cout << "Exception: " << e.what() << "\n";
}
return;
}
int main(int argc, char* argv[]){
try{
tcp::acceptor acceptor(io_service, tcp::endpoint(tcp::v4(), 4040));
while(true){
boost::shared_ptr< tcp::socket > socket( new tcp::socket(io_service) );
acceptor.accept( *socket );
std::string Request, Host;
boost::asio::streambuf response;
std::istream is( &response );
boost::asio::read( *socket, response, boost::asio::transfer_at_least(1) );
getline ( is, Request );
getline ( is, Host );
TransparantHttpProxy( socket, Request, Host);
}
} catch (std::exception& e){
std::cout << "Exception: " << e.what() << "\n";
}
return 0;
}