2008-02-22 00:47:06 -05:00
|
|
|
! 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
|
2008-04-26 03:01:43 -04:00
|
|
|
splitting calendar continuations accessors vectors math.order
|
2008-04-22 16:37:49 -04:00
|
|
|
io.encodings.8-bit io.encodings.binary fry debugger inspector ;
|
2007-09-20 18:09:08 -04:00
|
|
|
IN: http.client
|
|
|
|
|
2008-04-22 16:37:49 -04:00
|
|
|
: 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
|
|
|
|
|
2008-02-25 15:53:18 -05:00
|
|
|
: parse-url ( url -- resource host port )
|
|
|
|
"http://" ?head [ "Only http:// supported" throw ] unless
|
2008-03-19 20:15:32 -04:00
|
|
|
"/" split1 [ "/" prepend ] [ "/" ] if*
|
2008-02-25 15:53:18 -05:00
|
|
|
swap parse-host ;
|
2007-09-20 18:09:08 -04:00
|
|
|
|
2008-02-25 15:53:18 -05:00
|
|
|
: store-path ( request path -- request )
|
|
|
|
"?" split1 >r >>path r> dup [ query>assoc ] when >>query ;
|
2007-09-20 18:09:08 -04:00
|
|
|
|
2008-02-25 15:53:18 -05:00
|
|
|
: request-with-url ( url request -- request )
|
|
|
|
swap parse-url >r >r store-path r> >>host r> >>port ;
|
2007-09-20 18:09:08 -04:00
|
|
|
|
2008-03-07 18:21:20 -05:00
|
|
|
! This is all pretty complex because it needs to handle
|
|
|
|
! HTTP redirects, which might be absolute or relative
|
2008-02-25 15:53:18 -05:00
|
|
|
: absolute-redirect ( url -- request )
|
2008-03-07 18:21:20 -05:00
|
|
|
request get request-with-url ;
|
2007-09-20 18:09:08 -04:00
|
|
|
|
2008-02-25 15:53:18 -05:00
|
|
|
: relative-redirect ( path -- request )
|
2008-03-07 18:21:20 -05:00
|
|
|
request get swap store-path ;
|
2007-09-20 18:09:08 -04:00
|
|
|
|
2008-04-22 16:37:49 -04:00
|
|
|
SYMBOL: redirects
|
|
|
|
|
2008-04-23 02:42:30 -04:00
|
|
|
: absolute-url? ( url -- ? )
|
|
|
|
[ "http://" head? ] [ "https://" head? ] bi or ;
|
|
|
|
|
2008-02-25 15:53:18 -05:00
|
|
|
: do-redirect ( response -- response stream )
|
|
|
|
dup response-code 300 399 between? [
|
2008-03-07 18:21:20 -05:00
|
|
|
stdio get dispose
|
2008-04-22 16:37:49 -04:00
|
|
|
redirects inc
|
|
|
|
redirects get max-redirects < [
|
|
|
|
header>> "location" swap at
|
2008-04-23 02:42:30 -04:00
|
|
|
dup absolute-url? [
|
2008-04-22 16:37:49 -04:00
|
|
|
absolute-redirect
|
|
|
|
] [
|
|
|
|
relative-redirect
|
|
|
|
] if "GET" >>method http-request
|
2008-02-25 15:53:18 -05:00
|
|
|
] [
|
2008-04-22 16:37:49 -04:00
|
|
|
too-many-redirects
|
|
|
|
] if
|
2008-02-25 15:53:18 -05:00
|
|
|
] [
|
|
|
|
stdio get
|
|
|
|
] if ;
|
2007-09-20 18:09:08 -04:00
|
|
|
|
2008-03-07 18:21:20 -05:00
|
|
|
: close-on-error ( stream quot -- )
|
2008-03-11 04:39:09 -04:00
|
|
|
'[ , with-stream* ] [ ] pick '[ , dispose ] cleanup ; inline
|
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
|
|
|
|
2008-03-07 18:21:20 -05:00
|
|
|
: http-request ( request -- response stream )
|
|
|
|
dup request [
|
2008-03-23 00:43:43 -04:00
|
|
|
dup request-addr latin1 <client>
|
2008-03-07 18:21:20 -05:00
|
|
|
1 minutes over set-timeout
|
2008-02-25 15:53:18 -05:00
|
|
|
[
|
2008-03-07 18:21:20 -05:00
|
|
|
write-request flush
|
|
|
|
read-response
|
|
|
|
do-redirect
|
|
|
|
] close-on-error
|
|
|
|
] with-variable ;
|
2008-02-07 18:55:31 -05:00
|
|
|
|
2008-04-22 15:37:26 -04:00
|
|
|
: read-chunks ( -- )
|
2008-04-22 21:23:49 -04:00
|
|
|
read-crlf ";" split1 drop hex> dup { f 0 } member?
|
|
|
|
[ drop ] [ read % read-crlf "" assert= read-chunks ] if ;
|
2008-04-22 15:37:26 -04:00
|
|
|
|
|
|
|
: do-chunked-encoding ( response stream -- response stream/string )
|
|
|
|
over "transfer-encoding" header "chunked" = [
|
|
|
|
[ [ read-chunks ] "" make ] with-stream
|
|
|
|
] when ;
|
|
|
|
|
2008-03-07 18:21:20 -05:00
|
|
|
: <get-request> ( url -- request )
|
|
|
|
<request> request-with-url "GET" >>method ;
|
2008-02-25 15:53:18 -05:00
|
|
|
|
2008-04-22 15:37:26 -04:00
|
|
|
: string-or-contents ( stream/string -- string )
|
|
|
|
dup string? [ contents ] unless ;
|
|
|
|
|
|
|
|
: http-get-stream ( url -- response stream/string )
|
|
|
|
<get-request> http-request do-chunked-encoding ;
|
2007-09-20 18:09:08 -04:00
|
|
|
|
2008-02-07 18:55:31 -05:00
|
|
|
: success? ( code -- ? ) 200 = ;
|
2007-09-20 18:09:08 -04:00
|
|
|
|
2008-04-22 15:37:26 -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 ;
|
2008-01-31 02:15:28 -05:00
|
|
|
|
2008-02-07 18:55:31 -05:00
|
|
|
: http-get ( url -- string )
|
2008-04-22 15:37:26 -04:00
|
|
|
http-get-stream string-or-contents check-response ;
|
2008-01-31 02:15:28 -05:00
|
|
|
|
2008-02-07 18:55:31 -05:00
|
|
|
: download-name ( url -- name )
|
|
|
|
file-name "?" split1 drop "/" ?tail drop ;
|
2008-01-31 02:15:28 -05:00
|
|
|
|
|
|
|
: download-to ( url file -- )
|
2007-09-20 18:09:08 -04:00
|
|
|
#! Downloads the contents of a URL to a file.
|
2008-04-23 02:42:30 -04:00
|
|
|
swap http-get-stream check-response
|
|
|
|
dup string? [
|
|
|
|
latin1 [ write ] with-file-writer
|
|
|
|
] [
|
|
|
|
[ swap latin1 <file-writer> stream-copy ] with-disposal
|
|
|
|
] if ;
|
2008-01-31 02:15:28 -05:00
|
|
|
|
|
|
|
: 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-03-07 18:21:20 -05:00
|
|
|
request-with-url
|
2008-02-25 15:53:18 -05:00
|
|
|
"POST" >>method
|
|
|
|
swap >>post-data
|
|
|
|
swap >>post-data-type ;
|
|
|
|
|
|
|
|
: http-post ( content-type content url -- response string )
|
2008-04-22 15:37:26 -04:00
|
|
|
<post-request> http-request do-chunked-encoding string-or-contents ;
|