From mboxrd@z Thu Jan 1 00:00:00 1970 Path: news.gmane.org!.POSTED!not-for-mail From: Arun Isaac Newsgroups: gmane.lisp.guile.bugs Subject: bug#30154: [PATCH] web: Export http-request. Date: Thu, 21 Jun 2018 22:57:18 +0530 Message-ID: <20180621172718.16029-1-arunisaac@systemreboot.net> References: <20180118094310.11658-1-arunisaac@systemreboot.net> NNTP-Posting-Host: blaine.gmane.org Mime-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit X-Trace: blaine.gmane.org 1529602026 3632 195.159.176.226 (21 Jun 2018 17:27:06 GMT) X-Complaints-To: usenet@blaine.gmane.org NNTP-Posting-Date: Thu, 21 Jun 2018 17:27:06 +0000 (UTC) Cc: 30154@debbugs.gnu.org To: ludo@gnu.org Original-X-From: bug-guile-bounces+guile-bugs=m.gmane.org@gnu.org Thu Jun 21 19:27:02 2018 Return-path: Envelope-to: guile-bugs@m.gmane.org Original-Received: from lists.gnu.org ([208.118.235.17]) by blaine.gmane.org with esmtp (Exim 4.84_2) (envelope-from ) id 1fW3ML-0000nb-I8 for guile-bugs@m.gmane.org; Thu, 21 Jun 2018 19:27:01 +0200 Original-Received: from localhost ([::1]:56891 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1fW3OS-0007pc-QF for guile-bugs@m.gmane.org; Thu, 21 Jun 2018 13:29:12 -0400 Original-Received: from eggs.gnu.org ([2001:4830:134:3::10]:53644) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1fW3OM-0007pK-5Z for bug-guile@gnu.org; Thu, 21 Jun 2018 13:29:08 -0400 Original-Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1fW3OH-0000wS-WF for bug-guile@gnu.org; Thu, 21 Jun 2018 13:29:06 -0400 Original-Received: from debbugs.gnu.org ([208.118.235.43]:51463) by eggs.gnu.org with esmtps (TLS1.0:RSA_AES_128_CBC_SHA1:16) (Exim 4.71) (envelope-from ) id 1fW3OH-0000wA-Qo for bug-guile@gnu.org; Thu, 21 Jun 2018 13:29:01 -0400 Original-Received: from Debian-debbugs by debbugs.gnu.org with local (Exim 4.84_2) (envelope-from ) id 1fW3OH-0005fO-I2 for bug-guile@gnu.org; Thu, 21 Jun 2018 13:29:01 -0400 X-Loop: help-debbugs@gnu.org In-Reply-To: <20180118094310.11658-1-arunisaac@systemreboot.net> Resent-From: Arun Isaac Original-Sender: "Debbugs-submit" Resent-CC: bug-guile@gnu.org Resent-Date: Thu, 21 Jun 2018 17:29:01 +0000 Resent-Message-ID: Resent-Sender: help-debbugs@gnu.org X-GNU-PR-Message: followup 30154 X-GNU-PR-Package: guile X-GNU-PR-Keywords: patch Original-Received: via spool by 30154-submit@debbugs.gnu.org id=B30154.152960209521725 (code B ref 30154); Thu, 21 Jun 2018 17:29:01 +0000 Original-Received: (at 30154) by debbugs.gnu.org; 21 Jun 2018 17:28:15 +0000 Original-Received: from localhost ([127.0.0.1]:59360 helo=debbugs.gnu.org) by debbugs.gnu.org with esmtp (Exim 4.84_2) (envelope-from ) id 1fW3NV-0005eJ-Ur for submit@debbugs.gnu.org; Thu, 21 Jun 2018 13:28:15 -0400 Original-Received: from vultr.systemreboot.net ([45.77.148.100]:58820) by debbugs.gnu.org with esmtp (Exim 4.84_2) (envelope-from ) id 1fW3NN-0005df-Bc for 30154@debbugs.gnu.org; Thu, 21 Jun 2018 13:28:12 -0400 DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=systemreboot.net; s=default; h=Content-Transfer-Encoding:Content-Type: MIME-Version:Message-Id:Date:Subject:Cc:To:From:Sender:Reply-To:Content-ID: Content-Description:Resent-Date:Resent-From:Resent-Sender:Resent-To:Resent-Cc :Resent-Message-ID:In-Reply-To:References:List-Id:List-Help:List-Unsubscribe: List-Subscribe:List-Post:List-Owner:List-Archive; bh=py/3NlSdjOJoAE+CPLI3xvhffQGqxzfjFA9qLWXvSUA=; b=XjYhAS5OierT5ZeH9/sbLX0LOY zl9iayLos72++IPIwG66/+eIRbf75aGqQF/gxPZx+rnttZE6qcai9nly43ZbLxhJGBXfeFBxs7yj5 a9osvDTxSkK5wIQNIv/vG6aBYxe1lGDsQiyy4YsDeUDK8oREbm20+S+Rn3cwBn57+lOg=; Original-Received: from [124.40.246.228] (helo=localhost.localdomain) by systemreboot.net with esmtpsa (TLSv1.2:ECDHE-RSA-AES128-GCM-SHA256:128) (Exim 4.91) (envelope-from ) id 1fW3KM-00007w-7L; Thu, 21 Jun 2018 22:54:59 +0530 X-Mailer: git-send-email 2.15.1 X-BeenThere: debbugs-submit@debbugs.gnu.org X-Mailman-Version: 2.1.18 Precedence: list X-detected-operating-system: by eggs.gnu.org: GNU/Linux 2.2.x-3.x [generic] X-Received-From: 208.118.235.43 X-BeenThere: bug-guile@gnu.org List-Id: "Bug reports for GUILE, GNU's Ubiquitous Extension Language" List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: bug-guile-bounces+guile-bugs=m.gmane.org@gnu.org Original-Sender: "bug-guile" Xref: news.gmane.org gmane.lisp.guile.bugs:9078 Archived-At: * module/web/client.scm (request): Rename to http-request, add a docstring, and export it. (http-get, http-head, http-post, http-put, http-delete, http-trace, http-options): Update docstring. * doc/ref/web.texi (Web Client): Document http-request. --- doc/ref/web.texi | 40 ++++++++----- module/web/client.scm | 157 +++++++++++++++++++++++++------------------------- 2 files changed, 106 insertions(+), 91 deletions(-) diff --git a/doc/ref/web.texi b/doc/ref/web.texi index 07da5b64b..329912d33 100644 --- a/doc/ref/web.texi +++ b/doc/ref/web.texi @@ -1463,24 +1463,18 @@ how to install the GnuTLS bindings for Guile,, gnutls-guile, GnuTLS-Guile}, for more information. @end deffn -@deffn {Scheme Procedure} http-get uri arg... -@deffnx {Scheme Procedure} http-head uri arg... -@deffnx {Scheme Procedure} http-post uri arg... -@deffnx {Scheme Procedure} http-put uri arg... -@deffnx {Scheme Procedure} http-delete uri arg... -@deffnx {Scheme Procedure} http-trace uri arg... -@deffnx {Scheme Procedure} http-options uri arg... +@anchor{http-request}@deffn {Scheme Procedure} http-request uri arg... Connect to the server corresponding to @var{uri} and make a request over -HTTP, using the appropriate method (@code{GET}, @code{HEAD}, etc.). +HTTP, using @var{method} (@code{GET}, @code{HEAD}, @code{POST}, etc.). -All of these procedures have the same prototype: a URI followed by an -optional sequence of keyword arguments. These keyword arguments allow -you to modify the requests in various ways, for example attaching a body -to the request, or setting specific headers. The following table lists -the keyword arguments and their default values. +The following keyword arguments allow you to modify the requests in +various ways, for example attaching a body to the request, or setting +specific headers. The following table lists the keyword arguments and +their default values. @table @code +@item #:method 'GET @item #:body #f @item #:port (open-socket-for-uri @var{uri})] @item #:version '(1 . 1) @@ -1518,6 +1512,26 @@ body as a string, bytevector, #f value, or as a port (if @var{streaming?} is true). @end deffn +@deffn {Scheme Procedure} http-get uri arg... +@deffnx {Scheme Procedure} http-head uri arg... +@deffnx {Scheme Procedure} http-post uri arg... +@deffnx {Scheme Procedure} http-put uri arg... +@deffnx {Scheme Procedure} http-delete uri arg... +@deffnx {Scheme Procedure} http-trace uri arg... +@deffnx {Scheme Procedure} http-options uri arg... + +Connect to the server corresponding to @var{uri} and make a request over +HTTP, using the appropriate method (@code{GET}, @code{HEAD}, +@code{POST}, etc.). + +These procedures are variants of @code{http-request} specialized with a +specific @var{method} argument, and have the same prototype: a URI +followed by an optional sequence of keyword arguments. See +@ref{http-request} for full documentation on the various keyword +arguments. + +@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 diff --git a/module/web/client.scm b/module/web/client.scm index c13117dd2..102e2b724 100644 --- a/module/web/client.scm +++ b/module/web/client.scm @@ -47,6 +47,7 @@ #:prefix rnrs-ports:) #:export (current-http-proxy open-socket-for-uri + http-request http-get http-head http-post @@ -331,25 +332,50 @@ as is the case by default with a request returned by `build-request'." (else (error "unexpected body type" body)))) -;; We could expose this to user code if there is demand. -(define* (request uri #:key - (body #f) - (port (open-socket-for-uri uri)) - (method 'GET) - (version '(1 . 1)) - (keep-alive? #f) - (headers '()) - (decode-body? #t) - (streaming? #f) - (request - (build-request - (ensure-uri-reference uri) - #:method method - #:version version - #:headers (if keep-alive? - headers - (cons '(connection close) headers)) - #:port port))) +(define* (http-request uri #:key + (body #f) + (port (open-socket-for-uri uri)) + (method 'GET) + (version '(1 . 1)) + (keep-alive? #f) + (headers '()) + (decode-body? #t) + (streaming? #f) + (request + (build-request + (ensure-uri-reference uri) + #:method method + #:version version + #:headers (if keep-alive? + headers + (cons '(connection close) headers)) + #:port port))) + "Connect to the server corresponding to URI and ask for the resource, +using METHOD, defaulting to ‘GET’. If you already have a port open, +pass it as PORT. The port will be closed at the end of the request +unless KEEP-ALIVE? is true. Any extra headers in the alist HEADERS will +be added to the request. + +If BODY is not ‘#f’, a message body will also be sent with the HTTP +request. If BODY is a string, it is encoded according to the +content-type in HEADERS, defaulting to UTF-8. Otherwise BODY should be +a bytevector, or ‘#f’ for no body. Although it's allowed to send a +message body along with any request, usually only POST and PUT requests +have bodies. See ‘http-put’ and ‘http-post’ documentation, for more. + +If DECODE-BODY? is true, as is the default, the body of the +response will be decoded to string, if it is a textual content-type. +Otherwise it will be returned as a bytevector. + +However, if STREAMING? is true, instead of eagerly reading the response +body from the server, this function only reads off the headers. The +response body will be returned as a port on which the data may be read. +Unless KEEP-ALIVE? is true, the port will be closed after the full +response body has been read. + +Returns two values: the response read from the server, and the response +body as a string, bytevector, #f value, or as a port (if STREAMING? is +true)." (call-with-values (lambda () (sanitize-request request body)) (lambda (request body) (let ((request (write-request request port))) @@ -376,42 +402,6 @@ as is the case by default with a request returned by `build-request'." (decode-response-body response body) body)))))))))) -(define* (http-get uri #:key - (body #f) - (port (open-socket-for-uri uri)) - (version '(1 . 1)) (keep-alive? #f) - (headers '()) (decode-body? #t) (streaming? #f)) - "Connect to the server corresponding to URI and ask for the -resource, using the ‘GET’ method. If you already have a port open, -pass it as PORT. The port will be closed at the end of the -request unless KEEP-ALIVE? is true. Any extra headers in the -alist HEADERS will be added to the request. - -If BODY is not ‘#f’, a message body will also be sent with the HTTP -request. If BODY is a string, it is encoded according to the -content-type in HEADERS, defaulting to UTF-8. Otherwise BODY should be -a bytevector, or ‘#f’ for no body. Although it's allowed to send a -message body along with any request, usually only POST and PUT requests -have bodies. See ‘http-put’ and ‘http-post’ documentation, for more. - -If DECODE-BODY? is true, as is the default, the body of the -response will be decoded to string, if it is a textual content-type. -Otherwise it will be returned as a bytevector. - -However, if STREAMING? is true, instead of eagerly reading the response -body from the server, this function only reads off the headers. The -response body will be returned as a port on which the data may be read. -Unless KEEP-ALIVE? is true, the port will be closed after the full -response body has been read. - -Returns two values: the response read from the server, and the response -body as a string, bytevector, #f value, or as a port (if STREAMING? is -true)." - (request uri #:method 'GET #:body body - #:port port #:version version #:keep-alive? keep-alive? - #:headers headers #:decode-body? decode-body? - #:streaming? streaming?)) - (define-syntax-rule (define-http-verb http-verb method doc) (define* (http-verb uri #:key (body #f) @@ -422,20 +412,31 @@ true)." (decode-body? #t) (streaming? #f)) doc - (request uri - #:body body #:method method - #:port port #:version version #:keep-alive? keep-alive? - #:headers headers #:decode-body? decode-body? - #:streaming? streaming?))) + (http-request uri + #:body body #:method method + #:port port #:version version #:keep-alive? keep-alive? + #:headers headers #:decode-body? decode-body? + #:streaming? streaming?))) + +(define-http-verb http-get + 'GET + "Fetch message headers for the given URI using the HTTP \"GET\" +method. + +This function invokes ‘http-request’, with the \"GET\" method. See +‘http-request’ for full documentation on the various keyword arguments +that are accepted by this function. + +Returns two values: the resulting response, and the response body.") (define-http-verb http-head 'HEAD "Fetch message headers for the given URI using the HTTP \"HEAD\" method. -This function is similar to ‘http-get’, except it uses the \"HEAD\" -method. See ‘http-get’ for full documentation on the various keyword -arguments that are accepted by this function. +This function invokes ‘http-request’, with the \"HEAD\" method. See +‘http-request’ for full documentation on the various keyword arguments +that are accepted by this function. Returns two values: the resulting response, and ‘#f’. Responses to HEAD requests do not have a body. The second value is only returned so that @@ -445,9 +446,9 @@ other procedures can treat all of the http-foo verbs identically.") 'POST "Post data to the given URI using the HTTP \"POST\" method. -This function is similar to ‘http-get’, except it uses the \"POST\" -method. See ‘http-get’ for full documentation on the various keyword -arguments that are accepted by this function. +This function invokes ‘http-request’, with the \"POST\" method. See +‘http-request’ for full documentation on the various keyword arguments +that are accepted by this function. Returns two values: the resulting response, and the response body.") @@ -455,9 +456,9 @@ Returns two values: the resulting response, and the response body.") 'PUT "Put data at the given URI using the HTTP \"PUT\" method. -This function is similar to ‘http-get’, except it uses the \"PUT\" -method. See ‘http-get’ for full documentation on the various keyword -arguments that are accepted by this function. +This function invokes ‘http-request’, with the \"PUT\" method. See +‘http-request’ for full documentation on the various keyword arguments +that are accepted by this function. Returns two values: the resulting response, and the response body.") @@ -465,9 +466,9 @@ Returns two values: the resulting response, and the response body.") 'DELETE "Delete data at the given URI using the HTTP \"DELETE\" method. -This function is similar to ‘http-get’, except it uses the \"DELETE\" -method. See ‘http-get’ for full documentation on the various keyword -arguments that are accepted by this function. +This function invokes ‘http-request’, with the \"DELETE\" method. See +‘http-request’ for full documentation on the various keyword arguments +that are accepted by this function. Returns two values: the resulting response, and the response body.") @@ -475,9 +476,9 @@ Returns two values: the resulting response, and the response body.") 'TRACE "Send an HTTP \"TRACE\" request. -This function is similar to ‘http-get’, except it uses the \"TRACE\" -method. See ‘http-get’ for full documentation on the various keyword -arguments that are accepted by this function. +This function invokes ‘http-request’, with the \"TRACE\" method. See +‘http-request’ for full documentation on the various keyword arguments +that are accepted by this function. Returns two values: the resulting response, and the response body.") @@ -486,8 +487,8 @@ Returns two values: the resulting response, and the response body.") "Query characteristics of an HTTP resource using the HTTP \"OPTIONS\" method. -This function is similar to ‘http-get’, except it uses the \"OPTIONS\" -method. See ‘http-get’ for full documentation on the various keyword -arguments that are accepted by this function. +This function invokes ‘http-request’, with the \"OPTIONS\" method. See +‘http-request’ for full documentation on the various keyword arguments +that are accepted by this function. Returns two values: the resulting response, and the response body.") -- 2.15.1