aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-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")))))