[REBOL] Re: POST examples ...
From: gjones05:mail:orion at: 4-Jun-2001 10:48
From: "Petr Krenzelok"
...
> I thought I will kill someone for putting "function" into website in
> lowercase. I spent nearly one hour figuring out what is the problem
....
I think we've all had that happen. Frustrating.
> yes, but I am not using ftp. I am using http post method, so I don't
know if
> such aproach is even possible ...
OK, not trying to beat a dead horse here, but what the heck.
The same principle can be applied to http get requests. This example
grabs the second half of Microsoft's home page.
from-port: open/direct http://www.microsoft.com
to-port: open/direct %//windows/desktop/log.txt
from-port: skip from-port 8000
while [data: copy/part from-port 1000][append to-port data]
close from-port
close to-port
However, you need to make the request with a 'post request, so I
shamelessly hacked Martin Johannesson's http-post.r (the original url is
no longer correct, so I also updated it). I commented the major changes
so that you could see what I've done compared to the original. You will
see that this method could be readily cleaned up and made more generic
and encapsulated. Watch for wrapped lines!!!
;=============================
REBOL [
Title: "Simple HTTP POST"
File: %http-post.r
Author: "Martin Johannesson"
Email: [d95-mjo--nada--kth--se]
Date: 30-Jun-1999
Purpose: {
This script sends a "form" to a webserver using the POST
method. The included example translates a string in English
to German by posting the data to AltaVista's translation
web page and then parsing the reply.
}
Category: [web util net 4]
Comment: {Shamelessly hacked by Scott Jones for demonstrating
tight http control for my good, friend Petr Krenzelok ;-}
]
url-encode: func [
{URL-encode a string}
data "String to encode"
/local new-data
][
new-data: make string! ""
normal-char: charset [
#"A" - #"Z" #"a" - #"z"
#"@" #"." #"*" #"-" #"_"
#"0" - #"9"
]
if not string? data [return new-data]
forall data [
append new-data either find normal-char first data [
first data
][
rejoin ["%" to-string skip tail (to-hex to-integer first
data) -2]
]
]
new-data
]
http-post-form: func [
{Post a form to a web server}
url "The URL to post to"
data [block!] "A block of name/value pairs to represent the form"
/local
encoded-data
port-spec
HTTP-Post-Header
http-request
buffer
tmp-buffer
][
port-spec: make port! [
scheme: 'tcp
port-id: 80
timeout: 0:10
]
net-utils/url-parser/parse-url port-spec url
encoded-data: make string! ""
foreach [name value] data [
append encoded-data rejoin [
url-encode name "=" url-encode value "&"
]
]
remove back tail encoded-data
HTTP-Post-Header: make object! [
Accept: "*/*"
User-Agent: reform ["REBOL" system/version]
Host: port-spec/host
Content-Type: "application/x-www-form-urlencoded"
Content-Length: length? encoded-data
]
http-request: rejoin [
"POST /"
either found? port-spec/path [port-spec/path][""]
either found? port-spec/target [port-spec/target][""]
" HTTP/1.0^/"
net-utils/export HTTP-Post-Header "^/"
encoded-data
]
;dropped lines refinement and added direct
http-port: open/direct [
scheme: 'tcp
port-id: port-spec/port-id
timeout: port-spec/timeout
host: port-spec/host
user: port-spec/user
pass: port-spec/pass
]
;inserts 'post request
insert http-port http-request
;now grabbing header stuff 1 byte at a time
;so that we can get content length
;look for two newlines in a row
data: make string! 1000
while [not parse/all data [to "^/^/" to end]][
append data copy/part http-port 1
]
;parses out the content length into ret-length
;which is left as a string for now
parse data [thru "Content-Length: " copy ret-length to "^/" to end]
;print ret-length
;now get the rest of the file in what ever proportions you want
data: make string! 1000
l-port: open/direct %//windows/desktop/log.txt
;uncomment the next line if you wish to skip some amount of info
;http-port: skip http-port 2000
while [data: copy/part http-port 1000][append l-port data]
close http-port
close l-port
comment {
buffer: make string! 10000
tmp-buffer: reform ["HTTP-Response:" pick http-port 1]
while [not none? tmp-buffer] [
append buffer rejoin [tmp-buffer "^/"]
tmp-buffer: pick http-port 1
]
close http-port
}
HTTP-Header: make object! [
HTTP-Response: Date: Server: Last-Modified: none
Accept-Ranges: Content-Encoding: Content-Type: none
Content-Length: Location: Expires: Referer: Connection: none
]
; parse-header HTTP-Header buffer
]
english-to-german: func [
{Translates a string in English to German, using
babelfish.altavista.com}
english-text "String in english"
][
not-lt-gt: complement charset [#"<" #">"]
tag-rule: ["<" some not-lt-gt ">"]
tmp: http-post-form http://babelfish.altavista.com/tr reduce [
"doit" "done"
"urltext" english-text
"lp" "en_de"
]
comment {
if none? find tmp/HTTP-Response "200" [return join "Error: "
tmp/HTTP-Response]
either parse tmp/content [
thru "Auf Deutsch:" to "<font" thru ">" copy trans to "<" to end
][
return trans
][
return "Error: Unable to parse Babelfish HTML"
]
}
]
english-to-german "hello, how are you?"
;===============================
> One crazy thought: would it be possible to use http port 'awake field
for
> calling the fucntion, which would count current buffer size and could
update
> the progress bar?
It seems like there should be some way, knowing the total length and the
chunk lengths.
Hope this one helps *and* solve the problem.
--Scott Jones