Coder Social home page Coder Social logo

cljs-http's Introduction

cljs-http

https://img.shields.io/clojars/v/cljs-http.svg https://travis-ci.org/r0man/cljs-http.svg http://jarkeeper.com/r0man/cljs-http/status.svg https://jarkeeper.com/r0man/cljs-http/downloads.svg

A HTTP library for ClojureScript.

http://imgs.xkcd.com/comics/server_attention_span.png

Usage

Imports

cljs-http returns core.async channels, so you need to import the go macro and the <! function.

(ns example.core
  (:require-macros [cljs.core.async.macros :refer [go]])
  (:require [cljs-http.client :as http]
            [cljs.core.async :refer [<!]]))

Async response handling

All HTTP functions in cljs-http return a core.async channel. When a request has completed or failed it is put on that channel. You can take the response from that channel with the <! function within a go block.

(go (let [response (<! (http/get "https://api.github.com/users"
                                 {:with-credentials? false
                                  :query-params {"since" 135}}))]
      (prn (:status response))
      (prn (map :login (:body response)))))

You can pass your own response channel. This is useful when using a transducers.

(http/get "http://example.com" {:channel (chan 1 (map :body))})

Content type

cljs-http can serialize the body of a request and set the Content-Type header accordingly. You can send the body params in mutiple formats:

(http/post "http://example.com" {:edn-params {:foo :bar}})

(http/post "http://example.com" {:json-params {:foo :bar}})
;;(JSON is auto-converted via `cljs.core/clj->js`)

(http/post "http://example.com" {:transit-params {:key1 "value1" :key2 "value2"}})

(http/post "http://example.com" {:form-params {:key1 "value1" :key2 "value2"}})

To send form parameters (an array of values):

(http/post "http://example.com" {:form-params {:key1 [1 2 3] :key2 "value2"}})

To upload a file using Multipart parameters:

(http/post "http://example.com" {:multipart-params [["key1" "value1"] ["my-file" my-file]]})

Where my-file can be a JavaScript Blob instance

