home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
OS/2 Shareware BBS: 35 Internet
/
35-Internet.zip
/
srev13g.zip
/
sreproxy.80
< prev
next >
Wrap
Text File
|
1999-06-26
|
15KB
|
507 lines
/* 27 June 1999
SRE-http: A "proxy-like" front end for sre-http ver 1.3g.
Provides local cache for sre-http, and returns http/1.1
responses. This is NOT an http (1.0 or 1.1) compliant proxy --
but it has proxy-like features. Plus -- it has limited ssi capabilities,
can do some user-name/pwd lookup, and does all the sre-http postfiltering.
See SREPROXY.DOC for details.
There is one user changable parameter:
SAY_IS_PROXY:
If say_is_proxy=1, then a '[@proxy]' is added to the SERVER: response header
This can be a useful debugging trick (but it does slow things down a little bit)
*/
parse arg source, request , seloriginal
sel3=seloriginal
request0=request
jsend=0
if request='' then return 'NODATA NOWAIT NORESPONSE'
SAY_IS_PROXY=1
/*set exception handler */
signal on syntax name goterr;signal on error name goterr
signal on halt name goterr;call on failure name goterr2
parse var source myaddr port transaction who whoport . /* Often useful */
parse var request verb uri protocol . /* split up the request line */
sreproxy=value('SREF_PROXY',,'os2environment')
moreinfo=''
enmadd="SREF_"||port||"_"
IF TRANSACTION=1 THEN DO
if sreproxy='' then aa=value('SREF_PROXY',-2,'os2environment') /* -2 signals initialize */
end
dodebug=value("SREF_DEBUG",,'os2environment')
verbose=get_value('VERBOSE')
if dodebug=1 then say "!DEB:PXY "||left(transaction,5)' 'left(time('l'),11)' 'left(seloriginal,25)
if sreproxy<>1 then signal gomain
if abbrev(seloriginal,'!')=1 then do
signal gomain
end
if upper(verb)<>'GET' then signal gomain /* only do it for GET */
foo=make_semmi()
if foo=-1 then signal gomain
/* check cache */
hname=get_host_info(protocol) /* get host nickname */
if moreinfo=-1 then signal gomain /* let main handle errors */
reqnum=extract('request')
/* check cache, if not here, gomain */
dastuff=check_cache(hname,seloriginal)
if dastuff=-1 then moreinfo=''
if dastuff=-1 | dastuff=0 then signal gomain /* -1= error, 0=no found */
/* if te: header, that contains gzip or identity;q=0, then proxy can't do it */
ote=reqfield('TE')
if ote<>'' then do
if pos('GZIP',upper(ote))>0 then do
if value('SREF_SUPPRESS_GZIP_TE',,'os2environment')=0 then signal gomain
end
end
if verbose>3 then call pmprintf_sref('SREPROXY: from cache: 'seloriginal)
/* if Unmodified-Since of If-Match, then gomain (odd conditions) */
if reqfield('Unmodified-Since')<>'' | reqfield('If-Match')<>'' then signal gomain
crlf='0d0a'x
parse var dastuff cshtype0 (crlf) dafile0 (crlf) ctype (crlf) ,
lastmod (crlf) etag (crlf) ,
amaxage(crlf) headers
parse var amaxage maxage ',' nopostf
parse var cshtype0 cshtype goscache ','reqprivs
cshtype=strip(cshtype); goscache=strip(goscache)
parse var dafile0 dafile ','trigfile;dafile=strip(dafile); trigfile=striP(trigfile)
if trigfile<>'' then do /* check stamp of dafile against dastamp */
foo=sysfiletree(dafile,'goo1','T')
if goo1.0=0 then signal gomain /* no such cached file */
parse var goo1.1 cstamp . ; cstamp=strip(cstamp)
lapse=0
if abbrev(trigfile,'!TIME'!)=1 then do
tstamp=strip(substr(trigfile,7))
if compdate(cstamp,tstamp)>0 then lapse=1 /* current date > "when cached" date */
end
else do
foo=sysfiletree(trigfile,'goo1','T')
if goo1.0=0 then signal gomain /* no such cached file */
parse var goo1.1 tstamp . ; tstamp=strip(tstamp)
if compdate(tstamp,cstamp)>0 then lapse=1 /* trigger (original) file newer then cached version of file */
end
if lapse=1 then do
if verbose>2 then call pmprintf_Sref('SREPROXY -- trigger file newer then cached file')
signal gomain /* trigger file newer then cache */
end
if verbose>2 then call pmprintf_sref(' SREPROXY using 'dafile' ('trigfile')')
end
/* note: cshtype: 0= public static , 1= public semi-dynamic
2= private static , 3=private semi-dynamic
0 1= public static w/ goserve cache */
/* perhaps use etag and lastmod for conditional gets */
ifnone=reqfield("If-none-match")
if ifnone<>'' then do /* check If-none-match */
ifnone=translate(ifnone,' ','",')
etagmatch=wordpos(upper(etag),upper(ifnone))
if etagmatch=0 then etagmatch=wordpos('*',ifnone)
if etagmatch>0 then do
'RESPONSE HTTP/1.1 304 Not Modified Etag'
'HEADER ADD Content-type: 'ctype
'NODATA '
rstatus='304 0'
if verbose>3 then call pmprintf_sref(' SREPROXY using 304 etag ')
signal gopostf
end
end
else do /* check if-modified-since */
ifmod=reqfield('If-modified-since')
if ifmod<>'' then do
fatt=sref_gmt(,lastmod,'J')
modabs=sref_gmt(,ifmod,'J')
numeric digits 11
if fatt<=modabs then do
'RESPONSE HTTP/1.1 304 Not Modified '
'HEADER ADD Content-type: 'ctype
'NODATA '
rstatus='304 0'
if verbose>3 then call pmprintf_sref(' SREPROXY using 304 not modified ')
signal gopostf
end
end
end
/*if private (cshtype>1), then quick check on privileges etc. may be needed */
if cshtype>1 then do
checklog=get_value('CHECKLOG')
allow_access=strip(upper(get_value('ALLOW_ACCESS')))
aok=sref_check_allowed(reqprivs,mysem,myqueue,enmadd,transaction,hname,checklog,allow_access)
if aok=0 then signal gomain
end
/* if here, do return file from cache -- possibly range */
if verbose>3 then call pmprintf_sref(' SREPROXY cache hit is 'dafile)
adate=sref_gmt()
filen=stream(dafile,'c','query size')
tempdata_dir=get_value('TEMPDATA_DIR')
tdir=strip(TEMPDATA_DIR,'t','\')||'\'
tempfile2=tdir'$'reqnum'.'port /* For use in postfilter */
/* check allow range */
rstatus=0
if cshtype=0 then do
alrange=upper(get_value('ACCEPT_RANGE'))
if wordpos(alrange,'Y YES 1')>0 then do /* check for ranges header */
oo=reqfield('range')
if oo<>'' then do /* see if it can be handled */
i00=extract('bytessent')
'HEADER NOAUTO ADD Date: 'adate
'HEADER ADD Cache-Control: public,max-age='maxage
if say_is_proxy=1 then headers=mod_headers(headers)
if headers<>'' then 'HEADER ADD 'headers
rstatus=sref_process_range(dafile,ctype,filen,lastmod,etag,verbose)
if rstatus=416 then signal gomain /* accept error, let main handle it*/
end
end
end
/* not a range request */
if rstatus=0 then do
'RESPONSE HTTP/1.1 200 Ok.' /*http/1.1 is now the default response */
'HEADER NOAUTO ADD Date: 'adate
'HEADER ADD Cache-Control: public,max-age='maxage
if say_is_proxy=1 then headers=mod_headers(headers)
if headers<>'' then do
'HEADER ADD 'headers
end
goo=extract('bytessent')
if cshtype=1 | cshtype=3 then do /* do semi-dynamic ssis */
if verbose>3 then call pmprintf_sref(' SREPROXY: semi-dynamic hit ')
if stream(dafile,'c','query exists')='' then signal gomain /* missing cache file */
vvs=sref_semi_ssis(dafile,seloriginal,who,mysem,myqueue,enmadd, ,
transaction,servername,port)
'var type 'ctype ' name vvs'
if rc=-7 then
jsend=extract('bytessent')-goo
else
jsend=length(vvs)
rstatus='200 '||jsend
end
else do
noc='nocache '
if goscache=1 then noc=' '
'FILE 'noc' type 'ctype ' name 'dafile
if rc=-7 then
jsend=extract('bytessent')-goo
else
jsend=stream(dafile,'c','query size')
rstatus='200 '||jsend
end
end
/* DO POSTFILTERING */
gopostf: nop
if dodebug=1 then say "!DEB:PX2 "||left(transaction,5)' 'left(time('l'),11)' posfilter'
if verbose>2 then call pmprintf_sref(' SREPROXY status: 'rstatus)
ssize=value('SREF_PROXY_BYTES',,'os2environment')
if datatype(ssize)<>'NUM' then ssize=0
foo=value('SREF_PROXY_BYTES',ssize+jsend,'os2environment')
sct=value('SREF_PROXY_HITS',,'os2environment')
if sct='' then sct=0
foo=value('SREF_PROXY_HITS',sct+1,'os2environment')
if nopostf<>1 then call do_post_filter
return ' '
/* here if not in cache, or error, or ... */
gomain:
if sreproxy<>1 then do
if verbose>2 then say ' SREPROXY: Calling SREFILTR'
FOO=SREFILTR(SOURCE,REQUEST,SEL3)
end
else do
if verbose>2 then call pmprintf_sref(' SREPROXY: Calling SREFILTR-macrospace for: 'sel3)
goon=extract('bytessent')
foo=sref_srefiltr(source,request,sel3,moreinfo)
goon2=extract('bytessent')
jsend=goon2-goon
end
ssize=value('SREF_PROXY_BYTES2',,'os2environment')
if ssize='' then ssize=0
foo=value('SREF_PROXY_BYTES2',ssize+jsend,'os2environment')
sct=value('SREF_PROXY_HITS2',,'os2environment')
if sct='' then sct=0
foo=value('SREF_PROXY_HITS2',sct+1,'os2environment')
return ''
/********/
/* here on error */
goterr:
say " error in sreproxy filter "sigl', 'rc
call pmprintf(" error in sreproxy filter "sigl', 'rc)
exit
/*****************************/
/* get host,datadir, & servername for this requesete */
get_host_info:procedure expose moreinfo SELORIginal uri enmadd myaddr servername
parse arg protocol
stuff=sref_host_info(myaddr,enmadd,uri,protocol)
if strip(stuff)='BAD' then return -1 /* if http/1.1 client did not include at host: header */
if stuff<>0 then do
parse var stuff servername ',' host_nickname ',' ddir
host_nickname=strip(host_nickname); ddir=strip(ddir)
servername=strip(servername)
end
else do
ddir=datadir()
servername=servername()
host_nickname=' '
STUFF=servername ',' host_nickname ',' ddir
end
if abbrev(upper(uri),'HTTP://')>0 then do
parse var uri . '//' . '/' uri
if uri='' then uri='/'
parse var seloriginal . '//' . '/' seloriginal
end
moreinfo=stuff
return host_nickname
/********************************/
/* checks sreproxy cache */
check_cache:procedure expose enmadd mysem myqueue reqnum
parse arg hname,sel
if left(sel,1)='!' then do
if abbrev(upper(sel),'!SEND')<>1 then return 0 /* do NOT cache special codes */
end
if hname<>'' then
eek=hname'//'sel
else
eek=sel
eek=upper(eek)
goober='SREF_SREPROXY'
a=rxqueue('s',goober)
queue reqnum','myqueue','mysem',L,'EEK
a=eventsem_reset(mysem)
dothread='\SEM32\SREF_SREPROXY'
a=eventsem_post(dothread)
a=eventsem_wait(mysem)
if a<>0 then do
sss=sref_error(' A Fatal Semaphore failure in SREPROXY: 'a,1)
return -1
end
a=rxqueue('s',myqueue)
parse pull aline
PARSE VAR ALINE idnum ',' aline
idnum=strip(translate(idnum,' ','000d0a'x));TRANSACTION=STRIP(TRANSACTION)
if idnum<>reqnum then do /*wierd error: got someone else's message, give up */
say ' Read odd id from sreproxy queue :' idnum0 ',' idnum
return -1
end
aline=strip(aline)
return aline
/***************/
/* create a personallized queue & semaphore */
make_semmi:procedure expose mysem myqueue enmadd
mytid=dostid()
mysem='\SEM32\'||enmadd||"t"||mytid
myqueue=enmadd||'t'||mytid
a=rxqueue('s',myqueue)
signal off syntax ; signal off error ;signal on syntax name badq ; signal on error name badq
queue 0
yyq=queued()
if yyq>100 then return -1 /* gunked up, let main to it */
do mmy=1 to yyq
pull poo .
end
wow=eventsem_query(mysem)
if wow=-187 then return -1 /* odd semaphore, let main do it */
foo=eventsem_reset(MYSEM)
signal off syntax ; signal off error
signal on syntax name goterr;signal on error name goterr
return 1
badq:
return -1
/* ----------- */
/* get environment value, possibly host specific
hname=0 -- do not look under hostname
hname=1 -- do not look under default
*/
/* ------------ */
get_value: procedure expose enmadd hname
parse arg vname
vname=strip(vname) ;
if hname<>' ' then do
booger=strip(enmadd||vname||'.'||hname)
aval=value(booger,,'os2environment')
if aval<>' ' Then return aval
end
aval=value(enmadd||vname,,'os2environment')
return aval
/*****************/
/* jump here for postfilter */
do_post_filter:
postfilter_name=get_value('POSTFILTER_NAME')
post_filter=strip(get_value('POST_FILTER'))
write_logs=strip(get_value('WRITE_LOGS'))
/* save some extra stuff to the request specific variables (if a post_filter might
use it */
if post_filter=1 then do
if pos(',',seloriginal||request)=0 then do
foo=sref_value('SOURCE SEL REQUEST ',source','sel3','request,'REQ',reqnum,,enmadd)
end
else do
foo=sref_value('SOURCE',source,'REQ',reqnum,,enmadd)
foo=sref_value('SEL',sel3,'REQ',reqnum,,enmadd)
foo=sref_value('REQUEST',request,'REQ',reqnum,,enmadd)
end
end
record_option=strip(get_value('RECORD_OPTION'))
/* check for owner suppression */
chkowner=get_value('HIT_OWNER_SUPPRESS')
if chkowner=1 then do
owners=get_value('Owners')
if wordpos(who,owners)>0 then record_option='NO'
end
if (record_option="NO" & post_filter=0 & write_logs=0) then do /* nothing to do in post filter */
return ' '
end
record_all_file=get_value('RECORD_ALL_FILE',0)
selrec=sref_replacestrg(sel3,',','%2c','ALL')
request0=sref_replacestrg(request,',','%2c','ALL')
post_filter_message='SREPROXY resolved request: 'rstatus
browser=' ';authuser=' '
thereferer=reqfield('referer')
clientname0=sref_clientname(who,mysem,myqueue,'/SEM32/'||enmadd,enmadd,transaction)
browser=reqfield('user-agent')
authuser='-'
dec=sref_extract_upwd()
if dec<>'' then parse upper var dec authuser ':' . /* split to userid, if basic */
a=rxqueue('s',enmadd||'POSTF')
queue record_option ',' record_all_file ',' post_filter ',' postfilter_name ',' port ',' ,
post_filter_message ',' source ',' request0 ',' 0' 'selrec ',' ,
tempfile2 ',' servername ',' hname ',' afile ',' who ',' ,
enmadd ',' thereferer ',' reqnum ',' RSTATUS ',' write_logs ',' ,
clientname0 ',' authuser ',' browser ',' verbose
aa=eventsem_post('/SEM32/'||enmadd||'POSTF')
return ' ' /* note that postfilter and recorder don't need to tell the filter anything*/
/**************************/
/**************************/
/******************/
/* add " @pxy " to server: header */
mod_headers:procedure expose crlf
parse arg ah
ah0=''
do until ah=""
parse var ah a1 (crlf) ah
if a1='' then iterate
a1a=strip(upper(a1))
if abbrev(a1a,'SERVER')=0 then do
if ah0="" then
ah0=ah0||a1
else
ah0=ah0||crlf||a1
iterate
end
ah0=ah0||crlf||a1||' [@proxy]'
end
return ah0
/*****************/
/* compare "ordered" (yy/mm/dd/hh/ss) dates, with y2k correction */
compdate:procedure
parse arg a,b
a=strip(a); b=strip(b)
if left(a,2)<80 then
a="1"||a
else
a='0'||a
if left(b,2)<80 then
b="1"||b
else
b='0'||b
if a>b then return 1
return 0