Skip to content

kellenff/ring-middleware-accept

 
 

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

17 Commits
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

ring-middleware-accept

ring-middleware-accept is a Ring middleware component for performing server-driven content negotiation.

It allows Ring handlers to select the most appropriate content to output based on the value of these headers in the incoming request:

  • Accept
  • Accept-Language
  • Accept-Charset
  • Accept-Encoding

It implements RFC 2616 sections 14.1–4, including wildcard and prefix matching rules, client-side q-values, and server-side source quality (qs) values.

Build Status

Installation

ring-middleware-accept is available in Clojars. Add it as a dependency in your Leiningen project's project.clj:

[ring-middleware-accept "2.0.3"]

or to your Maven project's pom.xml:

<dependency>
	<groupId>ring-middleware-accept</groupId>
	<artifactId>ring-middleware-accept</artifactId>
	<version>2.0.3</version>
</dependency>

Use

ring-middleware-accept exposes a single public function, wrap-accept, in the namespace ring.middleware.accept. This function takes two arguments: the handler to be wrapped, and a map of the content types offered by the handler.

For example:

(wrap-accept my-handler
	{:mime ["text/html" "text/plain"], :language ["en" "fr" "de"]})

Valid keys in the map are :mime (corresponding to the Accept header), :language, :charset, and :encoding. In the simplest case, as in the example above, the map values are just vectors of strings.

The wrapper augments the request-map which is passed to the handler with an :accept entry. Its value is a map of results, i.e. which of the offered content types the client should be served.

For example:

{:mime "text/html", :language "en"}

If the client cannot accept any of the offered types, some of the map entries will be nil. This may warrant a 406 Not Acceptable HTTP response.

Simple example

(ns example.web
	(:require [ring.middleware.accept :refer [wrap-accept]])
	;...
	)

(defroutes routes
	(GET "/greeting" {accept :accept}
		(case (:language accept)
			"en" "hello"
			"fr" "bonjour"
			"de" "hallo")))

(def app
	(-> routes
		(wrap-accept {:language ["en" "fr" "de"]})
		))

Aliases

Content types can be given aliases using the :as keyword.

{:language ["en-gb" :as :british, "en-us" :as :american]
 :mime     ["application/json" :as :json, "text/html" :as :html]}

These aliases will then used in the map of results:

{:language :british, :mime :html}

Source quality (qs) values

The :qs keyword can be used to assign quality values to the content types which the server is offering. These are the server-side equivalent of the q-values found in client requests.

This example shows a server expressing a preference for HTML over plain text in the ratio 2:1.

{:mime ["text/html" :qs 1, "text/plain" :qs 0.5]}

These values are used to determine which content type is chosen in the event of the client being able to accept more than one of those on offer. ring-middleware-accept follows the de facto standard of multiplying client q-values and server qs-values, and selecting the greatest product.

This means that in our example, a client which accepts text/plain,text/html will be served HTML, but a client which accepts text/plain;q=1,text/html;q=0.1 will be served plain text. This is because the text/plain product 1×0.5 is greater than the text/html product 0.1×1.

License

Copyright © 2014 rufoa

Distributed under the Eclipse Public License, the same as Clojure.

About

Content negotiation middleware for Ring

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published

Languages

  • Clojure 100.0%