|
echo $fn ?>
|
|
../code/xhr.cls/var/www/html/ooRexx/wip
#!/usr/bin/rexx
/* --------------------------------------------------------------------------------------- */
/* No freakin' copyright, no stinkin' license, no guarantees or warrantees */
/* (implied, explicit or whatever). Usage is totally and completely at your own risk. */
/* Please keep this comment block as is if modifying this code. Thanks in advance, */
/* Ruurd Idenburg */
/* --------------------------------------------------------------------------------------- */
::class xhr public
-- using attributes without‘expose’, so that methods are free in choosing variable names
::attribute host get
::attribute host set private
::attribute port get
::attribute port set private
::attribute socket get
::attribute socket set private
::attribute reqHeaders get
::attribute reqHeaders set private
::attribute hostname get
::attribute hostname set private
::attribute rspHeaders get
::attribute rspHeaders set private
::attribute response get
::attribute response set private
::method init
use strict arg host, port=80
self~hostname = host
self~port = port
self~host = .inetaddress~new(host,port)
self~rspHeaders = .array~new
exit
::method doHeaders private
self~reqHeaders = .array~new
self~addHeader('Host:' self~hostname)
self~addHeader('User-Agent: Not My Browser 0.9')
self~addHeader('Accept: */*')
exit
::method get -- HTTP/1.1 GET with support for Content-Length: or Transfer-Encoding: chunked
use strict arg query
self~socket = .socket~new
if self~socket~connect(self~host)<0 then do
raise syntax 48.900 array('Socket connection to' self~hostname 'on port' self~port 'failed')
end
self~doHeaders
request = 'GET' query 'HTTP/1.1' || '0d0a'x || self~reqHeaders~makeString(,'0d0a'x) || '0d0a0d0a'x
if self~socket~send(request)<0 then do
raise syntax 48.900 array('Sending request to' self~hostname 'on port' self~port 'failed')
end
recvLength = 1024
response = self~socket~recv(recvLength)
if response==.nil then do
if self~socket~errno<0 then do
raise syntax 48.900 array('Receiving response from' self~hostname 'on port' self~port 'failed')
end
else do
raise syntax 48.900 array('Socket on' self~hostname 'on port' self~port 'already closed')
end
end
parse var response headers '0d0a0d0a'x data
parse var headers . 'Content-Length:' length '0d0a'x .
if length=='' then do
parse var headers . 'Transfer-Encoding:' how '0d0a'x .
if how='chunked' then do
data = self~getChunked(data)
end
else do
raise syntax 48.900 array('Unsupported Transfer-Encoding:' how)
end
end
else do (length>data~length) -- if we need to receive more content
data = self~getLength(data,length)
end
self~rspHeaders = headers~makeArray('0d0a'x)
self~response = data
if self~socket~close<0 then do
raise syntax 48.900 array('Closing socket for' self~hostname 'on port' self~port 'failed')
end
exit
::method post -- HTTP/1.1 POST, for now copied mostly from GET; will do finetuning/combining later on
use strict arg target,content
self~socket = .socket~new
if self~socket~connect(self~host)<0 then do
raise syntax 48.900 array('Socket connection to' self~hostname 'on port' self~port 'failed')
end
self~doHeaders
self~addHeader('Content-Type: application/x-www-form-urlencoded')
self~addHeader('Content-Length:' content~length)
request = 'POST' target 'HTTP/1.1' || '0d0a'x || self~reqHeaders~makeString(,'0d0a'x) || '0d0a0d0a'x || content
if self~socket~send(request)<0 then do
raise syntax 48.900 array('Sending request to' self~hostname 'on port' self~port 'failed')
end
recvLength = 1024
response = self~socket~recv(recvLength)
if response==.nil then do
if self~socket~errno<0 then do
raise syntax 48.900 array('Receiving response from' self~hostname 'on port' self~port 'failed')
end
else do
raise syntax 48.900 array('Socket on' self~hostname 'on port' self~port 'already closed')
end
end
parse var response headers '0d0a0d0a'x data
parse var headers . 'Content-Length:' length '0d0a'x .
if length=='' then do
parse var headers . 'Transfer-Encoding:' how '0d0a'x .
if how='chunked' then do
data = self~getChunked(data)
end
else do
raise syntax 48.900 array('Unsupported Transfer-Encoding:' how)
end
end
else do (length>data~length) -- if we need to receive more content
data = self~getLength(data,length)
end
self~rspHeaders = headers~makeArray('0d0a'x)
self~response = data
if self~socket~close<0 then do
raise syntax 48.900 array('Closing socket for' self~hostname 'on port' self~port 'failed')
end
exit
::method addHeader -- Allow for user supplied request headers
use strict arg header
self~reqHeaders~append(header)
exit
::method getChunked private
use strict arg chunks
-- The end of content in chunked mode is identified by the last chunk ('0' || '0d0a0d0a'x )
lastChunk = .false
if chunks<>"" then do
lastChunk = (chunks~substr(chunks~length-4)==(0 || '0d0a0d0a'x))
end
do while \lastChunk
nextChunk = self~socket~recv(1024)
if nextChunk==.nil then do
if self~socket~errno<0 then do
raise syntax 48.900 array('Receiving response chunk from' self~hostname 'on port' self~port 'failed')
end
else do
raise syntax 48.900 array('Socket on' self~hostname 'on port' self~port 'already closed')
end
end
chunks ||= nextChunk
lastChunk = (chunks~substr(chunks~length-4)==(0 || '0d0a0d0a'x))
end
data = ''
do until chunks==(0 || '0d0a0d0a'x)
parse var chunks header '0d0a'x chunk '0d0a'x chunks
data ||= chunk
end
return data
exit
::method getLength private
use strict arg content,length
recvLength = length-content~length -- already received part of the content
do while recvLength>0
nextContent = self~socket~recv(recvLength)
if nextContent==.nil then do
if self~socket~errno<0 then do
raise syntax 48.900 array('Receiving response chunk from' self~hostname 'on port' self~port 'failed')
end
else do
raise syntax 48.900 array('Socket on' self~hostname 'on port' self~port 'already closed')
end
end
content ||= nextContent
recvLength -= nextContent~length
end
return content
exit
::requires 'socket.cls'
If you feel inclined to make corrections, suggestions etc.,
please mail me any.
| |
All content © Ruurd Idenburg, 2007– echo date('Y');?>,
except where marked otherwise. All rights reserved. This page is primarily for non-commercial use only.
The Idenburg website records no personal information and sets no ‘cookies’.
This site is hosted on a VPS(Virtual Private System) rented from Transip.nl, a Dutch company, falling under Dutch (privacy) laws (I think).
This page updated on echo date("r", filemtime("./index.php"));?> by Ruurd Idenburg.
|
|