{"id":15062828,"url":"https://github.com/zalando/friboo","last_synced_at":"2025-12-12T01:17:38.253Z","repository":{"id":28864161,"uuid":"32388310","full_name":"zalando/friboo","owner":"zalando","description":"Utility library for writing microservices in Clojure, with support for Swagger and OAuth","archived":true,"fork":false,"pushed_at":"2017-06-09T08:44:40.000Z","size":604,"stargazers_count":119,"open_issues_count":25,"forks_count":16,"subscribers_count":16,"default_branch":"master","last_synced_at":"2024-11-28T14:28:36.590Z","etag":null,"topics":["clojure","microservices","swagger","swagger-api"],"latest_commit_sha":null,"homepage":"","language":"Clojure","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"apache-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/zalando.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":"CONTRIBUTING.md","funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2015-03-17T11:00:26.000Z","updated_at":"2024-09-02T02:23:29.000Z","dependencies_parsed_at":"2022-09-05T08:51:36.363Z","dependency_job_id":null,"html_url":"https://github.com/zalando/friboo","commit_stats":null,"previous_names":["zalando-stups/friboo"],"tags_count":66,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/zalando%2Ffriboo","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/zalando%2Ffriboo/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/zalando%2Ffriboo/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/zalando%2Ffriboo/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/zalando","download_url":"https://codeload.github.com/zalando/friboo/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":235321032,"owners_count":18971231,"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":["clojure","microservices","swagger","swagger-api"],"created_at":"2024-09-24T23:47:09.078Z","updated_at":"2025-10-04T22:31:24.683Z","avatar_url":"https://github.com/zalando.png","language":"Clojure","funding_links":[],"categories":["RESTful API","Service Toolkits"],"sub_categories":["Java VM"],"readme":"# friboo\n\n![Maven Central](https://img.shields.io/maven-central/v/org.zalando.stups/friboo.svg)\n[![Build Status](https://travis-ci.org/zalando/friboo.svg?branch=master)](https://travis-ci.org/zalando/friboo)\n[![codecov](https://codecov.io/gh/zalando/friboo/branch/master/graph/badge.svg)](https://codecov.io/gh/zalando/friboo)\n\n**Friboo** is a lightweight utility library for writing microservices in Clojure. It provides several components that you can use with Stuart Sierra's [Component lifecycle framework](https://github.com/stuartsierra/component).\n\nFriboo encourages an \"API First\" approach based on the [Swagger specification](http://swagger.io/). As such, the REST API is defined as YAML.\n\n## Leiningen dependency\n\n    [org.zalando.stups/friboo 2.0.0]\n\n## Why Friboo?\n\n- Friboo allows you to first define your API in a portable, language-agnostic format, and then implement it (with the help of [swagger1st](https://github.com/sarnowski/swagger1st)).\n- It contains ready-made components/building blocks for your applications: An HTTP server, DB access layer, metrics registry, Hystrix dashboard (in case you have compliance requirements to follow), and more. See [Components](#components).\n- Pluggable support for all authentication mechanisms (basic, OAuth 2.0, API keys). \n- It contains the \"glue code\" for you, and there is already a recommended way of doing things.\n\n## Development Status\n\nIn our production we use an extension library that is based on Friboo: [friboo-ext-zalando](https://github.com/zalando-incubator/friboo-ext-zalando).\nSee the list at the end of this page.\nHowever, there is always room for improvement, so we're very much open to contributions. For more details, see our [contribution guidelines](CONTRIBUTING.md) and check the Issues Tracker for ways you can help.\n\n## Getting Started\n\n### Requirements\n\n* [Leiningen](http://leiningen.org/)\n\n### Starting a New Project\n\nTo start a new project based on Friboo, use the Leiningen template:\n\n    $ lein new friboo com.example/friboo-is-awesome\n\nThis will generate a sample project containing some \"foobar\" logic that can serve as a starting point in your experiments.\n\nA new directory with name `friboo-is-awesome` will be created in the current directory, containing the following files:\n\n```\nfriboo-is-awesome\n├── README.md\n├── dev\n│   └── user.clj\n├── dev-config.edn\n├── project.clj\n├── resources\n│   └── api\n│       └── api.yaml\n├── src\n│   └── com\n│       └── example\n│           └── friboo_is_awesome\n│               ├── api.clj\n│               └── core.clj\n└── test\n    └── com\n        └── example\n            └── friboo_is_awesome\n                ├── api_test.clj\n                └── core_test.clj\n```\n\n* `README.md` contains some pregenerated development tips for the new project.\n* `dev/user.clj` contains functions for [Reloaded Workflow](http://thinkrelevance.com/blog/2013/06/04/clojure-workflow-reloaded).\n* `dev-config.edn` contains environment variables that will be used during reloaded workflow (instead of putting them into `profiles.clj`).\n* `project.clj` contains the project definition with all dependencies and some additional plugins.\n* `resources/api.yaml` contains the [Swagger API definition](https://github.com/OAI/OpenAPI-Specification/blob/master/versions/2.0.md) in .yaml format.\n* `src` directory contains these files:\n\t* `core.clj` is the [system](https://github.com/stuartsierra/component#systems) definition.\n\t* `api.clj` contains API endpoint handlers.\n* the `test` directory contains unit test examples using both `clojure.test` and [Midje](https://github.com/marick/Midje).\n\n## How Friboo works\n\nThere are two core parts in any Friboo application:\n\n- loading configuration by aggregating many sources\n- starting the [system](https://github.com/stuartsierra/component#systems)\n\nBoth these parts are taken care of in `core.clj` in `run` function. The name \"run\" is not fixed, it can be anything.\n\nLet's put configuration aside for now. A minimal `run` function might look like this:\n\n```clojure\n(require '[com.stuartsierra.component :as component]\n         '[org.zalando.stups.friboo.system.http :as http]\n         '[org.zalando.stups.friboo.system :as system])\n\n(defn run []\n  (let [system (component/map-\u003eSystemMap\n                 {:http (http/make-http \"api.yaml\" {})})]\n    (system/run {} system)))\n```\n\nHere we declare a system that has just one component created by `make-http` function. When started, this component will expose a RESTful API\nwhere requests are routed according to the Swagger definition in `api.yaml`, which is taken from the classpath (usually `resources/api.yaml`).\n\nThen we call `run` from `-main`:\n\n```clojure\n(defn -main [\u0026 args]\n  (try\n    (run)\n    (catch Exception e\n      (println \"Could not start the system because of\" (str e))\n      (System/exit 1))))\n```\n\n`run` function does not block, it immediately returns the started system that can later be stopped (as reloaded workflow suggests). \n\nThis already works, but it's not too flexible.\n\n### Parsing configuration options\n\nAccording to https://12factor.net/config, configuration should be provided via environment variables.\nHowever, with REPL-driven [reloaded workflow](http://thinkrelevance.com/blog/2013/06/04/clojure-workflow-reloaded) you would have to restart the JVM\nevery time you need to change a configuration value. That's less than perfect.\n\nFriboo supports several sources of configuration:\n\n- environment variables: `HTTP_PORT=8081`\n- JVM properties: `http.port=8081`\n- development configuration from `dev-config.edn`: `{:http-port 8081}`\n- default configurations per component (hardcoded)\n\nAnother challenge is — how to give components only the configuration they need? What if more than one component would like to use `PORT` variable?\nFriboo solves this with namespacing of configuration parameters. Namespace in this case is just a known prefix: `HTTP_`, `API_`, `ENGINE_` etc.\n\nConfiguration is in loaded inside `run` by `load-config` function before defining the system:\n\n```clojure\n(defn run [args-config]\n  (let [config (config/load-config\n                 (merge default-http-config\n                        args-config)\n                 [:http])\n        system (component/map-\u003eSystemMap\n                 {:http (http/make-http \"api.yaml\" (:http config))})]\n    (system/run config system)))\n```\n\nHere we make `run` accept a configuration map as an argument, it acts as an additional source of configuration (and it is used by Reloaded Workflow to inject reloadable configuration, see `dev/user.clj`).\n\n`load-config` takes 2 arguments:\n\n- map of default configuration that looks like this:\n\n```clojure\n{:http-port   8081\n :db-password \"1q2w3e4r5t\"\n :foo-bar     \"foobar\"\n```\n\n- list of namespaces, which are known prefixes configuration variables that we expect:\n\n```clojure\n[:http :db]\n```\n\nConfiguration parameters' names are normalized in the following way (this is actually done by [environ](https://github.com/weavejester/environ)):\n\n- `HTTP_PORT` becomes `:http-port`\n- `http.port` becomes `:http-port`\n\n`load-config` normalizes names in all configuration sources, merges them (real environment overrules the default config), filters the parameters by known prefixes and returns a nested map:\n\n```clojure\n{:http {:port 8081}\n :db   {:password \"1q2w3e4r5t\"}}\n```\n\nNote that `:foo-bar` parameter did not make it into the output, because it does not start with `:http-` nor `:db-`.\n\nAfter we have this configuration loaded, it's very straightforward to give each component its part:\n\n```clojure\n{:http (http/make-http \"api.yaml\" (:http config))\n :db   (db/make-db (:db config))}\n```\n\n`system/run` also takes the entire configuration as the first argument and uses the `:system` part of it.\n\n## Components\n\n### HTTP Component\n\nHTTP component starts a HTTP server and routes the requests based on the Swagger API definition. It lives in `org.zalando.stups.friboo.system.http` namespace.\n\nIt has an optional dependency `:controller` that is given to all\nAPI handlers as first argument. The use case is to make it contain some configuration\nand dependencies that the handlers should have access to.\n\n```yaml\npaths:\n  '/hello/{name}':\n    get:\n      operationId: \"com.example.myapp.api/get-hello\"\n      responses: {}\n```\n\nPart of system map (we make `:api` component to be a simple map, it's not necessary \nfor every component to implement `com.stuartsierra.component/Lifecycle` protocol):\n\n```clojure\n:http      (component/using\n             (http/make-http \"api.yaml\" (:http config))\n             {:controller :api})\n:api       {:configuration (:api config)}\n```\n\n`{:controller :api}` means that `:api` component will be available to `:http` under the name `:controller`, that's what it expects.\n\nIn `com.example.myapp.api` namespace:\n\n```clojure\n(defn get-hello [{:keys [configuration]} {:keys [name]} request]\n  (response {:message (str \"Hello \" name)}))\n```\n\n`get-hello` (and every other API handler function) is called with 3 arguments:\n\n- `:controller` (`:api` component in our example)\n- merged parameters map from path, query and body parameters\n- raw request map\n\nEvery handler function is expected to return a map representing a HTTP response:\n\n```clojure\n{:body    {:message \"Hello Michael\"}\n :headers {}\n :status  200\n```\n\nIn our example we use `ring.util.response/response` to create a HTTP 200.\n\n#### Configuration Options\n\n* There are all the [configuration options](https://ring-clojure.github.io/ring/ring.adapter.jetty.html) that Jetty supports, for example:\n\n```clojure\n{:port        8081\n :cors-origin \"*.zalando.de\"}\n```\n\n### DB Component\n\nDB component encapsulates JDBC connection pool and provides [Flyway](https://flywaydb.org/) to support schema migrations.\n\nWhen the component starts, it will have additional `:datasource` key that contains an implementation of `javax.sql.DataSource`. You can use it as you like.\n\nOne of the examples is in friboo-ext-zalando:\n\n    $ lein new friboo-ext-zalando db-example\n\nTake a look at the following files:\n\n```\nexample\n├── resources\n│   └── db\n│       ├── migration\n│       │   └── V1__initial_schema.sql\n│       └── queries.sql\n└── src\n    └── db_example\n        ├── api.clj\n        ├── core.clj\n        └── sql.clj\n```\n\n#### Configuration Options\n\nFor available options please refer to `org.zalando.stups.friboo.system.db/start-component`\n\n### Metrics Component\n\nThe metrics component initializes a [Dropwizard MetricsRegistry](http://metrics.dropwizard.io) to measure\nfrequency and performance of the Swagger API endpoints; see [HTTP component](#http-component).\n\n### Management HTTP component\n\nThis component starts another embedded Jetty at a different port (default 7979) and exposes endpoints used to monitor and manage the application:\n\n* `/metrics`: A JSON document containing all metrics, gathered by the metrics component\n* `/hystrix.stream`: The [Hystrix](https://github.com/Netflix/Hystrix) stream (can be aggregated by [Turbine](https://github.com/Netflix/Turbine))\n* `/monitor/monitor.html`: The Hystrix dashboard\n\n#### Configuration Options\n\nAll [Jetty configuration options](https://ring-clojure.github.io/ring/ring.adapter.jetty.html). \n\n## Real-World Usage\n\nThere are multiple examples of real-world usages of Friboo, including among Zalando's STUPS components:\n\n* [Pier One Docker registry](https://github.com/zalando-stups/pierone) (REST service with DB and S3 backend)\n* [Kio application registry](https://github.com/zalando-stups/kio) (REST service with DB)\n* [Even SSH access granting service](https://github.com/zalando-stups/even) (REST service with DB)\n* [Essentials](https://github.com/zalando-stups/essentials) (REST service with DB)\n\nTODO HINT: set java.util.logging.manager= org.apache.logging.log4j.jul.LogManager to have proper JUL logging.\n\n## License\n\nCopyright © 2016 Zalando SE\n\nLicensed under the Apache License, Version 2.0 (the \"License\");\nyou may not use this file except in compliance with the License.\nYou may obtain a copy of the License at\n\n   [http://www.apache.org/licenses/LICENSE-2.0](http://www.apache.org/licenses/LICENSE-2.0)\n\nUnless required by applicable law or agreed to in writing, software\ndistributed under the License is distributed on an \"AS IS\" BASIS,\nWITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\nSee the License for the specific language governing permissions and\nlimitations under the License.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fzalando%2Ffriboo","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fzalando%2Ffriboo","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fzalando%2Ffriboo/lists"}