### Generating URIs with bidi.vhosts/uri-info Source: https://github.com/juxt/bidi/blob/master/README.md This example shows how to use `bidi.vhosts/uri-info` to generate a map of URI components for a given route key and query parameters. It returns a detailed map including the full URI, path, host, scheme, and href, useful for constructing links or API responses. ```clojure (uri-info my-vhosts-model :index {:query-params {"q" "juxt"}}) ``` ```APIDOC {:uri "https://example.org:8443/index.html?q=juxt" :path "/index.html" :host "example.org:8443" :scheme :https :href "https://example.org:8443/index.html?q=juxt"} ``` -------------------------------- ### Using Wildcard Virtual Hosts in Bidi Source: https://github.com/juxt/bidi/blob/master/README.md This example illustrates the use of a wildcard `:*` as a virtual host declaration, allowing the associated routes to match any scheme or host. When `uri-info` is called, it will assume the scheme and host of the incoming request, providing flexibility for dynamic environments. ```clojure [:* ["/index.html" :index] ["/login" :login]] ``` -------------------------------- ### Defining a Single Virtual Host Structure in Bidi Source: https://github.com/juxt/bidi/blob/master/README.md This example illustrates the basic syntax for defining a virtual host structure in bidi. It shows how to associate a specific virtual host (e.g., a URL string) with a collection of routes, allowing for routing across different virtual host boundaries within the same server. ```clojure ["https://example.org:8443" ["/index.html" :index] ["/login" :login] ["/posts" […]] ``` -------------------------------- ### Clojure Bidi Defining Alternate Route Patterns Source: https://github.com/juxt/bidi/blob/master/README.md Demonstrates how to specify multiple potential candidate patterns for a single handler using a set. The first pattern in the set is considered canonical for URI formation. Examples include matching on different paths, HTTP methods, or server names. ```Clojure [#{"/index.html" "/index"} :index] ``` ```Clojure [#{:head :get} :index] ``` ```Clojure [#{{:server-name "juxt.pro"}{:server-name "localhost"}} {"/index.html" :index}] ``` -------------------------------- ### Defining Catch-All Routes for Error Handling in bidi Clojure Source: https://github.com/juxt/bidi/blob/master/README.md This example demonstrates how to create a catch-all route in bidi using the `true` pattern, which matches any path not previously matched. It illustrates how to define a fallback route for 404 Not Found errors, emphasizing the importance of route order when using vectors to ensure specific routes are matched before the catch-all. ```Clojure (def my-routes ["/" [["index.html" :index] [true :not-found]]]) ``` ```Clojure user> (match-route my-routes "/index.html") {:handler :index} user> (match-route my-routes "/other.html") {:handler :not-found} ``` -------------------------------- ### Wrapping bidi Routes as a Ring Handler in Clojure Source: https://github.com/juxt/bidi/blob/master/README.md This snippet demonstrates how to convert bidi routes into a standard Ring handler using `make-handler`. It defines example handlers and combines them into a single handler. The second part shows how to chain this handler with Ring middleware for session and flash management. ```Clojure (ns my.handler (:require [bidi.ring :refer (make-handler)] [ring.util.response :as res])) (defn index-handler [request] (res/response "Homepage")) (defn article-handler [{:keys [route-params]}] (res/response (str "You are viewing article: " (:id route-params)))) (def handler (make-handler ["/" {"index.html" index-handler ["articles/" :id "/article.html"] article-handler}])) ``` ```Clojure (ns my.app (:require [my.handler :refer [handler]] [ring.middleware.session :refer [wrap-session]] [ring.middleware.flash :refer [wrap-flash]])) (def app (-> handler wrap-session wrap-flash)) ``` -------------------------------- ### Implementing Custom Request Criteria Guards in bidi Clojure Routes Source: https://github.com/juxt/bidi/blob/master/README.md This example expands on bidi's guard functionality, showing how to restrict routes based on arbitrary request criteria using a map. It demonstrates matching a route only if the server name is 'juxt.pro' and the request method is 'post', allowing for fine-grained control over route dispatch based on virtual hosts or other HTTP properties. ```Clojure ["/" {"blog" {:get {"/index" (fn [req] {:status 200 :body "Index"})}} {:request-method :post :server-name "juxt.pro"} {"/zip" (fn [req] {:status 201 :body "Created"})}}] ``` -------------------------------- ### Using Regular Expressions for Path Matching in bidi Clojure Routes Source: https://github.com/juxt/bidi/blob/master/README.md This example illustrates how to use regular expressions within bidi routes to define more precise path segment capturing. It shows how to replace a simple keyword with a regex-keyword pair to ensure a path segment matches only numbers, preventing unwanted characters. ```Clojure [ [ "foo/" :id "/bar" ] :handler ] ``` ```Clojure [ [ "foo/" [ #"\\d+" :id ] "/bar" ] :handler ] ``` -------------------------------- ### Implementing Request Method Guards in bidi Clojure Routes Source: https://github.com/juxt/bidi/blob/master/README.md This snippet demonstrates how to restrict bidi routes based on the HTTP request method, similar to Compojure's method-specific routes. It shows how to wrap a route with a keyword representing the desired method (e.g., `:get`) to ensure the route only matches for that specific request type. ```Clojure ["/" {"blog" {:get {"/index" (fn [req] {:status 200 :body "Index"})}}}] ``` -------------------------------- ### Running Tests and Benchmarks for bidi Source: https://github.com/juxt/bidi/blob/master/README.md This snippet demonstrates how to execute tests for the bidi project using the `lein test` command. It includes performance benchmarks comparing route matching times for Compojure, uncompiled bidi, and compiled bidi routes, highlighting the performance benefits of bidi's compiled routes. ```Shell $ lein test lein test bidi.bidi-test lein test bidi.perf-test Time for 1000 matches using Compojure routes "Elapsed time: 17.645077 msecs" Time for 1000 matches using uncompiled bidi routes "Elapsed time: 66.449164 msecs" Time for 1000 matches using compiled bidi routes "Elapsed time: 21.269446 msecs" Ran 9 tests containing 47 assertions. 0 failures, 0 errors. ``` -------------------------------- ### Clojure Bidi Serving Files from File System Source: https://github.com/juxt/bidi/blob/master/README.md Shows how to use the `Files` record to serve static files directly from a specified file system directory, similar to how `Resources` serves from the classpath. ```Clojure ["pics/" (->Files {:dir "/tmp/pics"})] ``` -------------------------------- ### Clojure Bidi Serving Resources from Classpath Source: https://github.com/juxt/bidi/blob/master/README.md Illustrates the use of `Resources` and `ResourcesMaybe` records to serve static resources from the classpath. `ResourcesMaybe` returns nil if a resource is not found, allowing subsequent routes to be tried, unlike `Resources` which returns a 404. ```Clojure ["/resources" (->ResourcesMaybe {:prefix "public/"})] ``` -------------------------------- ### Creating a Multi-Virtual Host Model with bidi.vhosts/vhosts-model Source: https://github.com/juxt/bidi/blob/master/README.md This Clojure snippet demonstrates how to aggregate multiple virtual host structures into a single model using the `bidi.vhosts/vhosts-model` function. Each argument to the function is a virtual-host structure, enabling comprehensive routing across diverse virtual host configurations. ```clojure (require '[bidi.vhosts :refer [vhosts-model]]) (def my-vhosts-model (vhosts-model ["https://example.org:8443" ["/index.html" :index] ["/login" :login]] ["https://blog.example.org" ["/posts.html" […]]])) ``` -------------------------------- ### Define Routes Using bidi's Verbose Syntax Source: https://github.com/juxt/bidi/blob/master/README.md This snippet introduces bidi's verbose syntax, which provides a more readable way to define complex route structures using functions like `branch`, `param`, and `leaf`. This syntax compiles down to the standard terse route map format, offering an alternative for improved clarity. ```Clojure (require '[bidi.verbose :refer [branch param leaf]]) (branch "http://localhost:8080" (branch "/users/" (param :user-id) (branch "/topics" (leaf "" :topics) (leaf "/bulk" :topic-bulk))) (branch "/topics/" (param :topic) (leaf "" :private-topic)) (leaf "/schemas" :schemas) (branch "/orgs/" (param :org-id) (leaf "/topics" :org-topics))) ``` -------------------------------- ### Define Multiple Routes with a Map in Clojure Source: https://github.com/juxt/bidi/blob/master/README.md This snippet demonstrates defining multiple routes under a common prefix using a map. Each entry in the map associates a path segment with its corresponding handler keyword, allowing for a more organized and scalable route definition. ```Clojure user> (def my-routes ["/" {"index.html" :index "article.html" :article}]) ``` -------------------------------- ### Match a Simple Route in Clojure with bidi Source: https://github.com/juxt/bidi/blob/master/README.md This snippet demonstrates how to use `bidi.bidi/match-route` to test if a defined route matches a given path. When a match occurs, a map containing the `:handler` keyword is returned, which can then be used to dispatch to the appropriate handler. ```Clojure user> (use 'bidi.bidi) nil user> (match-route route "/index.html") {:handler :index} ``` -------------------------------- ### Clojure Bidi Tagging Routes for Path Generation Source: https://github.com/juxt/bidi/blob/master/README.md Illustrates the use of the `tag` function to associate a keyword tag with a handler. This allows `path-for` to generate URIs using the tag instead of a direct handler reference, simplifying route formation. ```Clojure (tag my-handler :my-tag) ``` ```Clojure ["/" [["foo" (-> foo-handler (tag :foo)] [["bar/" :id] (-> bar-handler (tag :bar)]]] (path-for my-routes :foo) (path-for my-routes :bar :id "123") ``` -------------------------------- ### Clojure Bidi Extracting All Routes with route-seq Source: https://github.com/juxt/bidi/blob/master/README.md Explains the `route-seq` function, which extracts all possible routes from a given route structure. This is useful for tasks like generating a site map, with each route represented as a map containing path and handler entries. ```Clojure (route-seq my-route-structure) ``` -------------------------------- ### Define a Simple Route in Clojure with bidi Source: https://github.com/juxt/bidi/blob/master/README.md This snippet defines a basic bidi route in Clojure. A route is represented as a vector containing a path pattern (e.g., "/index.html") and a handler keyword (e.g., :index). This route will be used for matching incoming requests. ```Clojure user> (def route ["/index.html" :index]) ``` -------------------------------- ### Clojure Bidi Route Redirection with Redirect Record Source: https://github.com/juxt/bidi/blob/master/README.md Demonstrates the `Redirect` record for robust URI redirection. It ensures the target URI matches an existing handler, reducing broken links and encouraging retention of old URIs. Requests to the old URI yield a 307 Temporary Redirect to the new URI. ```Clojure (defn my-handler [req] {:status 200 :body "Hello World!"}) ["/articles" {"/new" my-handler "/old" (->Redirect 307 my-handler)}] ``` -------------------------------- ### Match Multiple and Nested Routes in Clojure Source: https://github.com/juxt/bidi/blob/master/README.md This snippet demonstrates matching paths against the previously defined multiple and nested routes. It shows how `match-route` correctly identifies the handler for both top-level and deeply nested paths within the route structure. ```Clojure user> (match-route my-routes "/index.html") {:handler :index} user> (match-route my-routes "/articles/article.html") {:handler :article} ``` -------------------------------- ### Defining Synonymous Virtual Hosts in Bidi Source: https://github.com/juxt/bidi/blob/master/README.md This snippet demonstrates how to define a virtual host declaration as a vector, allowing a single set of routes to match multiple synonymous hosts. This is useful for scenarios where a resource might be accessible via different schemes or hostnames, with `uri-info` prioritizing the first matching host or scheme. ```clojure [["https://example.org:8443" "http://example.org:8000"] ["/index.html" :index] ["/login" :login]] ``` -------------------------------- ### Resulting Route Structure from bidi Verbose Syntax Source: https://github.com/juxt/bidi/blob/master/README.md This snippet shows the standard terse route map format that is generated when bidi's verbose syntax is compiled. It illustrates how the more readable `branch`/`param`/`leaf` structure translates into the underlying data structure used by bidi for route matching and generation. ```Clojure ["http://localhost:8080" [[["/users/" :user-id] [["/topics" [["" :topics] ["/bulk" :topic-bulk]]]]] [["/topics/" :topic] [["" :private-topic]]] ["/schemas" :schemas] [["/orgs/" :org-id] [["/topics" :org-topics]]]]] ``` -------------------------------- ### Bidi Route Structure BNF Grammar Source: https://github.com/juxt/bidi/blob/master/README.md This section formally defines the basic route structure in bidi using Backus–Naur Form (BNF). It details the components of a route pair, including various pattern types, method guards, general guards, and matched results, providing a foundational understanding of bidi's routing syntax. ```APIDOC RouteStructure := RoutePair RoutePair ::= [ Pattern Matched ] Pattern ::= Path | [ PatternSegment+ ] | MethodGuard | GeneralGuard | true | false MethodGuard ::= :get :post :put :delete :head :options GeneralGuard ::= [ GuardKey GuardValue ]* (a map) GuardKey ::= Keyword GuardValue ::= Value | Set | Function Path ::= String PatternSegment ::= String | Regex | Keyword | [ (String | Regex) Keyword ] Matched ::= Function | Symbol | Keyword | [ RoutePair+ ] { RoutePair+ } ``` -------------------------------- ### Generate Path with Parameters in Clojure with bidi Source: https://github.com/juxt/bidi/blob/master/README.md This snippet demonstrates how to use `path-for` to generate URIs for routes that include path parameters. The required parameter values are passed as additional arguments to the function, ensuring the correct URI is constructed dynamically. ```Clojure user> (path-for my-routes :article :id 123) "/articles/123/article.html" user> (path-for my-routes :article :id 999) "/articles/999/article.html" ``` -------------------------------- ### Generate Path for a Simple Route in Clojure with bidi Source: https://github.com/juxt/bidi/blob/master/README.md This snippet shows how to use `bidi.bidi/path-for` to generate a URI from a handler keyword and a route definition. This function is useful for creating dynamic links in views, ensuring consistency and resilience to route changes. ```Clojure user> (path-for route :index) "/index.html" ``` -------------------------------- ### Handle No Route Match in Clojure with bidi Source: https://github.com/juxt/bidi/blob/master/README.md This snippet illustrates the behavior of `bidi.bidi/match-route` when no route matches the provided path. In such cases, the function returns `nil`, indicating that no handler could be found for the given URI. ```Clojure user> (match-route route "/another.html") nil ``` -------------------------------- ### Clojure Bidi Wrapping Handlers with Middleware Source: https://github.com/juxt/bidi/blob/master/README.md Explains `WrapMiddleware` for applying Ring middleware to specific handlers within a route definition. This feature should be used with caution, as Ring middleware is generally applied to handlers, not routes, and alternative approaches are often preferred. ```Clojure (match-route ["/index.html" (->WrapMiddleware handler wrap-params)] "/index.html") ``` -------------------------------- ### Extracting and Encoding Keywords in bidi Clojure Routes Source: https://github.com/juxt/bidi/blob/master/README.md This snippet shows how to configure bidi to extract URI segments as Clojure keywords and, conversely, how to encode keywords into URIs. It uses the `keyword` core function in the route pattern to achieve this, supporting both simple and namespaced keywords, with proper URL encoding for namespaces. ```Clojure [ "foo/" [ keyword :db/ident ] "/bar" ] ``` -------------------------------- ### Validating Bidi Route Structures with Schema Source: https://github.com/juxt/bidi/blob/master/README.md This Clojure snippet demonstrates how to use the `Prismatic/schema` library to validate bidi route structures. It shows how to check a route against the `bidi.schema/RoutePair` schema, returning `nil` for valid routes or an error value for invalid ones, and how to throw an exception for invalid structures. ```clojure (require '[schema.core :as s] bidi.schema) (def route ["/index.html" :index]) ;; Check that the route is properly structured - returns nil if valid; ;; otherwise, returns a value with 'bad' parts of the route. (s/check bidi.schema/RoutePair route) ;; Throw an exception if the route is badly structured (s/validate bidi.schema/RoutePair route) ``` -------------------------------- ### Match Routes and Extract Path Parameters in Clojure Source: https://github.com/juxt/bidi/blob/master/README.md This snippet shows how `match-route` extracts values from URI segments defined as parameters in the route pattern. The extracted values are returned in the result map under the `:route-params` key, making them accessible for handler logic. ```Clojure user> (match-route my-routes "/articles/123/article.html") {:handler :article, :route-params {:id "123"}} user> (match-route my-routes "/articles/999/article.html") {:handler :article, :route-params {:id "999"}} ``` -------------------------------- ### Define Routes with Path Parameters in Clojure Source: https://github.com/juxt/bidi/blob/master/README.md This snippet demonstrates defining routes that extract parameters from the URI using a vector pattern like `[:id "/article.html"]`. The `:id` keyword acts as a placeholder for a variable segment in the path, which will be captured during matching. ```Clojure user> (def my-routes ["/" {"index.html" :index "articles/" {"index.html" :article-index [:id "/article.html"] :article}}]) ``` -------------------------------- ### Define Nested Routes in Clojure with bidi Source: https://github.com/juxt/bidi/blob/master/README.md This snippet illustrates how bidi supports nested route definitions, where a path segment can lead to another map of routes. This hierarchical structure helps organize complex routing schemes, especially for applications with deep URL structures. ```Clojure user> (def my-routes ["/" {"index.html" :index "articles/" {"index.html" :article-index "article.html" :article}}]) ``` -------------------------------- ### Generate Path for Nested Routes in Clojure Source: https://github.com/juxt/bidi/blob/master/README.md This snippet shows how `path-for` can be used to generate URIs for handlers defined within nested route structures. It correctly constructs the full path by traversing the route map based on the provided handler keyword. ```Clojure user> (path-for my-routes :article-index) "/articles/index.html" ``` -------------------------------- ### Clojure Handler Map Promise for Circular Dependencies Source: https://github.com/juxt/bidi/blob/master/doc/patterns.md This Clojure code demonstrates the 'Handler map promise' pattern to resolve circular dependencies between REST resources, specifically using Liberator. It shows how two resources, `contacts` and `contact`, can form hyperlinks to each other using `path-for` by accessing a shared `handlers` promise. The `make-handlers` function ensures the promise is delivered with a map of handlers before it can be dereferenced, preventing escape of the handler construction phase. Routes are assumed to be available under the `:routes` key in the request. ```Clojure (defresource contacts [database handlers] :allowed-methods #{:post} :post! (fn [{{body :body} :request}] {:id (create-contact! database body)}) :handle-created (fn [{{routes :routes} :request id :id}] (assert (realized? handlers)) (ring-response {:headers {"Location" (path-for routes (:contact @handlers) :id id)}}))) (defresource contact [handlers] :allowed-methods #{:delete :put} :available-media-types #{"application/json"} :handle-ok (fn [{{{id :id} :route-params routes :routes} :request}] (assert (realized? handlers)) (html [:div [:h2 "Contact: " id] [:a {:href (path-for routes (:contacts @handlers))} "Index"]]))) (defn make-handlers [database] (let [p (promise)] ;; Deliver the promise so it doesn't escape this function. @(deliver p {:contacts (contacts database p) :contact (contact p)}))) (defn make-routes [handlers] ["/" [["contacts" (:contacts handlers)] [["contact/" :id] (:contact handlers)] ]]) ;; Create the route structure like this :- (-> database make-handlers make-routes) ``` === COMPLETE CONTENT === This response contains all available snippets from this library. No additional content exists. Do not make further requests.