shenfeng/http-kit — pull request #7 by ptaoussanis (2013-01-22 06:44:30+00:00)
Title: API tweak for discussion

Following the discussion at https://github.com/shenfeng/http-kit/commit/a025489c5c60bf40d339418aa54cd50640c3952f#commitcomment-2475219

What do you think of this?:

```clojure
(defn request
"Issues an async HTTP request and returns a promise object to which the value
of `{:request _ :cb-result _ :status _ :headers _ :body _}` or
`{:request _ :cb-result _ :error _ }` will be delivered.

;; Asynchronous GET request (returns a promise)
(request {:url \"http://www.cnn.com\"})

;; Asynchronous GET request with callback
(request {:method \"http://www.cnn.com\" :get}
(fn [{:keys [request status body headers cb-result error] :as resp}]
(if error
(do (println \"Error on\" request) error)
(do (println \"Success on\" request) body))))

;; Synchronous requests
@(request ...) or (deref (request ...) timeout-ms timeout-val)

;; Issue 2 concurrent requests, then wait for results
(let [resp1 (request ...)
resp2 (request ...)]
(println \"resp1's status: \" (:status @resp1))
(println \"resp2's status: \" (:status @resp2)))

Request options: :client, :timeout, :headers, :body, :query-params,
:form-params, :basic-auth, :user-agent :filter :worker-pool"
[{:keys [client timeout filter worker-pool] :as opts
:or {client @default-client timeout -1 filter IFilter/ACCEPT_ALL worker-pool default-pool}}
callback]
(let [{:keys [url method headers body] :as req} (coerce-req opts)
response (promise)
respond! (fn [http-response]
(deliver response
(assoc http-response
:request req
:cb-result (when callback
(try (callback resp)
(catch Exception e e))))))

handler (reify IResponseHandler
(onSuccess [this status headers body]
(respond! {:body body
:headers (prepare-response-headers headers)
:status status}))
(onThrowable [this t] (respond! {:error t})))
listener (RespListener. handler filter worker-pool)]
(.exec ^HttpClient client url method headers body timeout listener)
response))
```

This returns the exception-wrapped callback as _part_ of the response, in a :cb-result key. If the callback generates an error, :cb-result gets the value of that error.

I think this is simple to understand and flexible. Like the previous `try-callback`, it also always delivers (i.e. no blocking promises that will never deliver).