#!/usr/bin/perl # # Packetizer Web Services Proxy (pwsp) # (Version 2.0) # # Copyright (C) 2009 # Packetizer, Inc. # # This script will accept requests from clients and then forward them # to services.packetizer.com. This is necessary since web browsers # enforce a "same origin" policy which prevent them from loading # pages from one domain and then accessing a different domain. # # As a very light-weight proxy, this code is intended to mimic the behavior # as one would see it if accessing services.packetizer.com directly, # though there is one important difference: one must specify the # service desired via a URI parameter. For example, to access the # "time" service, one might access a URL like this: # http://www.packetizer.com/cgi-bin/pwsp?service=time&f=text # # Of course, the sample URL above would be different for your # own web site. Place this script in your cgi-bin directory # and you should be all set. # # This CGI script was written for Apache, so some changes might be required # to work with other web servers. # use CGI; use URI::Escape; use IO::Socket; # Specify what to do when an alarm signal is received $SIG{ALRM} = sub { die "socket timeout\n"; }; # URI template for Packetizer Web Services $services_server = "services.packetizer.com"; $services_port = 80; $location = "/{service}/"; $query = new CGI; # # Look through the various parameters and extract the service parameter, # preserving all of the other parameters # $init_param = 1; $query_string = ""; foreach $param ($query->param) { if ($param eq "service") { $service = $query->param($param); } else { if ($init_param) { $init_param = 0; } else { $query_string .= "&"; } $query_string .= uri_escape($param); $query_string .= "="; $query_string .= uri_escape($query->param($param)); } } # # If a service was specified, then let's try to invoke the service # if (length($service) > 0) { $location =~ s/{service}/$service/; if (length($query_string) > 0) { $location .= "?" . $query_string; } $retries = 3; while($retries > 0) { $remote = IO::Socket::INET->new( Proto => "tcp", PeerAddr => "$services_server", PeerPort => "$services_port"); last if ($remote); $retries--; sleep(4); } unless ($remote) { die "could no connect to remote server"; } print $remote "GET $location HTTP/1.1\r\n"; # Produce the headers that of significance to Packetizer Web Services if (length($ENV{'HTTP_ACCEPT'})) { print $remote "Accept: " . $ENV{'HTTP_ACCEPT'} . "\r\n"; } if (length($ENV{'HTTP_USER_AGENT'})) { print $remote "User-Agent:" . $ENV{'HTTP_USER_AGENT'} . "\r\n"; } if (length($ENV{'HTTP_ACCEPT_LANGUAGE'})) { print $remote "Accept-Language:" . $ENV{'HTTP_ACCEPT_LANGUAGE'} . "\r\n"; } if (length($ENV{'HTTP_ACCEPT_ENCODING'})) { print $remote "Accept-Encoding:" . $ENV{'HTTP_ACCEPT_ENCODING'} . "\r\n"; } print $remote "Host: $services_server\r\n"; print $remote "Connection: close\r\n"; print $remote "\r\n"; # Let's not wait too long for a reply, treating lengthy delays as a # 500 Internal Server error alarm(8); $discard = <$remote>; while(<$remote>) { print; } close($remote); # Turn off the alarm alarm(0); } else { print "Status: 404\r\n"; print "Content-Type: text/plain; charset=utf-8\r\n"; print "\r\n"; print "No service was specified.\n"; }