{"id":13442288,"url":"https://github.com/JulianBirch/cljs-ajax","last_synced_at":"2025-03-20T13:33:15.494Z","repository":{"id":42976157,"uuid":"9328057","full_name":"JulianBirch/cljs-ajax","owner":"JulianBirch","description":"simple asynchronous Ajax client for ClojureScript and Clojure","archived":false,"fork":false,"pushed_at":"2024-06-06T13:41:25.000Z","size":380,"stargazers_count":671,"open_issues_count":25,"forks_count":137,"subscribers_count":15,"default_branch":"master","last_synced_at":"2025-03-17T03:17:03.676Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":"","language":"Clojure","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/JulianBirch.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGES.md","contributing":"CONTRIBUTING.md","funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2013-04-09T18:08:17.000Z","updated_at":"2025-02-21T00:00:22.000Z","dependencies_parsed_at":"2024-05-01T15:27:24.784Z","dependency_job_id":"ff60e856-556e-459f-83a7-2f2b704d569b","html_url":"https://github.com/JulianBirch/cljs-ajax","commit_stats":{"total_commits":287,"total_committers":78,"mean_commits":"3.6794871794871793","dds":0.7142857142857143,"last_synced_commit":"359e83ca0cd628c22252ba861860cb921622a618"},"previous_names":[],"tags_count":1,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/JulianBirch%2Fcljs-ajax","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/JulianBirch%2Fcljs-ajax/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/JulianBirch%2Fcljs-ajax/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/JulianBirch%2Fcljs-ajax/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/JulianBirch","download_url":"https://codeload.github.com/JulianBirch/cljs-ajax/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":244619271,"owners_count":20482389,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2024-07-31T03:01:43.934Z","updated_at":"2025-03-20T13:33:15.489Z","avatar_url":"https://github.com/JulianBirch.png","language":"Clojure","funding_links":[],"categories":["Clojure","front-end","Awesome ClojureScript"],"sub_categories":["Client/Server Communication"],"readme":"# cljs-ajax\n\nsimple Ajax client for ClojureScript and Clojure\n\n[![CircleCI](https://circleci.com/gh/JulianBirch/cljs-ajax.svg?style=shield)](https://circleci.com/gh/JulianBirch/cljs-ajax)\n\n`cljs-ajax` exposes the same interface (where useful) in both Clojure and ClojureScript. On ClojureScript it operates as a wrapper around [`goog.net.XhrIo`](https://developers.google.com/closure/library/docs/xhrio?hl=en) or [`js/XmlHttpRequest`](https://developer.mozilla.org/en-US/docs/Web/API/XMLHttpRequest), while on the JVM it's a wrapper around the [Apache HttpAsyncClient](https://hc.apache.org/httpcomponents-asyncclient-4.1.x/index.html) library. \n\nIn addition to this document, there's an [FAQ](docs/faq.md), a [change log](CHANGES.md) and a [contribution document](CONTRIBUTING.md). Furthermore, there is detailed documentation on specific features and design advice in the [docs folder](docs).\n\n## Usage\n\nLeiningen/Boot: `[cljs-ajax \"0.7.5\"]`\n\n[![Leiningen version](http://clojars.org/cljs-ajax/latest-version.svg)](http://clojars.org/cljs-ajax)\n\nThe client provides an easy way to send Ajax requests to the server using `GET`, `POST`, and `PUT` functions. It also provides a simple way using `ajax-request`. All requests are asynchronous, accepting callback functions for response and error handling.\n\nThere are four formats currently supported for communicating with the server:  `:transit`, `:json`, `:text` and `:raw`.\n(`:text` will send parameters up using normal form submission and return the raw text. `:raw` does the same, but on the JVM it returns the body's `java.io.InputStream` and *doesn't close it*.)\n\nFor advice on how to set up the server side in Clojure to work with `cljs-ajax`, please see the page on [handling responses on the server](docs/server.md).\n\n## GET/POST/PUT\n\nThe `GET`, `POST`, and `PUT` helpers accept a URI followed by a map of options:\n\n* `:handler` - the handler function for successful operation should accept a single parameter which is the deserialized response. If you do not provide a handler, the contents of the `default-handler` atom will be called instead. By default this is `println`.\n* `:progress-handler` - the handler function for progress events. **This handler is only available when using the `goog.net.XhrIo` API**\n* `:error-handler` - the handler function for errors, should accept an error response (detailed below). If you do not provide an error-handler, the contents of the `default-error-handler` atom will be called instead. By default this is `println` for Clojure and writes an error to the console for ClojureScript.\n* `:finally` - a function that takes no parameters and will be triggered during the callback in addition to any other handlers\n* `:format` - specifies the format for the body of the request (Transit, JSON, etc.). Also sets the appropriate `Content-Type` header.  Defaults to `:transit` if not provided.\n* `:response-format` - specifies that you'd like to receive a certain format of data from the server (by setting the `Accept` header and forcing the response to be parsed as the desired format).  If not provided, a permissive `Accept` header will be sent, and the response body will be interpreted according to the response's `Content-Type` header.\n* `:params` - the parameters that will be sent with the request,  format dependent: `:transit` and `:edn` can send anything, `:json`, `:text` and `:raw` need to be given a map.  `GET` will add params onto the query string, `POST` will put the params in the body\n* `:url-params` - parameters that will be added onto query string. In the case of a GET request, parameters defined here will replace parameters defined in `:params`.\n* `:timeout` - the ajax call's timeout in milliseconds.  Default is `0` (no timeout).\n* `:headers` - a map of the HTTP headers to set with the request\n* `:cookie-policy` - a keyword for the cookie management specification. **Only available in Java**. Optional. One of `:none`, `:default`, `:netscape`, `:standard`, `:standard-strict`.\n\n* `:with-credentials` - a boolean, whether to set the `withCredentials` flag on the XHR object.\n* `:body` the exact data to send with in the request. If specified, both `:params` and `:request-format` are ignored.  Note that you can submit js/FormData and other \"raw\" javascript types through this.\n* `:interceptors` - the [interceptors](docs/interceptors.md) to run for this request. If not set, runs contents of the `default-interceptors` global atom. This is an empty vector by default. For more information, visit the [interceptors page](docs/interceptors.md).\n\nNote that you can override `default-handler` and `default-error-handler`, but they are global to your application/page.\n\n### JSON specific settings\n\nThe following settings affect the interpretation of JSON responses:  (You must specify `:response-format` as `:json` to use these.)\n\n* `:keywords?` - true/false specifies whether keys in maps will be keywordized\n* `:prefix` - the prefix to be stripped from the start of the JSON response. e.g. `while(1);` which is added by some APIs to [prevent JSON hijacking](https://stackoverflow.com/questions/2669690/why-does-google-prepend-while1-to-their-json-responses).  You should *always* use this if you've got a GET request.\n\n### GET specific settings\n\nThe `:vec-strategy` setting affects how sequences are written out. \nA `:vec-strategy` of `:java` will render `{:a [1 2]}` as `a=1\u0026a=2`.\nA `:vec-strategy` of `:rails` will render `{:a [1 2]}` as `a[]=1\u0026a[]=2`. This is also the correct setting for working with HTTP.\n\n### GET/POST examples\n\n```clojure\n(ns foo\n  (:require [ajax.core :refer [GET POST]]))\n\n(defn handler [response]\n  (.log js/console (str response)))\n\n(defn error-handler [{:keys [status status-text]}]\n  (.log js/console (str \"something bad happened: \" status \" \" status-text)))\n\n(GET \"/hello\")\n\n(GET \"/hello\" {:params {:foo \"foo\"}})\n\n(GET \"/hello\" {:params {:a 0\n                        :b [1 2]\n                        :c {:d 3 :e 4}\n                        \"f\" 5}})\n;;; writes \"a=0\u0026b=1\u0026b=2\u0026c[d]=3\u0026c[e]=4\u0026f=5\"\n\n(GET \"/hello\" {:params {:a 0\n                        :b [1 2]\n                        :c {:d 3 :e 4}\n                        \"f\" 5}\n               :vec-strategy :rails})\n;;; writes \"a=0\u0026b[]=1\u0026b[]=2\u0026c[d]=3\u0026c[e]=4\u0026f=5\"\n\n\n(GET \"/hello\" {:handler handler\n               :error-handler error-handler})\n\n(POST \"/hello\")\n\n; Post a transit format message\n(POST \"/send-message\"\n        {:params {:message \"Hello World\"\n                  :user    \"Bob\"}\n         :handler handler\n         :error-handler error-handler})\n\n\n; Will send file inputs that are in the form\n(POST \"/send-form-modern\" {:body (js/FormData. form-element)})\n\n; Send file explicitly, ClojureScript specific\n(let [form-data (doto\n                    (js/FormData.)\n                  (.append \"id\" \"10\")\n                  (.append \"file\" js-file-value \"filename.txt\"))]\n  (POST \"/send-file\" {:body form-data\n                      :response-format (raw-response-format)\n                      :timeout 100}))\n\n; Send multiple files explicitly, ClojureScript specific\n; input-element is an html element of file type.\n(let [form-data (let [f-d (js/FormData.)\n      files (.-files input-element)]\n     (doseq [file-key (.keys js/Object files)]\n              (.append f-d file-key            \n                   (aget files file-key)))\n                    f-d)]\n    (POST \"/send-files\" {:body form-data\n                         :response-format (raw-response-format)\n                         :timeout 1000}))\n                      \n(POST \"/send-message\"\n        {:params {:message \"Hello World\"\n                  :user    \"Bob\"}\n         :handler handler\n         :error-handler error-handler\n         :response-format :json\n         :keywords? true})\n         \n(PUT \"/add-item\"\n     {:params {:id 1 :name \"mystery item\"}})\n     \n(GET {:url \"/generate.png\" ; Request a PNG and get it back as a js/ArrayBuffer\n      :response-format {:content-type \"image/png\" :description \"PNG image\" :read -body :type :arraybuffer}})\n```\n\n### FormData support\n\nNote that `js/FormData` is not supported before IE10, so if you need to support those browsers, don't use it.  `cljs-ajax` doesn't have any other support for file uploads (although pull requests are welcome).  Also note that you *must* include `ring.middleware.multipart-params/wrap-multipart-params` in your ring handlers as `js/FormData` always submits as multipart even if you don't use it to submit files.\n\n### Error Responses\n\nAn error response is a map with the following keys passed to it:\n\n* `:status` - the HTTP status code, numeric. A dummy number is provided if you didn't get to the server.\n* `:status-text` - the HTTP status message, or feedback from a parse failure\n* `:failure` - a keyword describing the type of failure\n  * `:error` an error on the server\n  * `:parse` the response from the server failed to parse\n  * `:aborted` the client aborted the request\n  * `:timeout` the request timed out\n\nIf the failure had a valid response, it will be stored in the `:response` key.\n\nIf the error is `:parse` then the raw text of the response will be stored in `:original-text`.\n\nFinally, if the server returned an error, and that then failed to parse, it will return the error map, but add a key `:parse-error` that contains the parse failure.\n\nThe `error-handler` for `GET`, `POST`, and `PUT` is passed one parameter which is an error response.  Note that *in all cases* either `handler` or `error-handler` will be called.  You should never get an exception returned by `GET`, `POST` etcetera.\n\n## ajax-request\n\nThe `ajax-request` is the simple interface.  It differs from the GET and POST API as follows:\n\n* **You can't use keywords to specify formats. You must provide a complete format in your request (see the [formats documentation](docs/formats.md) for more details)**\n* The API is harder to use.\n* You can use your own formats.\n* It compiles to smaller code when advanced optimizations are switched on.\n* It doesn't do Content-Type discovery.\n* There's only one handler, so you have to handle errors.\n\nIt has a single parameter, which is a map with the following members:\nThe parameters are: \n* `:uri`\n* `:method` - (`:get`, `\"GET\"`, `:post` or `\"POST\"` etcetera)  \n* `:format` and `:response-format`, documented in the [formats documentation](docs/formats.md)\n* `:handler` - A function that takes a single argument `[ok result]`.  The result will be the response if true and the error response if false.\n\nThe following parameters are the same as in the `GET`/`POST` easy api:\n* `:params` - the parameters that will be sent with the request,  format dependent: `:transit` and `:edn` can send anything, `:json` and `:raw` need to be given a map.  `GET` will add params onto the query string, `POST` will put the params in the body\n* `:timeout` - the ajax call's timeout.  30 seconds if left blank\n* `:headers` - a map of the HTTP headers to set with the request\n* `:cookie-policy` - a keyword for the cookie management specification. **Only available in Java**. Optional. One of `:none`, `:default`, `:netscape`, `:standard`, `:standard-strict`.\n* `:with-credentials` - a boolean, whether to set the `withCredentials` flag on the XHR object.\n* `:interceptors` - the [interceptors](docs/interceptors.md) to run for this request. If not set, runs contents of the `default-interceptors` global atom. This is an empty vector by default. For more information, visit the [interceptors page](docs/interceptors.md).\n\n### `ajax-request` examples\n\n```clj\n(defn handler2 [[ok response]]\n  (if ok\n    (.log js/console (str response))\n    (.error js/console (str response))))\n\n(ajax-request\n        {:uri \"/send-message\"\n         :method :post\n         :params {:message \"Hello World\"\n                  :user    \"Bob\"}\n         :handler handler2\n         :format (json-request-format)\n         :response-format (json-response-format {:keywords? true})})\n\n(ajax-request\n        {:uri \"/send-message\"\n         :method :post\n         :params {:message \"Hello World\"\n                  :user    \"Bob\"}\n         :handler handler2\n         :format (url-request-format) \n         :response-format (json-response-format {:keywords? true})})\n```\n\nThese examples will use the Google Closure library `XhrIo` API. If you want to use `XMLHttpRequest` API directly, add `:api (js/XMLHttpRequest.)` to the map.\n\n## License\n\nDistributed under the Eclipse Public License, the same as Clojure.\n\n\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2FJulianBirch%2Fcljs-ajax","html_url":"https://awesome.ecosyste.ms/projects/github.com%2FJulianBirch%2Fcljs-ajax","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2FJulianBirch%2Fcljs-ajax/lists"}