factor/extra/http/client/client.factor

112 lines
2.9 KiB
Factor
Raw Normal View History

! Copyright (C) 2005, 2008 Slava Pestov.
2007-09-20 18:09:08 -04:00
! See http://factorcode.org/license.txt for BSD license.
USING: assocs http kernel math math.parser namespaces sequences
2008-02-09 22:34:42 -05:00
io io.sockets io.streams.string io.files io.timeouts strings
splitting calendar continuations accessors vectors math.order
2008-05-05 04:51:41 -04:00
io.encodings.8-bit io.encodings.binary io.streams.duplex
2008-06-02 16:00:03 -04:00
fry debugger inspector ascii urls ;
2007-09-20 18:09:08 -04:00
IN: http.client
: max-redirects 10 ;
ERROR: too-many-redirects ;
M: too-many-redirects summary
drop
[ "Redirection limit of " % max-redirects # " exceeded" % ] "" make ;
2008-03-07 18:21:20 -05:00
DEFER: http-request
<PRIVATE
SYMBOL: redirects
2008-06-02 16:00:03 -04:00
: redirect-url ( request url -- request )
'[ , >url derive-url ensure-port ] change-url ;
2008-05-05 18:31:46 -04:00
: do-redirect ( response data -- response data )
over code>> 300 399 between? [
drop
redirects inc
redirects get max-redirects < [
2008-05-05 18:31:46 -04:00
request get
2008-06-02 16:00:03 -04:00
swap "location" header redirect-url
2008-05-05 18:31:46 -04:00
"GET" >>method http-request
2008-02-25 15:53:18 -05:00
] [
too-many-redirects
] if
2008-05-05 18:31:46 -04:00
] when ;
2007-09-20 18:09:08 -04:00
2008-02-25 15:53:18 -05:00
PRIVATE>
2007-09-20 18:09:08 -04:00
: read-chunk-size ( -- n )
read-crlf ";" split1 drop [ blank? ] right-trim
hex> [ "Bad chunk size" throw ] unless* ;
2008-05-05 18:31:46 -04:00
: read-chunks ( -- )
read-chunk-size dup zero?
2008-05-05 18:31:46 -04:00
[ drop ] [ read % read-crlf "" assert= read-chunks ] if ;
: read-response-body ( response -- response data )
dup "transfer-encoding" header "chunked" =
[ [ read-chunks ] "" make ] [ input-stream get contents ] if ;
: http-request ( request -- response data )
2008-03-07 18:21:20 -05:00
dup request [
dup url>> url-addr latin1 [
1 minutes timeouts
write-request
2008-03-07 18:21:20 -05:00
read-response
2008-05-05 18:31:46 -04:00
read-response-body
] with-client
do-redirect
2008-03-07 18:21:20 -05:00
] with-variable ;
2008-03-07 18:21:20 -05:00
: <get-request> ( url -- request )
2008-05-05 18:31:46 -04:00
<request>
2008-06-02 16:00:03 -04:00
"GET" >>method
swap >url ensure-port >>url ;
2008-05-05 18:31:46 -04:00
: http-get* ( url -- response data )
<get-request> http-request ;
2007-09-20 18:09:08 -04:00
: success? ( code -- ? ) 200 = ;
2007-09-20 18:09:08 -04:00
ERROR: download-failed response body ;
M: download-failed error.
"HTTP download failed:" print nl
[
response>>
write-response-code
write-response-message nl
drop
]
[ body>> write ] bi ;
: check-response ( response string -- string )
over code>> success? [ nip ] [ download-failed ] if ;
: http-get ( url -- string )
2008-05-05 18:31:46 -04:00
http-get* check-response ;
: download-name ( url -- name )
file-name "?" split1 drop "/" ?tail drop ;
: download-to ( url file -- )
2007-09-20 18:09:08 -04:00
#! Downloads the contents of a URL to a file.
2008-05-26 01:47:27 -04:00
[ http-get ] dip latin1 [ write ] with-file-writer ;
: download ( url -- )
dup download-name download-to ;
2007-09-20 18:09:08 -04:00
2008-03-07 18:21:20 -05:00
: <post-request> ( content-type content url -- request )
2008-02-29 01:57:38 -05:00
<request>
2008-05-05 18:31:46 -04:00
"POST" >>method
2008-06-02 16:00:03 -04:00
swap >url ensure-port >>url
2008-05-05 18:31:46 -04:00
swap >>post-data
swap >>post-data-type ;
2008-02-25 15:53:18 -05:00
2008-05-05 18:31:46 -04:00
: http-post ( content-type content url -- response data )
<post-request> http-request ;