diff options
| author | Asko Nõmm <asko@bien.ee> | 2021-10-02 19:58:15 -0300 |
|---|---|---|
| committer | Asko Nõmm <asko@bien.ee> | 2021-10-02 19:58:15 -0300 |
| commit | a4d6e488859f14db1547975b011cc3559e5c47ef (patch) | |
| tree | 30d6c427be1a82d268700a3e11a099da6ada014d | |
| parent | b020883897f50c35af3a8774a911fe7c69631bce (diff) | |
Make Ruuter HTTP server agnostic
| -rw-r--r-- | README.md | 70 | ||||
| -rw-r--r-- | project.clj | 5 | ||||
| -rw-r--r-- | src/ruuter/core.clj | 25 |
3 files changed, 66 insertions, 34 deletions
@@ -10,30 +10,51 @@ A tiny HTTP router that operates with a simple data structure where each route i ### Setting up -Require the namespace `ruuter.core` and then pass your routes to the `route!` function, like this: +Require the namespace `ruuter.core` and then pass your routes to the `route` function along with the current request map, like this: ```clojure (ns myapp.core (:require [ruuter.core :as ruuter])) -(defn -main [& opts] - (ruuter/route! [{:path "/" - :method :get - :response {:status 200 - :body "Hi there!"}}])) +(def routes [{:path "/" + :method :get + :response {:status 200 + :body "Hi there!"}}]) + +(def request {:uri "/" + :request-method :get}) + +(ruuter/route routes request) ; => {:status 200 + ; :body "Hi there!"} ``` -This will start an HTTP server on a default port of 9600 using [http-kit](https://github.com/http-kit/http-kit) under the hood. +This will attempt to match a route with the request map and return the matched route' response. If no route was found, it will attempt to find a route that has a `:path` that is `:not-found`, and return its response instead. But if not even that route was found, it will simply return a built-in 404 response instead. -The `route!` function also takes a second, optional argument, which is the [options map for http-kit](http://http-kit.github.io/http-kit/org.httpkit.server.html#var-run-server), allowing you to specify the port and so on, like this: +Note that the `request-method` doesn't have to be a keyword, it can be anything that your HTTP server returns. But it does have to be called `request-method` for the router to know where to look for. + +### Setting up with http-kit + +Now, obviously on its own the router is not very useful as it needs an actual HTTP server to, so here's an example that uses http-kit: ```clojure +(ns myapp.core + (:require [ruuter.core :as ruuter] + [org.httpkit.server :as http])) + +; The given request map (second argument) will match the +; first route in this example, and return its response. (def routes [{:path "/" :method :get :response {:status 200 - :body "Hi there!"}}]) + :body "Hi there!"}} + {:path "/hello/:who" + :method :get + :response (fn [req] + {:status 200 + :body (str "Hello, " (:who (:params req)))})}]) -(ruuter/route! routes {:port 8080}) +(defn -main [] + (http/run-server #(ruuter/route routes %) {:port 8080})) ``` ### Creating routes @@ -57,9 +78,7 @@ To create parameters from the path, prepend a colon (:) in front of a path slice #### `:method` -The HTTP method to listen for when matching the given path. - -Accepted values are: +The HTTP method to listen for when matching the given path. This can be whatever the HTTP server uses. For example, if you're using http-kit for the HTTP server then the accepted values are: - `:get` - `:post` @@ -71,4 +90,27 @@ Accepted values are: #### `:response` -The response can be a direct map, or a function returning a map. In case of a function, you will also get passed to you the `request` object. For better information on what are all the things you could do with a response, check out [the http-kit documentation](https://http-kit.github.io/server.html). +The response can be a direct map, or a function returning a map. In case of a function, you will also get passed to you the `request` map that the HTTP server returns, with added-in `:params` that contain the values for the URL parameters you use in your route's `:path`. + +Thus, a `:response` can be a map: + +```clojure +{:status 200 + :body "Hi there!"} + ``` + +Or a function returning a map: + +```clojure +(fn [req] + {:status 200 + :body "Hi there!"}) + ``` + +What the actual map can contain that you return depends again on the HTTP server you decided to use Ruuter with. The examples I've noted here are based on `http-kit`, but feel free to make a PR with additions for other HTTP servers. + +## Changelog + +### 1.1.0 + +- Made Ruuter server-agnostic, which means now it really is just a router and nothing else, and can thus be used with just about any HTTP server you can throw at it. It also means there are now zero dependencies! ZERO!
\ No newline at end of file diff --git a/project.clj b/project.clj index 033b323..21498d6 100644 --- a/project.clj +++ b/project.clj @@ -1,10 +1,9 @@ -(defproject org.clojars.askonomm/ruuter "1.0.1" +(defproject org.clojars.askonomm/ruuter "1.1.0" :description "A tiny HTTP router" :url "https://github.com/askonomm/ruuter" :license {:name "MIT" :url "https://raw.githubusercontent.com/askonomm/ruuter/master/LICENSE.txt"} - :dependencies [[org.clojure/clojure "1.10.3"] - [http-kit "2.5.3"]] + :dependencies [[org.clojure/clojure "1.10.3"]] :plugins [[lein-cloverage "1.2.2"]] :main ruuter.core :min-lein-version "2.0.0" diff --git a/src/ruuter/core.clj b/src/ruuter/core.clj index b441b1f..f811802 100644 --- a/src/ruuter/core.clj +++ b/src/ruuter/core.clj @@ -1,6 +1,5 @@ (ns ruuter.core - (:require [clojure.string :as string] - [org.httpkit.server :as http]) + (:require [clojure.string :as string]) (:gen-class)) @@ -75,29 +74,21 @@ :body "Not found."})) -(defn- router +(defn route "For a given collection of `routes` and the current HTTP request as `req`, will attempt to match a route with the HTTP request, which it - will then try to return a response for. + will then try to return a response for. The only requirement for `req` + is to contain both a `uri` and `request-method` key. First should match + the request path (like the paths defined in routes) and the second + should match the request method used by the HTTP server you pass this fn to. If no route matched for a given HTTP request it will try to find a route with `:not-found` as its `:path` instead, and return the response - for that." + for that, and if that route was also not found, will return a built-in + 404 response instead." [routes {:keys [uri request-method] :as req}] (if-let [route (match-route routes uri request-method)] (route+req->response route req) (route+req->response (->> routes (filter #(= :not-found (:path %))) first) req))) - - -(defn route! - "Starts an HTTP server which will then try to find a matching route for - each request from within the given collection of `routes`. Takes an - optional `opts` map, which corresponds directly to http-kit's config, - allowing you to specify things like `{:port 8080}` and so on." - ([routes] - (route! routes {:port 9600})) - ([routes opts] - (println "Starting HTTP server on port " (:port opts)) - (http/run-server #(router routes %) opts)))
\ No newline at end of file |
