aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorArun Isaac2021-12-30 16:43:57 +0530
committerArun Isaac2021-12-30 16:43:57 +0530
commit68f478625dbec55c5d78d5896d60016e140150a8 (patch)
treef4eb98a277f43d5cafc14c6c847ed7e3ec70e736
parent87166ff87ee0c13611f28a0dfab75a52a13bdd32 (diff)
downloadkolam-68f478625dbec55c5d78d5896d60016e140150a8.tar.gz
kolam-68f478625dbec55c5d78d5896d60016e140150a8.tar.lz
kolam-68f478625dbec55c5d78d5896d60016e140150a8.zip
kolam: Implement HTTP client.
* kolam/http.scm: Import (srfi srfi-26), (web client), (web response) and (kolam utils). (variables->alist, graphql-http-response): New functions. (graphql-http-get, graphql-http-post): New public functions.
-rw-r--r--kolam/http.scm65
1 files changed, 64 insertions, 1 deletions
diff --git a/kolam/http.scm b/kolam/http.scm
index 2098ef1..9efbd60 100644
--- a/kolam/http.scm
+++ b/kolam/http.scm
@@ -19,13 +19,19 @@
(define-module (kolam http)
#:use-module (rnrs io ports)
+ #:use-module (srfi srfi-26)
#:use-module (ice-9 match)
+ #:use-module (web client)
#:use-module (web request)
+ #:use-module (web response)
#:use-module (web uri)
#:use-module (json)
#:use-module (kolam graphql)
#:use-module (kolam parse)
- #:export (graphql-handler))
+ #:use-module (kolam utils)
+ #:export (graphql-handler
+ graphql-http-get
+ graphql-http-post))
(define transcoder
(make-transcoder (utf-8-codec) 'none 'raise))
@@ -62,3 +68,60 @@ run-server from guile's (web server)."
"query"))
(('document operations ...)
`(("data" . ,(map evaluator operations))))))))))
+
+(define (variables->alist variables)
+ "Convert VARIABLES into an association list to be embedded into the
+GraphQL request."
+ (map (match-lambda
+ ((key . value)
+ (cons (keyword->symbol key)
+ value)))
+ (pairify variables)))
+
+(define (graphql-http-get uri document . variables)
+ "Send GraphQL query as specified in GraphQL DOCUMENT to graphql
+endpoint URI. The GET HTTP method is used. VARIABLES must be a list of
+variables to send with the query. It must be of the form (name value
+...) where NAME must be a keyword. For example, (#:spam 1 #:ham
+\"bacon\" #:eggs 2)."
+ (call-with-values
+ (cut http-get
+ (string-append uri
+ "?query="
+ (uri-encode (scm->graphql-string document))
+ "&"
+ "variables="
+ (uri-encode (scm->json-string
+ (variables->alist variables))))
+ #:streaming? #t)
+ graphql-http-response))
+
+(define (graphql-http-post uri document . variables)
+ "Send GraphQL query as specified in GraphQL DOCUMENT to graphql
+endpoint URI. The POST HTTP method is used. VARIABLES must be a list
+of variables to send with the query. It must be of the form (name
+value ...) where NAME must be a keyword. For example, (#:spam 1 #:ham
+\"bacon\" #:eggs 2)."
+ (call-with-values
+ (cut http-post
+ uri
+ #:body (scm->json-string
+ (cons (cons 'query (scm->graphql-string document))
+ (match variables
+ (() '())
+ (_ (cons 'variables (variables->alist variables))))))
+ #:streaming? #t)
+ graphql-http-response))
+
+(define (graphql-http-response response port)
+ "Return GraphQL response data from HTTP RESPONSE and response body
+read from PORT. Raise errors, if any."
+ (unless (and (>= (response-code response) 200)
+ (< (response-code response) 300))
+ (error "GraphQL query failed with non-2xx status code:"
+ response (get-string-all port)))
+ (let ((response-alist (json->scm port)))
+ (cond
+ ((assoc-ref response-alist "errors")
+ => (cut error "GraphQL query failed with errors:" <>))
+ (else (assoc-ref response-alist "data")))))