From 68f478625dbec55c5d78d5896d60016e140150a8 Mon Sep 17 00:00:00 2001 From: Arun Isaac Date: Thu, 30 Dec 2021 16:43:57 +0530 Subject: 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. --- kolam/http.scm | 65 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 64 insertions(+), 1 deletion(-) 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"))))) -- cgit v1.2.3