Giter Site home page Giter Site logo

fnhouse's Introduction

fnhouse!

Leiningen dependency (Clojars): [prismatic/fnhouse "0.1.0"]

This is an alpha release. The API and organizational structure are subject to change. Comments and contributions are much appreciated.

fnhouse

Fnhouse is a library that builds on top of ring to provide a concise way to write web handlers safely, readably, without global variables, without repeating yourself, and with hooks to do much more.

Here is an example fnhouse handler:

(defnk $entries$POST
  "Add a new entry to the guestbook"
  {:responses {200 schemas/ClientEntry}}
  [[:request body :- schemas/EntryData]
   [:resources guestbook index]]
  (let [entry-id (swap! index inc)
        indexed-entry (assoc body :index entry-id)]
    (swap! guestbook assoc entry-id indexed-entry)
    {:body indexed-entry}))

This handler is implemented in terms of a keyword function (defnk) introduced in the Plumbing library. Using Schema, fnhouse handlers can specify the type of their input arguments: in the example above, body is declared to be of type EntryData. The handler explicitly declares the resources on which it depends: guestbook. The Schema annotations on the arguments to the handler allow for schema checking to validate that the inputs have the right structure.

The entirety of fnhouse consists of a small number of files that play nicely together, but can be easily substituted, if need be. To see an example use of fnhouse, check out guesthouse, the guestbook example.

schemas.clj

Defines Schemas for Handlers and HandlerInfo. The HandlerInfo is a Schema for information about a specific HTTP handler, like the one above. It specifies:

  • the path and the HTTP method of the handler (which are used in routing)
  • the declared Schemas of the following components of the request: the body, URI-args, and query-params
  • the responses, a map from status code to the Schema of the body field of the response that the handler returns
  • the resources upon which the handler depends
  • source map information specifying the source code location where the handler is defined
  • optionally it can also specify additional, arbitrary, user-defined annotations

handlers.clj

Defines nss->handlers-fn, which takes a map from path prefix string to namespace symbol. Sucks up all the fnhouse handlers in each namespace, and prefixes each handler's path with the corresponding path prefix. Finally, curries the resulting set of handlers to produce a function from a map of the union of all resources required by the handlers, to an API description (which is just a sequence of schemas/AnnotatedHandlers -- a handler function paired with HandlerInfo that describes it).

middleware.clj

Defines the coercion-middleware function, which takes an AnnotatedHandler, an input-coercer, and an output coercer. These coercers are functions from schema to functions of request and data; the inner functions return the transformed data (or nil, if coercion is not necessary). It wraps the handlers in a ring-style middleware that coerces and validates inputs and outputs. The middleware uses walkers to simultaneously coerce and validate inputs in a generous way (i.e., 1.0 in body will be cast to 1 in order to validate against a long schema), and outputs will be clientized to match the output schemas as specified by the output-coercer. If custom coercion is not needed, (constantly nil) can be passed as a no-op coercer.

routes.clj

Defines the root-handler function, which takes a seq of AnnotatedHandlers, and returns a single handler that routes the request to the appropriate handler while binding :uri-args in the request to the appropriate path segments.

docs.clj

A proof of concept, ultra-primitive HTML doc generation from a fnhouse API spec, including schemas and per-namespace handler doc pages. The docs.clj file defines the all-docs function, which generates HTML for handlers and schemas from a sequence of HandlerInfo descriptions. It also defines a handler $:page$GET that can serve up the HTML generated by the all-docs function.

For much richer, stylish and functional documentation (and much more) via swagger, check out fnhouse-swagger.

Example: Guesthouse

The guesthouse example, demonstrates how each of the components of fnhouse can be used in order to generate a simple, yet fully featured, web service. This example project provides a simple guestbook service in which clients can add, remove, modify, and search for entries in an online guestbook.

The handlers for the guestbook are all defined in guestbook.clj. To see how the components of fnhouse can be tied together in order to make a webserver look at the start-api method of core.clj. To see start-api in action, check out the corresponding core_test.clj.

Community

Please feel free to join the Plumbing mailing list to ask questions or discuss how you're using Schema.

For announcements of new releases, you can also follow on @PrismaticEng on Twitter.

We welcome contributions in the form of bug reports and pull requests; please see CONTRIBUTING.md in the repo root for guidelines.

Supported Clojure versions

Fnhouse is currently supported on Clojure 1.5.1 and 1.6.x.

License

Copyright (C) 2013 Prismatic and Contributors. Distributed under the Eclipse Public License, the same as Clojure.

fnhouse's People

Contributors

w01fe avatar davegolland avatar dbasch avatar si14 avatar mschulkind avatar loganlinn avatar

Watchers

Nikodim Lazarov avatar Tony Heckmann avatar  avatar Atanas Minev avatar James Cloos avatar Lunar Le avatar Ardavast Dayleryan avatar Vladimir Tzankov avatar Dimitar Kovachev avatar  avatar Stanislav Ivanov avatar Daniel Balchev avatar Akshaan Kakar avatar Svet avatar Ahmet Kucuk avatar Dave Stess avatar Yordan Madzhunkov avatar Sergey Orshanskiy avatar James Tillman avatar Ivan Atanasov avatar  avatar Peter Brodsky avatar Martin Obreshkov avatar Andrew Wilkes avatar  avatar Georgi Yanchev avatar Ivaylo Strandjev avatar Alexis Zubiolo avatar Lachezar Bozhkov avatar Alexander Yankov avatar  avatar  avatar  avatar

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.