Discussion:
Is this proxying possible
Børge Nilsen
2003-09-25 13:19:48 UTC
Permalink
I have a little problem that I though I could solve in a simple way using
apache, but after going through the documentation I am not so sure...

Basically the problem is that on my server I get some POST messages that I
would like to do the following with:
a: log the entire message to the file system
b. add a field to the message itself (ideally within the http body)
c. proxy the message to another server/ port for processing

My first idea was that this could be done with a few rewrite rules and a
perl script, but I'm beginning to get som doubts. Is there anyone out there
that could help me...please...?
Daniel Lopez
2003-09-25 13:03:32 UTC
Permalink
Post by Børge Nilsen
I have a little problem that I though I could solve in a simple way using
apache, but after going through the documentation I am not so sure...
Basically the problem is that on my server I get some POST messages that I
a: log the entire message to the file system
b. add a field to the message itself (ideally within the http body)
c. proxy the message to another server/ port for processing
My first idea was that this could be done with a few rewrite rules and a
perl script, but I'm beginning to get som doubts. Is there anyone out there
that could help me...please...?
mod_rewrite does nto allow you to change the body,
If you are using Apache 2, you can write an input filter (if you are using
mod_perl, php or any other module that exposes the filtering API) or try and
use http://httpd.apache.org/docs-2.0/mod/mod_ext_filter.html
(works for output filtering, not sure it will work for input fitlering)

If you have Apache 1.3 and are using PHP or mod_perl or another solution,
you may be able to just acept the POST, issue teh request yourself using the
HTTP client libraries of PHP or Perl and then return the result to your users)

Cheers

DAniel
--
Teach Yourself Apache 2 -- http://apacheworld.org/ty24/
J***@Talaris.com
2003-09-25 17:57:32 UTC
Permalink
Ok I may have something that you can use.
So point by point because I do not understand point B
I have a perl script which I wrote that does all of what you are asking.
The way the script works is:

You setup this perl script on your cgi-bin and have all your post directed to that CGI perl script
The script will log the entire post in both URL encoded and URL decode as well as allow you to add other fielsd to the post, i.e. Log the entire Env from the post and or add your own comments to the log file of the post message.

The script then will repost the message to any server you wish, currently I have the script setup to post two two servers, however you can modifiy the script to post to "N" servers. Before you post you can always add data to the post stream, i.e comments, this is not setup on the script today but it is very easy to add.

The script has comments but I have no time to clean up the script.

For security reason you should have someone look at the script. I have not run a full security check on it because I use the script for testing purposes and not for production use.

I hope this helps.

Jorge Reyes
The_Colombian
Post by Børge Nilsen
a: log the entire message to the file system
Yes
Post by Børge Nilsen
b. add a field to the message itself (ideally within the http body)
Yes but not sure what you mean by the http body
Post by Børge Nilsen
c. proxy the message to another server/ port for processing
yes. to n number of server

