Liking cljdoc? Tell your friends :D

Introduction

yada is a web library for Clojure that lets you write websites and web APIs that conform to HTTP standards.

Despite some differences, virtually all web libraries do a similar thing: call your code with some request data and ask you to return a response, leaving the bulk of the responsibililty for implementing the HTTP standards in your hands: responding with the correct status codes, response headers and ensuring semantics have been followed properly.

yada is different. Rather than leaving all the implementation details to you, it helps you out in doing the right thing (according to HTTP standards), thereby creating a better web [1].

It achieves this by providing you with a highly-configurable handler that is general enough to use in the vast majority of cases. Rather than coding the handler, the developer only has to configure one. This declarative approach provides greater scope for accuracy, consistency and re-use.

yada represents a break from the traditional yet stale method of building web backends, an approach that can trace its roots all the way back to the days of Common Gateway Interface. While yada's data-oriented approach takes full advantage of the data-oriented philosophy of Clojure, there’s no reason why this methodology cannot be implemented by new web libraries in other languages.

Using yada for your web project will allow you to finally exploit and benefit from the many features embodied in the outstanding design of HTTP, for scale, flexibility, security, longevity and interoperability.

Design goals

yada is designed to meet the following goals:

  • Be easy to use for intermediate Clojure developers

  • Comprehensive compliance with HTTP standards over pragmatism and performance

  • Increase productivity through re-use

  • Handle large workloads with reasonable performance

  • Support multiple architectural styles, including Hypermedia APIs (REST)

yada is not an experiment. It is designed for, and has been tested in, production environments.

yada is sufficiently quick-and-easy for quick prototype work but scales up when you need it to, to feature-rich secure services that can handle the most demanding workloads, while remaining faithful to the HTTP standards.

Some familiarity with HTTP will help you understand yada concepts quicker, but isn’t absolutely necessary. As you learn how to wield yada you will also discover and learn more about the HTTP standards as you go.

Say 'Hello!' to yada

It’s quick to get started with yada without knowing how it works - it’s easy to get started even if you only have a basic knowledge of Clojure.

Let’s begin with a few examples. The obligatory Hello World! example is (yada/handler "Hello World!"), which responds with a message.

Perhaps you might want to serve a file? That’s (yada/handler (new java.io.File "index.html")).

Now you know how to serve a file, you know how to serve a directory. But perhaps you’ve got some resources on the classpath? (yada/handler (clojure.java.io/resource "talks/")).

What about (yada/handler nil)? Without knowing, can you guess what that might do? (That’s right, it produces a 404 Not Found response).

What about a quick dice generator? (yada/handler #(inc (rand-int 6))). Notice we use a function here, rather than a constant value, to vary numbers between rolls.

How about streaming those dice rolls as 'Server Sent Events'? Put those dice rolls on a core.async channel, and return it with yada.

All these examples demonstrate the use of Clojure types that are converted on-the-fly into yada resources, and you can create your own types too.

Let’s delve a little deeper…

Resources

In yada, resources are defined by a plain-old Clojure map.

This has many benefits. While functions are opaque, data is open to inspection. Data structures are easy to generate, transform and query - chores that Clojure makes light work of.

Here’s an example of a resource:

(yada/resource
  {:properties {…}
   :methods {:get {:response (fn [ctx] "Hello World!")}
             :put {…}
             :brew {…}}
 …
})

There’s a lot of things you can do with a resource data model but perhaps the most obvious is to create a request handler from it to create responses from HTTP requests. That’s the role of a handler.

With yada, we transform a resource into a handler using the handler function.

(require '[yada.yada :as yada])

(yada/handler (yada/resource {…}))

A handler can be called as a function, with a single argument representing an HTTP request. It returns a value representing the corresponding HTTP response.

A yada handler is an instance of the yada.handler/Handler record. Since this record satisfies clojure.lang.IFn, yada handlers behave just like normal Ring handlers and can be used wherever you might use a Ring handler.

Serving requests

To use yada to create real responses to real HTTP requests, you need to add yada to a web-server. The web server takes care of the networking and messages of HTTP (RFC 7230), while yada focuses on the semantics and content ([RFC7231] and upwards).

Currently, the only web server you can use is ztellman/aleph. This is because yada is built on an asynchronous abstraction provided by ztellman/manifold. However, there is no technical reason why, in future, other web servers can’t be wrapped by manifold.

In the meantime, Aleph (which wraps a much bigger library, Netty) provides a very capable and performant server.

To write real applications you also need a router that understands URIs, and yada has some features that are enabled when used with juxt/bidi, although there is nothing to stop you using yada with other routing libraries.

Conclusion

That’s yada in a nutshell, but the quickest way to to learn it is to set up an environment and play. That’s what we’ll do in the next chapter.

Can you improve this documentation? These fine people already did:
Malcolm Sparks & Joshua Ballanco
Edit on GitHub

cljdoc is a website building & hosting documentation for Clojure/Script libraries

× close