{"id":26194268,"url":"https://github.com/active-group/active-data-http","last_synced_at":"2026-02-09T08:02:33.292Z","repository":{"id":259464765,"uuid":"874788389","full_name":"active-group/active-data-http","owner":"active-group","description":"Utility library to use active-data in web server and client environments.","archived":false,"fork":false,"pushed_at":"2025-01-09T08:22:18.000Z","size":104,"stargazers_count":0,"open_issues_count":1,"forks_count":0,"subscribers_count":4,"default_branch":"main","last_synced_at":"2025-10-21T06:26:25.568Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"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/active-group.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"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":"2024-10-18T13:13:33.000Z","updated_at":"2025-01-09T08:22:22.000Z","dependencies_parsed_at":"2024-10-25T18:22:05.561Z","dependency_job_id":"2785c081-d40e-497f-a2e2-b4212209001c","html_url":"https://github.com/active-group/active-data-http","commit_stats":null,"previous_names":["active-group/active-data-http"],"tags_count":2,"template":false,"template_full_name":null,"purl":"pkg:github/active-group/active-data-http","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/active-group%2Factive-data-http","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/active-group%2Factive-data-http/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/active-group%2Factive-data-http/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/active-group%2Factive-data-http/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/active-group","download_url":"https://codeload.github.com/active-group/active-data-http/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/active-group%2Factive-data-http/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":29259466,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-02-09T04:11:57.159Z","status":"ssl_error","status_checked_at":"2026-02-09T04:11:56.117Z","response_time":56,"last_error":"SSL_connect returned=1 errno=0 peeraddr=140.82.121.5:443 state=error: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"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":"2025-03-12T01:55:59.660Z","updated_at":"2026-02-09T08:02:33.239Z","avatar_url":"https://github.com/active-group.png","language":"Clojure","funding_links":[],"categories":[],"sub_categories":[],"readme":"[![Clojars Project](https://img.shields.io/clojars/v/de.active-group/active-data-http.svg)](https://clojars.org/de.active-group/active-data-http)\n[![cljdoc badge](https://cljdoc.org/badge/de.active-group/active-data-http)](https://cljdoc.org/d/de.active-group/active-data-http/CURRENT)\n\nThe goal of this library is to facilitate using data described by\n[realms](https://github.com/active-group/active-data) in web\napplications contexts, i.e. when transporting data via http.\n\n[Latest Version](https://clojars.org/de.active-group/active-data-http)\n\n[API Docs](https://cljdoc.org/d/de.active-group/active-data-http/CURRENT)\n\n## Introduction\n\nThere are two main facilities included in this library. One part is\nfor defining translations of your data in Transit/EDN form. The second\npart is to simplify defining and using server endpoints used by fat\nweb clients.\n\n### Transit format\n\nBased on\n[active-data-translate](https://github.com/active-group/active-data-translate),\nthere is a \"batteries included\" transit format that can translate\nbetween most of your data and a transit compatible form automatically:\n\n```\nactive.data.http.formats.transit/transit-format\n```\n\nUse this only if the coupling introduced by that is not an issue, or\ncan be mitigated by other means.\n\nThe coupling can for example be\n  \n- between producer and consumer code of the transit values, if\n  they are developed independently, or\n\n- between past and future versions of the code, if transit values are\n  written to some kind of databases, or if producer and consumer can\n  have different versions of the code.\n\nIn those situations, you should define explicit translations for the\nrealms that are defined in your code and thus are subject to potential\nchange over time. You can use\n\n```\nactive.data.http.formats.transit/basic-formatters\n```\n\nas a base for that, which includes formatters for things that are\nunlikely to change, like formatting strings as strings, numbers as\nnumbers, and sequences as vectors, etc.\n\n### Reitit coercion\n\nA reitit coercion based on realms and a format is available in the\n`active.data.http.reitit` namespace. This allows you to declare\nparameters and response bodies as realms, and have them automatically\ntranslated via the format.\n\n```clojure\n(require '[active.data.http.reitit :as http-reitit])\n\n(def-record user [...])\n\n(def my-format ...)\n\n[\"/api/public/get-user/:id\"\n {:get {:handler (fn [request]\n                   {:status 200\n                    :body (db/get-user-from-db (:id (:path (:parameters request))))})\n        :parameters {:path {:id realm/integer}}\n        :responses {200 {:body user}}\n        :coercion (http-reitit/realm-coercion my-format)}}]\n```\n\nSee\n[active-data-translate](https://github.com/active-group/active-data-translate)\non how to define formats.\n\nNote that to get this working you'll need a few middlewares for these\nroutes. Namely the coersion middlewares, parameters-middleware and\nsome transit middleware like muuntaja:\n\n```clojure\n{:middleware \n [reitit.ring.coercion/coerce-exceptions-middleware\n  reitit.ring.coercion/coerce-request-middleware\n  reitit.ring.coercion/coerce-response-middleware\n  reitit.ring.middleware.parameters/parameters-middlware]\n :muuntaja muuntaja.core/instance}\n```\n\nSee Reitit documentation for more details on how this can be set up.\n\n### RPCs\n\nTo make endpoints for a webclient served by the same server and the\nusage of them even easier to set up, there is an \"RPC\"-like facility\nincluded in this library.\n\nIt is intended for \"internal apis\" and shared code (cljc) only, where\nthe coupling between the server and the client code is not an issue.\n\nTo use this, you would first define a so called context and the api in\nsome shared code (cljc file):\n\n```clojure\n(require '[active.data.http.rpc :as rpc #?(:cljs :include-macros true)])\n\n(def internal-api (rpc/context \"/api/internal\"))\n\n(rpc/defn-rpc get-user! internal-api :- user [id :- realm/integer])\n```\n\nAnd define implementations for those RPCs in some server code, for\nexample with reitit:\n\n```clojure\n(require '[active.data.http.rpc.reitit :as rpc-reitit])\n\n(def routes\n  (rpc-reitit/context-routes\n    internal-api\n    [(rpc-reitit/impl get-user! db/get-user-from-db)]))\n```\n\nAnd finally to \"call\" those RPCs from the client side, for example with\nthe [reacl-c](https://github.com/active-group/reacl-c) library, you\nwould modify the shared api code to add a \"caller\" to the context like\nso:\n\n```clojure\n(require '[active.data.http.rpc :as rpc #?(:cljs :include-macros true)])\n#?(:cljs (require '[active.data.http.rpc.reacl-c :as rpc-reacl-c]))\n\n(def internal-api (-\u003e (rpc/context \"/api/internal\")\n                      #?(:cljs (rpc/set-context-caller rpc-reacl-c/caller))))\n```\n\nWhich then enables you to call the names defined by `defn-rpc` as a\nfunction to get a reacl-c request, which can then be executed in various\nways:\n\n```clojure\n(require '[reacl-c-basics.ajax :as ajax])\n\n(ajax/fetch (get-user! 4711))\n```\n\nSee [reacl-c-basics](https://github.com/active-group/reacl-c-basics)\nfor more details on that.\n\n### Signals\n\nSignals are (small) pieces of data sent by the server to your fat\nwebclient, for example to inform it that new data is available. It is\nnot recommended to send that data itself, but to fetch that data\nseparately after receiving a signal to do so.\n\nTo add that to your shared internal api, you can write something like\nthis:\n\n```clojure\n(require '[active.data.http.signals :as signals])\n\n(def wakeup-signal ::wakeup)\n\n(defonce signals\n  (signals/context \"/api/internal-signals\"\n                   (realm/enum wakeup-signal)))\n```\n\nNote: the context has some internal state, so it is recommended to use\n`defonce` for it.\n\nTo get the necessary reitit routes use\n\n```clojure\n(require '[active.data.http.signals.reitit :as signals.reitit])\n\n(def routes\n  (signals.reitit/context-routes api/signals))\n```\n\nTo actually signal something\n\n```clojure\n(require '[active.data.http.signals :as signals])\n\n(signals/broadcast! api/signals api/wakeup-signal)\n```\n\nAnd to receive signals when using [reacl-c](https://github.com/active-group/reacl-c):\n\n```clojure\n(require '[active.data.http.signals.reacl-c :as signals])\n\n;; an item that emits the current timestamp when a wakeup is received\n(signals/receive api/signals api/wakeup-signals)\n```\n\nNote that signals use websockets under the hood, so you need a recent\nversion of ring and a ring-adapter that supports websockets.\n\n## License\n\nCopyright © 2024 Active Group GmbH\n\nThis program and the accompanying materials are made available under the\nterms of the Eclipse Public License 2.0 which is available at\nhttp://www.eclipse.org/legal/epl-2.0.\n\nThis Source Code may also be made available under the following Secondary\nLicenses when the conditions for such availability set forth in the Eclipse\nPublic License, v. 2.0 are satisfied: GNU General Public License as published by\nthe Free Software Foundation, either version 2 of the License, or (at your\noption) any later version, with the GNU Classpath Exception which is available\nat https://www.gnu.org/software/classpath/license.html.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Factive-group%2Factive-data-http","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Factive-group%2Factive-data-http","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Factive-group%2Factive-data-http/lists"}