#! /usr/bin/perl
##############################################################################
# POST Redirect Version 1.0.2 #
# Jorge Reyes ***@relux.com
# The_Colombian
# Created 04/21/2003 Last Modified 06/28/2003 #
##############################################################################
# BEWARE ! this script will spit out only plain text
print "Content-type: text/plain\n\n";
############################################################
#Don't touch, these are necessary to run the script!
$mailprog = '/usr/sbin/sendmail';
$date_command = "/bin/date";
$mail = 0;
$mailto = '***@somewhere.com';
$from = '***@somewhere.com';
$date = `$date_command +"%a-%b-%d-%Z-%Y-%H-%M-%S"`; chop($date);
$USERagent = 'Mozilla/4.0 (compatible)';
#################################################################
###### Log files of raw data either UUENCODE and UU-DECODE
$DATA1 = "/data/DATA1.txt";
$DATA2 = "/data/DATA2.txt";
$postlog = '/var/log/httpd/post.log';
## testing server INSERT SERVER NAME
### Here is where you want to redirec to a test server
$serverPOSTTEST = 'INSERT SERVER NAME';
#### URL POST Path
$serverPOSTPATHTEST = '/cgi-bin/secure.cgi';
$serverPOSTPATH2TEST = '/cgi-bin/secure1.cgi';
$siteTESTPORT = '80';
### real servers after you post
## Production server one
## POrt to post to example 80 443 8000 etc
$sitePRODPORT = '8000';
## server URL
$serverPRODPOST = 'someone.atsomewhere.com';
## File to post to
$serverPRODPOSTPATH = '/dir1/dir2/file.pl';
## Production Server two
## POrt to post to example 80 443 8000 etc
$siteSTAGEPORT = '8000';
## server URL
$serverSTAGEPOST = '/dir1/dir2/file.pl';
## File to post to
$serverSTAGEPOSTPATH = '/dir1/dir2/file.pl';
###############################################################
### change here to post to prod1 or Prod2 or Testing server
$URLsite = $serverPRODPOST;
$URL2site = $serverSTAGEPOST;
#
$POSTPATH = $serverPRODPOSTPATH;
$POSTPATH2 = $serverSTAGEPOSTPATH;
#
$port2 = $sitePRODPORT;
$port = $siteSTAGEPORT;
###############################################################
### If you want to post to both at the same time
### Change from 0 to 1. If only one post enable then
### First on the list ("URLsite") will get the post
###############################################################
$all_URLsite = 1;
###############################################################
# Required for perl5.
use Socket;
use LWP;
use HTTP::Cookies;
###############################################################
# read POST data from STDIN
read STDIN, $temp, $ENV{'CONTENT_LENGTH'};
###############################################################
# We first remove the POST VALUE of "Comments="
# This is only used in testing mode with a post
# from a web page to test the script
# The post page can be found in the same folder
# where this script is located and is called index.html
###############################################################
# $temp=~s/Comments=/""/eg;
###############################################################
#get a second copy of the post
###############################################################
$temp2 = $temp;
$temp3 = $temp2;
###############################################################
## For testing and DEBUG from a web page we print
## back as a response from a post
## for KEY or for the Entire post TEMP
# print "Server Name: ", $ENV{'SERVER_NAME'}, "\n";
# print "Running on Port: ", $ENV{'SERVER_PORT'}, "\n";
# print "Server Software: ", $ENV{'SERVER_SOFTWARE'}, "\n";
# print "Server Protocol: ", $ENV{'SERVER_PROTOCOL'}, "\n";
# print "CGI Revision: ", $ENV{'GATEWAY_INTERFACE'}, "\n";
# print "The length of the data (in bytes) $ENV{'CONTENT_LENGTH'}\n";
# print "[$site] [$port] [$sitePROD] [$siteSTAGE]\n";
# print "$temp2.\n";
###############################################################
#### Here is the real post and write to file###################
#### First choice we convert back from URL Encode
#### The second we leave as is (i.e URL ECONDED)
###############################################################
##### $temp = URL EN CODED
##### $temp2 = URL DE CODED
##### $temp3 = URL EN CODED
###############################################################
# Get post to file as it comes URL ENCODED
open(INFILE, ">>$DATA1")|| print "$DATA1 can't open ($!)<br>";
flock(INFILE,$exclusive_lock);
select(INFILE);
print "$temp.\n";
close(INFILE);
# We post to file after we convert back from URL ENCODED POST
# First we Translate + to spaces
$temp2=~s/\+/ /g;
# Second we translate %xx codes to characters
$temp2=~s/%([0-9a-f]{2})/pack("c",hex($1))/gie;
# Now we remove those control M's from the end of the lines
$temp2=~ s/\cM\n/\n/g;
# Now we post to file
open(INFILE2, ">>$DATA2")|| print "$DATA2 can't open ($!)<br>";
flock(INFILE2,$exclusive_lock);
select(INFILE2);
print "$temp2.\n";
close(INFILE2);
###############################################################
# We now post via HTTP POST to Production and to Stage
# We first get the size of the POST and we start posting
# to PROD first then TO STAGE
# If posting fails and e-mail will be sent out
###############################################################
$form = $temp3;
$len = (length $form);
&post_STAGE if $form;
&post_PROD if $form;
&E_MAIL if ($mail eq '1');
sleep(2), exit (0);
# End of postings
###############################################################
### Begin Sub-routines for posting data to server
# Open a socket and post the data
## This script now supports cookies from servers !!!!
###############################################################
sub post_STAGE {
$agent = LWP::UserAgent->new();
$agent->agent($USERagent);
unless($agent->cookie_jar) {
$agent->cookie_jar(HTTP::Cookies->new('file'=>'cookies.txt',
'autosave'=>'true'));
}
$postUrl = sprintf("http://%s:%s%s", $URLsite, $port, $POSTPATH);
$request = HTTP::Request->new('POST'=>$postUrl);
$request->content_type('application/x-www-form-urlencoded');
$request->content($temp3);
$response = $agent->request($request);
if ($response->is_success) {
$mail = 0;
} else {
$mail = 1;
$server_failed = $URLsite;
&E_MAIL;
}
printf ("%s\n", $response->content);
if ($postlog) {
open(OUT,">>$postlog") || warn "Can't open $postlog: $!\n";
printf OUT ("%s\n", $response->content);
close(OUT);
}
}
################################################################
## Get IP Address for the server we are posting.
################################################################
#sub getIP_for_host {
# local($host) = @_;
# local(@ary);
# @ary = gethostbyname($host);
# return(unpack("C4",$ary[4]));
#}
###############################################################
# Post
###############################################################
sub post_PROD {
$URLsite = $URL2site;
$port = $port2;
$POSTPATH = $POSTPATH2;
&post_STAGE if ($all_URLsite eq '1');
}
###############################################################
# Mail Option
###############################################################
sub E_MAIL {
if ($mail eq '1') {
open (MAIL, "|$mailprog $mailto") || die "Can't open $mailprog!\n";
print MAIL "Reply-to: $mailto\n";
print MAIL "From: $from\n";
print MAIL "Subject: Post LIVE server data FAILED !!!!!!!\n\n";
print MAIL "POST to $server_failed FAILED!!!! Server DEAD?\n";
print MAIL "------------------------------------------------------\n";
print MAIL "Submitted at: $date\n";
close (MAIL);
}
}
###############################################################


-----Original Message-----
From: Daniel Lopez [mailto:***@rawbyte.com]
Sent: Thu 9/25/2003 6:03 AM
To: modproxy-***@apache.org
Cc:
Subject: Re: Is this proxying possible
Post by Børge Nilsen
I have a little problem that I though I could solve in a simple way using
apache, but after going through the documentation I am not so sure...
Basically the problem is that on my server I get some POST messages that I
a: log the entire message to the file system
b. add a field to the message itself (ideally within the http body)
c. proxy the message to another server/ port for processing
My first idea was that this could be done with a few rewrite rules and a
perl script, but I'm beginning to get som doubts. Is there anyone out there
that could help me...please...?
mod_rewrite does nto allow you to change the body,
If you are using Apache 2, you can write an input filter (if you are using
mod_perl, php or any other module that exposes the filtering API) or try and
use http://httpd.apache.org/docs-2.0/mod/mod_ext_filter.html
(works for output filtering, not sure it will work for input fitlering)

If you have Apache 1.3 and are using PHP or mod_perl or another solution,
you may be able to just acept the POST, issue teh request yourself using the
HTTP client libraries of PHP or Perl and then return the result to your users)

Cheers

DAniel


--
Teach Yourself Apache 2

Loading...