web: Add `http-get*'.
authorLudovic Courtès <ludo@gnu.org>
Wed, 28 Nov 2012 21:50:26 +0000 (22:50 +0100)
committerLudovic Courtès <ludo@gnu.org>
Wed, 28 Nov 2012 21:50:26 +0000 (22:50 +0100)
* module/web/client.scm (http-get*): New procedure.
* doc/ref/web.texi (Web Client): Document it.

doc/ref/web.texi
module/web/client.scm

index 3b53ccd..e892453 100644 (file)
@@ -1400,6 +1400,13 @@ response will be decoded to string, if it is a textual content-type.
 Otherwise it will be returned as a bytevector.
 @end deffn
 
+@deffn {Scheme Procedure} http-get* uri [#:port=(open-socket-for-uri uri)] [#:version='(1 . 1)] [#:keep-alive?=#f] [#:extra-headers='()] [#:decode-body?=#t]
+Like @code{http-get}, but return an input port from which to read.  When
+@var{decode-body?} is true, as is the default, the returned port has its
+encoding set appropriately if the data at @var{uri} is textual.  Closing the
+returned port closes @var{port}, unless @var{keep-alive?} is true.
+@end deffn
+
 @code{http-get} is useful for making one-off requests to web sites.  If
 you are writing a web spider or some other client that needs to handle a
 number of requests in parallel, it's better to build an event-driven URL
index d9dff03..df0a749 100644 (file)
@@ -39,7 +39,8 @@
   #:use-module (web response)
   #:use-module (web uri)
   #:export (open-socket-for-uri
-            http-get))
+            http-get
+            http-get*))
 
 (define (open-socket-for-uri uri)
   "Return an open input/output port for a connection to URI."
@@ -135,3 +136,25 @@ Otherwise it will be returned as a bytevector."
               (if decode-body?
                   (decode-response-body res body)
                   body)))))
+
+(define* (http-get* uri #:key (port (open-socket-for-uri uri))
+                    (version '(1 . 1)) (keep-alive? #f) (extra-headers '())
+                    (decode-body? #t))
+  "Like ‘http-get’, but return an input port from which to read.  When
+DECODE-BODY? is true, as is the default, the returned port has its
+encoding set appropriately if the data at URI is textual.  Closing the
+returned port closes PORT, unless KEEP-ALIVE? is true."
+  (let ((req (build-request uri #:version version
+                            #:headers (if keep-alive?
+                                          extra-headers
+                                          (cons '(connection close)
+                                                extra-headers)))))
+    (write-request req port)
+    (force-output port)
+    (unless keep-alive?
+      (shutdown port 1))
+    (let* ((res (read-response port))
+           (body (response-body-port res
+                                     #:keep-alive? keep-alive?
+                                     #:decode? decode-body?)))
+      (values res body))))