(def my-file (js/Blob. #js ["<h1>Hello</h1>"] #js {:type "text/html"}))

or a HTML file input field.

<input id="my-file" type="file">
(def my-file
  (-> (.getElementById js/document "my-file")
      .-files first))

If you want to set the name of the file use a vector as my-file.

(def my-file ["myfile" [value filename]])

See https://developer.mozilla.org/en-US/docs/Web/API/FormData/append#Syntax for more details.

HTTP Basic Authentication

(http/get "http://example.com" {:basic-auth {:username "hello" :password "world"}})

OAuth 2.0 Bearer Token

(http/get "http://example.com" {:with-credentials? false
                                :oauth-token "SecretBearerToken"})

Custom Headers (Authorization)

(http/post "https://example.com"
           {:with-credentials? false
            :headers {"Authorization" "SuperSecretToken"}})

Upload/Download progress monitoring

(let [progress-channel (async/chan)]
  (http/post "http://example.com" {:multipart-params [["key1" "value1"] ["my-file" my-file]] :progress progress-chan}))

The progress-channel will receive progress events: {:directon dir :loaded uploaded_or_downloaded :total size}

  • :direction is :upload or :download
  • in some cases :total can be missing

JSONP

(http/jsonp "http://example.com" {:callback-name "callback" :timeout 3000})

Where callback-name is used to specify JSONP callback param name. Defaults to “callback”. timeout is the length of time, in milliseconds. This channel is prepared to wait for for a request to complete. If the call is not competed within the set time span, it is assumed to have failed.

License

Copyright (C) 2012-2016 r0man

Distributed under the Eclipse Public License, the same as Clojure.

cljs-http's People

Contributors

a1exsh avatar ashercoren avatar bago2k4 avatar bsubotic avatar calebsmith avatar cursork avatar deraen avatar edipofederle avatar elliot42 avatar emidln avatar j-em avatar jalehman avatar jindrichmynarz avatar jmlsf avatar katox avatar loganlinn avatar mekza avatar mikavilpas avatar mkremins avatar myguidingstar avatar oliyh avatar phillc avatar r0man avatar rgkirch avatar robert-stuttaford avatar stwind avatar ttasterisco avatar veggiemonk avatar wavejumper avatar yalh avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

cljs-http's Issues

don't try to parse 204 replies

The status code "204 No Content" is attempted to be parsed with the given encoding, causing errors since no content can't be parsed. it would be good to skip parsing of the reply indicates that there is no content provided.

Cannot detect redirect

If you make a request the client will follow redirects but you have no way of knowing in the response what the final url was. adding an entry for .getLastUri in the channel response will allow the requester to determine where they were redirected too.

Error when applying transducer on channel to map :body

Hi, I'm using the example in the readme to always take :body out of my requests at the API call function:

(defn json-to [path]
  (http/get path {:with-credentials? false
                  :channel (chan 1 (map :body))}))

But I get an error in my console: "Error: [object Object] is not ISeqable".
The request looks like this:

{"body": [
  {"id": 1},
  ...
  ]
}

Is there something extra I need to do? Seems like I can't actually map over my request because it's a Javascript object and not a cljs data type.

Control Content-Type header

I would like to be able to control the "Content-Type" header.

It would also be nice if I could put all my data in the request :body and have cljs-http serialize it based on my provided content-type, rather than have to put my data in the proper magic key (:edn-params, :transit-params etc).

This would also pave a path to making it easier to configure cljs-http serialization from the app, something like this (this is clojure/pedestal code not cljs)

(def content-types
  {"application/json;charset=UTF-8"
   (fn [body]
     (print-fn #(http/json-print body)))

   "application/edn;charset=UTF-8"
   (fn [body]
     (print-fn #(pr body)))

   "application/transit+json;charset=UTF-8"
   (fn [body]
     (fn [^OutputStream output-stream]
       (transit/write (transit/writer output-stream :json-verbose) body)
       (.flush output-stream)))

   "application/transit+msgpack;charset=UTF-8"
   (fn [body]
     (fn [^OutputStream output-stream]
       (transit/write (transit/writer output-stream :msgpack) body)
       (.flush output-stream)))

   })

Using a map with multipart-params leads to non-determinant ordering

I was having an issue passing a map to multipart params in which the server would reject the request as invalid when the code was run in certain contexts, but not others. It seemed deterministic, but was puzzling because the code was identical.

I finally realized that multipart/form-data is supposed to be sent in the order the fields are presented in the document, per http://www.w3.org/TR/html4/interact/forms.html#h-17.13.4

Therefore, for reliable use of this, an ordered data structure is needed such as a vector or ordered-map

Doing the same from Clojure.

It's not really an issue, but a related question.

I'm already using cljs-http, it's great.

I want to use the same workflow in my Clojure server - send a GET request to some other server and get the response.
What's the recommended way to do that?

I already use core.async in both the client and the server, but couldn't find the way to do this request from Clojure (not Clojurescript).

Thanks

Encoded URI path gets decoded

I'm trying to send a GET request something like http://example.com/articleUrl/http%3A%2F%2Fwww.wiscnews.com%2Fsports%2Farticle_c8b5102a-c30a-5906-86a1-2ffef91f858f.html/ but the actual request sent keeps getting decoded somehow. Any pointer as to where to unit test this in cljs-http please?

&android= appended to all queries on chrome for android

if a query is issued from Chrome on an android device, every request gets an &android=<rand_int> param appended to the called url.

browsing the code i see it's a feature supposed to fix CORS on android:

(defn wrap-android-cors-bugfix [client]
  (fn [request]
    (client
     (if (util/android?)
       (assoc-in request [:query-params :android] (Math/random))
       request))))

the problem is that with strict APIS, implemented with compojure-api for instance, every useless parameter sent by the client is unallowed, thus breaking the call.

If i switch chrome to "request desktop site" on my phone browser, every http call is working normally even though we're using CORS, so maybe this piece of code is outdated ?

if possible, could you at least make it optional ?
Thank you very much.

Enable to configure cljs-http.core/jsonp if response keys are keywordized

I need cljs-http.core/jsonp not to keywordize response keys (https://github.com/r0man/cljs-http/blob/master/src/cljs_http/core.cljs#L116), because the keys in the JSON I'm requesting contain slashes and are thus (incorrectly) casted to namespaced keywords. Currently, keywordization is hard-coded, so it's not possible to disable it. Is it possible to add an option to configure if keys would be keywordized (defaulting to true to maintain compatibility)?

xhr.listen not callable (xhr undefined) in core.js line 33

(ns trans.core
  (:require-macros [cljs.core.async.macros :refer [go]])
  (:require
   [dommy.utils :as utils]
   [dommy.core :as dommy]
   [cljs-http.client :as http]
   [cljs.core.async :refer [<!]])
  (:use-macros
   [dommy.macros :only [node sel sel1 deftemplate]]))

;; dom manipulation stuff removed

(defn get-transactions [_]
  (let [aid (dommy/value (sel1 :#accountId))]
    (if (not= aid "")
      (go
        (let [response (<! (http/get (str "http://xxx:8080/transaction/account/" aid)))]
          (if (http/unexceptional-status? (:status response))
            (show-trans (:body response))))))))

(dommy/listen! (sel1 :#get-transactions) :click get-transactions)

My project file has the following dependencies

  :dependencies [[org.clojure/clojure "1.5.1"]
                 [org.clojure/clojurescript "0.0-2173"]
                 [prismatic/dommy "0.1.2"]
                 [cljs-ajax "0.2.3"]
                 [cljs-http "0.1.10"]
                 [org.clojure/core.async "0.1.303.0-886421-alpha"]]

Firefox 29 and Chrome 34 both complain when the get-transactions function is run. The error is that xhr is not callable in core.cljs line 33:

Chrome: "Uncaught TypeError: undefined is not a function"
Firefox: "TypeError: xhr.listen is not a function"

Is there something I've overlooked that I need to provide, or is this possibly a bug?

Thank you,
John

core/abort fails on client/request

It took me a while to realise that the abort function here https://github.com/r0man/cljs-http/blob/master/src/cljs_http/core.cljs#L9 is not compatible with channels generated by client/request and friends (due to the response wrappers? https://github.com/r0man/cljs-http/blob/master/src/cljs_http/client.cljs#L97; since 9fe48a7 ?)

I saw the commits by @Deraen with the additional cancel channel which can be used to cancel a request and managed to get that method working; however I would have preferred not to have created an extra channel... (also should this be called abort rather than cancel?)

Anyway, can I recommend a change in the documentation to advise unsuspecting ppl that core/abort shouldn't be used against client/request; and request that it's either made compatible, or an additional abort function that works with client/request be added to client.clj?

Misplaced function annotation warning in jsonp.js

Getting the following compiler warning after using cljs-http 0.1.35 in my project:

Jul 30, 2015 11:53:55 AM com.google.javascript.jscomp.LoggerErrorManager println
WARNING: file:/Users/xxxxxx/.m2/repository/org/clojure/google-closure-library/0.0-20140718-946a7d39/google-closure-library-0.0-20140718-946a7d39.jar!/goog/net/jsonp.js:269: WARNING - Misplaced function annotation.
  return function(var_args) {
  ^

Jul 30, 2015 11:53:55 AM com.google.javascript.jscomp.LoggerErrorManager printSummary
WARNING: 0 error(s), 1 warning(s)

Is this a known warning?

API for modifying default `cljs-http.client/request` middleware?

I have a use-case like this: I need to talk JSON but there are keys in the third-party JSON payloads which are not keywordizable.

Currently (I think) this means that I can't use the niceties of the cljs-http.client namespace, which I was using extensively, because :keywordize-keys true is baked in to the json-response middleware included there.

Would it be possible / practical / a good thing for users to be able to somehow modify this default middleware? So that, for instance, I could do something like this:

(swap! cljs-http.client/*default-middleware* (partial remove (set cljs-http.client/wrap-json-response)))

Or is that a terrible idea? Thanks for listening!

Support for nodejs

Is there planned support for cljs running under nodejs (in a server environment) ?

Thanks

Custom Authentication

I need to talk to an API that expects "xBasic" instead of "Basic" authentication, but is otherwise the same as basic authentication.

What is the recommended way to add support for more authentication types?

A multimethod middleware function seems like a good candidate to support various types of auth.

JSONp support

How do you feel about adding JSONp support? To do it right may mean changing the core interaction between core/request and client/request, but it might be nice to abstract away the communication layer a bit more. JSONp doesn't fit that nicely with this library since requests can't be aborted, and all you get back is the response body -- but a lot of the middleware fns in client would still be useful.

Here's a first pass at the request fn:

(defn jsonp-request
  "Behaves like request, using JSONP instead of XHR.
   JSONP requests can not be aborted."
  [request]
  (let [channel (async/chan)
        fn-name (gensym "jsonp")
        request-url (util/build-url
                            (update-in request [:query-string] str "&callback=" fn-name))
        script-element (js/document.createElement "script")]
    (.setAttribute script-element "src" request-url)
    (aset js/window fn-name
          (fn [body]
            (.removeChild js/document.head script-element)
            (doto channel
              (async/put! {:status 200
                           :success true
                           :body body})
              async/close!)))
    (.appendChild js/document.head script-element)
    channel))

I'm happy to put together a PR if you think it fits!

cljs-http starts looping when providing custom channel

Not sure if I am not using it correctly or this is a bug.

When I write this simple program

(def c (async/chan))

(go (while true
  (prn (async/<! c))))

(go
  (let [resp (async/<! (http/get "some_api" {:accept "application/json"}))]
    (async/>! c resp)))

Everything works fine. But when I run this one

(def c (async/chan))

(go (while true
  (prn (async/<! c))))

(go
  (http/get "some_api" {:accept "application/json" :channel c}))

everything goes awry. Tons of nils are printed to the console and it never stops. I would have thought these two are meant to be equivalent?

Running on [cljs-http "0.1.35"]

get request not sending body

When I use the following request in google chrome, it shows me the payload that was sent correctly

(http/post (str host "/profiles/search") {:with-credentials? false
                                           :accept            "application/edn"
                                           :edn-params        {:query query}})

However if I use a GET request it appears from chrome developer tools that no payload is sent:

(http/get (str host "/profiles/search") {:with-credentials? false
                                           :accept            "application/edn"
                                           :edn-params        {:query query}})

Looking in the source code I cannot work out why this is?

Transit MsgPack

Any plans to support transit-decode for the "application/transit+msgpack;charset=UTF-8" content-type?

error handler

Is there a way to capture unsuccessful http requests? I.e. 500 status codes. It would be great to see the response body for 500 requests as to debug errors.

Right now an error is thrown from the underlying library and I don't know how to capture/debug it.

How to set accept header on a GET

Hi,

For my app I need to set the accept header to either application/xml or application/json, but it isn't clear on how to do this. I tried to do this the same way as clj-http does this, but that didn't seem to work.

More examples would be very welcome.

Thank you,
Thomas

Aborting requests

Hi,

I think there is a problem with the cljs-http.core/abort!. It tries to find the XhrRequest by using the channel as map key, this is problematic as several wrappers are creating new channels using async/map. This means that the user doesn't have the original channel and abort! doesn't work.

Perhaps it would be possible to remove the need for pending-requests atom and add logic to cljs-http.core/request which would abort the request is channel is closed by the user?

  • async/map would still be problematic as closing the output channel doesn't close input channels, but I think this could be solved

Passing custom headers

How to pass x-user-id to headers.
I have tried (http/get "url_here" {:headers {"x-user-id" "1"}}), but this one sends Access-Control-Request-Headers:x-user-id, and this is not what I want. x-user-id:1 to be send as a header.

Using multiple default headers results in last value repeated

Ran into this issue when setting the csrf-token as well as x-requested-with as default headers. To reproduce:

(def default-headers
  [["X-Requested-With" "xmlhttprequest"]
   ["X-Csrf-Token" (csrf-token)]])

(cljs-http.core/request {:method get :url "/page" :default-headers default-headers})

This results in the following request headers:

X-Csrf-Token:tzKsIB0b-abc123
X-Requested-With:tzKsIB0b-abc123

Reversing the order of the default-headers results in the request headers having "xmlhttprequest" for both values. In other words, using multiple key value pairs here results in all keys being set to the same value, whichever is last. Changing to a hashmap results in the same behavior (though the ordering isn't guaranteed).

I was able to reproduce this in test case by adding a second key/value pair in test/core/test-build-xhr.

I have made a fix that passes the test and will attach it as a pull request shortly.

Cancel request

I am searching a way to cancel request.
I can close channel but request will not be aborted.
Maybe request method can return two channels (if asked to), one for response and control chan for cancelling request.

Mocking request?

AngularJs comes with pretty handy mocking feature in their http api which is really convenient to develop

More reusable internal API?

I'm working on two other versions of cljs-http that work on Nodejs and ArangoDB/Foxx. Of course it's fine to just refer to some vars in cljs-http.client. But do you think it's sensible to make internal API more reusable, given that only several things need to be changed in each version. And since cljs-http internal API work on plain Clojure data structure, most of it can be ported to JVM Clojure seamlessly.

Support custom middlewares

Clj-http supports custom middlewares (e.g. to be able to set default headers for all the requests), it would be nice if cljs-http would support it as well.

[client] - GET with duplicated query params

Hello! I'm having a problem with duplicated query params, I need to receive a list of parameters on the server, I'm using compojure, so if I go with:

;; server
(defroutes routes
  (GET "/" {{:strs [list-of-vals]} :query-params :as request}
       (println list-of-vals)))
;; ["1" "2"]
;; client
GET /?list-of-vals=1&list-of-vals=2

This works great with an XMLHttpRequest (or other clients), but not with cljs-http.

So, if I try to parse multiple params with the same name:

(println (http/parse-query-params "/?list-of-vals=1&list-of-vals=2&list-of-vals=3"))
{:/api?list-of-vals 1, :list-of-vals 3}
(println (http/parse-query-params "/?list-of-vals=1&list-of-vals=2&list-of-values=2"))
{:/api?list-of-vals 1, :list-of-vals 2, :list-of-values 3}

Given that query params are handled with a map this behaviour is expected

(-> {}
    (assoc :list-of-vals 1)
    (assoc :list-of-vals 2))
;; {:list-of-vals 2}

Given all that, how do you handle a list of query params correctly? This looks like a common [1,2] practice.

1- http://stackoverflow.com/a/2602127/600052
2- http://stackoverflow.com/a/13261403/600052

Error "Uncaught Error: Undefined nameToPath for com.cognitect.transit.eq "

Hello, I was just trying to poke around with this library and lein figwheel without much success. I'm getting error "Uncaught Error: Undefined nameToPath for com.cognitect.transit.eq " which is coming from transit (probably). Clojurescript version is 0.0-2356. Also I see bunch of warnings during compilation:

WARNING: unsigned-bit-shift-right already refers to: #'clojure.core/unsigned-bit-shift-right in namespace: cljs.core, being replaced by: #'cljs.core/unsigned-bit-shift-right
WARNING: No such namespace: com.cognitect.transit.eq at line 15 file:/home/gnzh/.m2/repository/com/cognitect/transit-cljs/0.8.188/transit-cljs-0.8.188.jar!/cognitect/transit.cljs
WARNING: No such namespace: com.cognitect.transit.types at line 15 file:/home/gnzh/.m2/repository/com/cognitect/transit-cljs/0.8.188/transit-cljs-0.8.188.jar!/cognitect/transit.cljs
WARNING: No such namespace: com.cognitect.transit at line 15 file:/home/gnzh/.m2/repository/com/cognitect/transit-cljs/0.8.188/transit-cljs-0.8.188.jar!/cognitect/transit.cljs

Are there any limitations on which clojurescript version I can use with this library?

Thanks!

not working header X-Access-Token

(go (let [response (<! (http/get "endpoint"
                                 {:headers {"X-Access-Token"  "token"}}))]
      (println "status" (:status response))
      (println "body" (:body response))))

request headers in browser not contains X-Access-Token header

credentials always sent (breaks demo)

xhr.withCredentials is always being set (it's hardcoded true). I fixed it in my fork (https://github.com/emidln/cljs-http) by allowing a :with-credentials? key to be set to false. If unset, I defer to existing behavior.

I'm bringing this up as an issue (as opposed to a pull request) as I saw that the feature existed at some point in the past, but was removed for some reason. Can you comment on this?

form-params not being sent

I have no idea why this simple example wont work. Am I missing something?

(ns testroute
  (:require [cljs-http.client :as http]))

(http/post "http://localhost:4000/testroute" {:form-params {:key1 "value1" :key2 "value2"}})

Compojure route:

(ANY "/testroute" request (println request))

Request:

{:ssl-client-cert nil, :remote-addr 0:0:0:0:0:0:0:1, :params {}, :route-params {}, :headers {origin http://localhost:4000, host localhost:4000, user-agent Mozilla/5.0 (Macintosh; Intel Mac OS X 10_9_5) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/37.0.2062.122 Safari/537.36, content-type application/x-www-form-urlencoded;charset=UTF-8, content-length 0, referer http://localhost:4000/, connection keep-alive, accept */*, accept-language en-US,en;q=0.8,sv;q=0.6, accept-encoding gzip,deflate}, :server-port 4000, :content-length 0, :form-params {}, :query-params {}, :content-type application/x-www-form-urlencoded;charset=UTF-8, :character-encoding UTF-8, :uri /testroute, :server-name localhost, :query-string nil, :body #<HttpInput org.eclipse.jetty.server.HttpInput@68bd80d7>, :scheme :http, :request-method :post}

Correct request with curl --data "key1=value1&key2=value2" http://localhost:4000/testroute

{:ssl-client-cert nil, :remote-addr 0:0:0:0:0:0:0:1, :params {:key1 value1, :key2 value2}, :route-params {}, :headers {host localhost:4000, content-length 23, content-type application/x-www-form-urlencoded, user-agent curl/7.30.0, accept */*}, :server-port 4000, :content-length 23, :form-params {key2 value2, key1 value1}, :query-params {}, :content-type application/x-www-form-urlencoded, :character-encoding nil, :uri /testroute, :server-name localhost, :query-string nil, :body #<HttpInput org.eclipse.jetty.server.HttpInput@24bad38a>, :scheme :http, :request-method :post}

This is with version 0.1.16 of cljs-http.

Uploading files

Are there any plans to add support for file uploading?

Maybe could be supported using FormData and with an API like

(http/post "http://example.com" {:form-data-params (js/FormData. some-form-element)})

console error when passing a channel

with cljs-http 0.1.17, i see an error in the console when passing a channel.

code (copied from readme):

(http/get "http://example.com" {:channel (chan 1 (map :body))})

error in console:
Uncaught Error: Assert failed: Can't put nil in on a channel
(not (nil? val))

running lein test crashes phantomjs

Hi, I'm trying to run the unit tests but phantomjs crashes before completing. Strangely the tests pass on travis (https://travis-ci.org/r0man/cljs-http)

Do these tests pass on your local system? Any ideas why this is happening?

➜  cljs-http git:(master) ✗ lein version
Leiningen 2.6.1 on Java 1.8.0_45 Java HotSpot(TM) 64-Bit Server VM

➜  cljs-http git:(master) lein test

;; ======================================================================
;; Testing with Phantom:


Testing cljs-http.client-test

FAIL in (test-cancel-channel) (:)
expected: (= resp nil)
  actual: (not (= {:status -1, :success false, :body "", :headers {}, :trace-redirects ["http://google.com" "http://google.com"], :error-code :exception, :error-text "Error: NETWORK_ERR: XMLHttpRequest Exception 101"} nil))

FAIL in (http-error-code) (:)
expected: (= :no-error (:error-code (<! success-req)))
  actual: (not (= :no-error :exception))

FAIL in (http-error-code) (:)
expected: (= :timeout (:error-code (<! timeout-req)))
  actual: (not (= :timeout :exception))
TypeError: Type error

  phantomjs://code/phantom5315752302497335760.js:74 in onError
Subprocess failed

cljs-http.core/xhr does not set header content type and correct request method name

  • What will be request method for example in bellow?
  • What will be header content-type for example in bellow?

(http/post "http://example.com" {:edn-params {:foo :bar}})

When headers set "content-type" with "application/x-www-form-urlencoded", it is setting correct content type with request method POST. But with other type, content type is not set and request method is OPTIONS.

  • Working example

(go
(let [r {:with-credentials? false,
:scheme :http,
:server-name "localhost",
:server-port 3000,
:uri "/post",
:headers {"content-type" "application/x-www-form-urlencoded"},
:request-method :post
:query-params nil,
:query-string nil,
:body "a=1",
}](->
%28xhr r%29
%28<!%29
%28log%29)))

Here
General
Remote Address:127.0.0.1:3000
Request URL:http://localhost:3000/post
Request Method:POST
Status Code:200 OK

Request Headers
Accept:/
Accept-Encoding:gzip, deflate
Accept-Language:en-US,en;q=0.8
Connection:keep-alive
Content-Length:3
Content-Type:application/x-www-form-urlencoded
Host:localhost:3000
Origin:http://localhost:3449
Referer:http://localhost:3449/

  • Error example

(go
(let [r {:with-credentials? false,
:scheme :http,
:server-name "localhost",
:server-port 3000,
:uri "/post",
:headers {"content-type" "application/edn"},
:request-method :post
:query-string nil,
:query-params nil,
:body (pr-str {:a 1}),
}](->
%28xhr r%29
%28<!%29
%28log%29)))

General
Remote Address:127.0.0.1:3000
Request URL:http://localhost:3000/post
Request Method:OPTIONS
Status Code:200 OK

Request headers
Accept:/
Accept-Encoding:gzip, deflate, sdch
Accept-Language:en-US,en;q=0.8
Access-Control-Request-Headers:content-type
Access-Control-Request-Method:POST
Connection:keep-alive
Host:localhost:3000
Origin:http://localhost:3449
Referer:http://localhost:3449/

This is not an issue for cljs-http but goog.net.xhr.

CORS preflight requests won't complete

I'm using Pedestal as the CORS server.

(def service {:env :prod
              ::bootstrap/routes routes
              ;; Allow services that are accessing this
              ;; service from a http-referer[sic] of http://localhost:3000.
              ;; All others are denied.
              ::bootstrap/allowed-origins ["http://localhost:3000"]
              ::bootstrap/resource-path "/public"
              ::bootstrap/type :jetty
              ::bootstrap/port 8080})

This request returns nil:

(go (<! (http/options "http://localhost:8080" 
    {:headers {"Origin" "http://localhost:3000" 
        "Access-Control-Request-Method" "GET" 
        "Access-Control-Request-Headers""Content-Type, Origin, Host, User-Agent, Content-Type, Content-Length, Referer, Connection"}})))

The js console returns this:

XMLHttpRequest cannot load http://localhost:8080/. Response to preflight request doesn't pass access control check: Credentials flag is 'true', but the 'Access-Control-Allow-Credentials' header is ''. It must be 'true' to allow credentials. Origin 'http://localhost:3000' is therefore not allowed access.
xhrio.js:561 XHR failed loading: OPTIONS "http://localhost:8080/".

POST request params?

Hi,

A question: how can I make a POST request with form params?

Is it supported? Couldn't find anything about this in the documentation or in the source code.

Thanks.

Add more to the Wiki!

This library looks awesome, but with the luck of Wiki it's very difficult to understand how to use it (I'm referring to the more complex features, such as custom middleware, custom headers, etc.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.