Home

Awesome

swagger1st: A Swagger-First Clojure Ring handler

Maven Central Build Status codecov

swagger1st is a Clojure Ring handler that parses, validates and routes requests based on your Swagger/OpenAPI definition. It takes the opposite approach of ring-swagger—which enables you to generate your Swagger spec from your Clojure code—by allowing you to use your Swagger spec to generate Clojure code.

Instead of defining routes and validation rules in your code, you can use swagger1st along with Swagger/OpenAPI's great tool set to specify your API according to the Swagger/Open API 2.0 Specification. This enables you to specify your API in an API-First, technology-independent format. The resulting definition is the ultimate format for publishing, sharing and reviewing your API.

Compatibility Overview

swagger1st aims to implement all of the Swagger/OpenAPI spec's features, so that you only have to write your business logic. This document shows which aspects of the spec it currently supports.

swagger1st will use the Swagger definition of your API as a configuration file for processing incoming requests—ensuring that your implementation and specification always remain in sync. During runtime, you can inspect and easily test your API with the built-in Swagger UI. You can also extend the interpretation of your definition according to your own needs.

Imagine a simple API definition like this:

swagger: '2.0'

info:
  title: Example API
  version: '0.1'

paths:
  /helloworld:
    get:
      summary: Returns a greeting.
      operationId: example.api/generate-greeting
      parameters:
        - name: firstname
          in: query
          type: string
          pattern: "^[A-Z][a-z]+"
      responses:
          200:
              description: say hello

By default, this definition is connected to your business logic via the operationId, which might be defined like so:

(ns example.api
  (:require [ring.util.response :as r]))

(defn generate-greeting [request]
  (let [firstname (-> request :parameters :query :firstname)]
    (-> (r/response (str "Hello " firstname "!"))
        (r/content-type "plain/text"))))

This is all you need to do to define and implement your API. Only fully validated requests get to your function, so you can rely on swagger1st to properly check all input parameters according to your definition. The function itself is a normal Clojure function without any dependencies to swagger1st - simple as that.

Quickstart

The following provides instructions for simple, complex and manual setups. For all three approaches you'll need to install Leiningen as the build tool.

Simple Setup

If you're bootstrapping a completely new project, or just want to try out swagger1st, you can use this Leiningen template:

$ lein new swagger1st myproject
$ cd myproject
$ lein ring server-headless

This will run a local web server on port 3000, so you can interact with the API at http://localhost:3000/. Also, you might want to have a look at http://localhost:3000/ui/ for a graphical interface to explore and experiment with your API (using Swagger UI).

Complex Setup

To see how you can handle dependency injection with swagger1st, generate a project setup that includes Stuart Sierra's component framework:

$ lein new swagger1st myproject +component
$ cd myproject
$ lein run -m myproject.core

As with the simple setup above, this will launch a local web server on port 3000.

Manual Setup

The following steps describe how to manually set up swagger1st in a Clojure project. This is especially useful if you want to integrate it into an existing project or cannot use the provided template for other reasons.

Use the following dependency in your Leiningen project:

[org.zalando/swagger1st "<latest>"]

This creates a Ring-compliant handler:

(ns example
  (:require [io.sarnowski.swagger1st.core :as s1st]
            [io.sarnowski.swagger1st.util.security :as s1stsec]))

(def app
  (-> (s1st/context :yaml-cp "my-swagger-api.yaml")
      (s1st/discoverer)
      (s1st/mapper)
      (s1st/parser)
      (s1st/protector {"oauth2" (s1stsec/allow-all)})
      (s1st/executor)))

Commands for Development

# get the source
$ git clone https://github.com/zalando-stups/swagger1st.git
$ cd swagger1st

# run the tests
$ lein test

# run all tests, including performance benchmarks
$ lein test :all

# build an own artifact for local development
$ lein install

# release a new version
$ lein release :minor

For interactive development, you can start a REPL by typing lein repl.

Projects Using Swagger1st in Production

The Ring Handler in Detail

License

Copyright (c) 2015, Tobias Sarnowski Copyright (c) 2016, Zalando SE

Permission to use, copy, modify, and/or distribute this software for any purpose with or without fee is hereby granted, provided that the above copyright notice and this permission notice appear in all copies.

THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.