Last active
March 22, 2020 14:49
-
-
Save souenzzo/82a141d0ceea83b26d52e5e6abade2ca to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
(ns com.wsscode.pathom.diplomat.http.java-http | |
(:require [com.wsscode.pathom.diplomat.http :as http] | |
[clojure.spec.alpha :as s] | |
[clojure.core.async :as async] | |
[clojure.string :as string] | |
[clojure.data.json :as json]) | |
(:import (java.net.http HttpResponse$BodyHandlers HttpRequest HttpClient HttpResponse HttpHeaders HttpRequest$BodyPublishers) | |
(java.net URI) | |
(java.util.function Function BiPredicate) | |
(java.util Optional))) | |
(set! *warn-on-reflection* true) | |
(defn build-request | |
[{::http/keys [url content-type accept as body headers form-params method] | |
:or {headers {}} | |
:as env}] | |
(let [uri (URI/create url) | |
method (string/upper-case (http/request-method env)) | |
version (Optional/empty) | |
timeout (Optional/empty) | |
headers (HttpHeaders/of (cond-> headers | |
content-type (assoc "content-type" [(http/encode-type->header content-type)])) | |
(reify BiPredicate | |
(test [this a b] | |
true))) | |
expect-continue false | |
body-publisher (if form-params | |
(Optional/of | |
(HttpRequest$BodyPublishers/ofString | |
(json/write-str form-params))) | |
(Optional/empty))] | |
(proxy [HttpRequest] [] | |
(uri [] uri) | |
(method [] method) | |
(version [] version) | |
(timeout [] timeout) | |
(headers [] headers) | |
(expectContinue [] expect-continue) | |
(bodyPublisher [] body-publisher)))) | |
(defn build-response-map | |
[{::http/keys [as]} ^HttpResponse response] | |
(let [headers (into {} | |
(comp | |
(map (fn [[k v]] | |
[k (first v)]))) | |
(.map (.headers response)))] | |
{::http/status (.statusCode response) | |
::http/body (if (and (= as ::http/json) | |
(string/starts-with? (string/lower-case (get headers "content-type")) | |
"application/json")) | |
(json/read-str (.body response) | |
:key-fn keyword) | |
(.body response)) | |
::http/headers headers})) | |
(defn request | |
[] | |
(let [client (HttpClient/newHttpClient)] | |
(fn [env] | |
(s/assert ::http/request env) | |
(let [request (build-request env)] | |
(build-response-map env (.send client request (HttpResponse$BodyHandlers/ofString))))))) | |
(defn request-async | |
[] | |
(let [client (HttpClient/newHttpClient)] | |
(fn [env] | |
(s/assert ::http/request env) | |
(let [request (build-request env) | |
chan (async/promise-chan (map (partial build-response-map env)))] | |
(doto (.sendAsync client request (HttpResponse$BodyHandlers/ofString)) | |
(.thenApply (reify Function | |
(apply [this response] | |
(async/put! chan response))))) | |
chan)))) | |
(comment | |
(http/request {::http/driver (request) | |
::http/url (str "https://api.github.com/graphql?access_token=" (System/getenv "GITHUB_TOKEN")) | |
::http/as ::http/json | |
::http/content-type ::http/json | |
::http/form-params {:query "query { __schema { queryType { name } } }"}}) | |
=> {::http/status 200, | |
::http/headers {"server" "GitHub.com",,,} | |
::http/body {:data {:__schema {:queryType {:name "Query"}}}}}) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment