-
-
Notifications
You must be signed in to change notification settings - Fork 10
routes
In order to stub HTTP endpoints you must conform to the route schema. Here's an example:
{ "/something" {:status 200 :body "hello"}
"/something-else" {:status 201 } }
The key in this map is the request specification and the value is the response specification. The combination of key and value (i.e. request- and response specification) is called a route. You supply this route map to the with-routes! macro or the start!
function. For example:
(with-routes!
{ "/something" {:status 200 :body "hello"}
"/something-else" {:status 201 } }
(client/get ...))
As an alternative to explicitly declaring the route map (that consists of one to many routes) you can provide it from a function that takes a server
instance as a parameter. This is useful if you need access to some data from the server
in order to build up your routes. For example:
(fn [server]
(let [absolute-uri (str (:uri server) "/somewhere")]
{ "/somewhere" {:status 200 :body absolute-uri}}))
In this example we get the URI of the server (which may be autogenerated if using the macro for later use in our response specification. For example:
(with-routes!
(fn [server]
(let [absolute-uri (str (:uri server) "/somewhere")]
{ "/somewhere" {:status 200 :body absolute-uri}}))
(client/get ...))
The server
schema is defined like this:
{:uri :port :nano-server :routes {:request-spec-fn <function that takes a request (map) that returns true/false whether this spec matches the request> :request-spec :response-spec-fn <function that takes a request (map) and return the response-spec> :response-spec :recordings }}
For more information on recordings refer to this wiki page.
The request specification (the key in the route map) can be created in three different ways:
-
Path only
This allows you to match a path in the request. For example:
{ "/something" { ... } }
This will match requests (regardless of http method) whose path is equal to "/something". For example it'll match the URI
http://localhost:8083/something
but nothttp://localhost:8083/something2
. -
Map
If path is not enough it's possible to define the request specification using a map. The schema is defined as this:
{:path <string> :method <any of :get :post :put :delete etc> :query-params { :query-param-name <value> }}
For example:
{{:path "/x" :method :get :query-params { :q "query" }} {...} }
This will match a
GET
request with path equal to/x
that has a query parameterq=query
. For examplehttp://localhost:8083/x?q=query
. More routing options might be available in the future. -
Function
This is the most advanced option and allows you to determine a match based on the actual request by providing a function that returns true or false on match:
(fn [request] <true or false>)
The request schema looks like this:
{:method <keyword of http method, for example :get :post etc> :headers <map> :content-type <the content-type header> :path <the uri path> :request-line <the request line (currently HTTP/1.1 is always added) :body <the request body> :query-params <map>
For example:
{ (fn [request] (clojure.string/starts-with? (:path request) "/my-resource")) { ... }}
The response specification (the value in the route map) can be created in two different ways:
-
Map
The response can be generated from a response specification defined as a map. The schema is defined as this:
{:status <the status code as Int> :headers <map of name-value pairs> :content-type <shortcut for setting the "content-type" header> :body <The body as string>
For example:
{{...} {:status 200 :content-type "text/plain" :body "Hello world"} }
The response generated from this specification should be self explanatory.
-
Function
This allows you generate a response based on the request as outlined in section 3 here by providing a function:
(fn [request] <response specification>)
For example:
{{...} (fn [request] {:status 200 :content-type "text/plain" :body "Hello " (->> request :headers :name)}) }
Given that the name header is defined as
NAME: John
this will generated a response with body "Hello John"