Fork me on GitHub
#pedestal
<
2024-03-17
>
steffan18:03:45

The documentation for http://pedestal.io/pedestal/0.6/reference/table-syntax.html/http://pedestal.io/pedestal/0.6/reference/terse-syntax.html routing syntax states that "The "handler position" be anything that satisfies the IntoInterceptor protocol" but I don't believe that is true. The documentation suggests a "function value" is acceptable, which IntoInterceptor treats as the handler case. However, using a function value in table/terse routes fails:

(ns org.example
  (:require [io.pedestal.http :as http]))

(defn greeting
  [_request]
  {:status 200
   :body   "Hello!"})

(defn start-with-routes
  [routes]
  (-> {::http/routes routes
       ::http/type   :jetty
       ::http/port   8080
       ::http/join?  false}
      http/create-server
      http/start))

(comment

  ;; Terse syntax - Works OK
  (start-with-routes [[["/greeting" {:get `greeting}]]])

  ;; Terse syntax - Fails with this error
  ;; Execution error (IllegalArgumentException) at
  ;; io.pedestal.http.route.definition.terse/eval12858$fn$G (terse.clj:54).
  ;; No implementation of method: :expand-verb-action of protocol:
  ;; #'io.pedestal.http.route.definition.terse/ExpandableVerbAction
  ;; found for class: org.example$greeting
  (start-with-routes [[["/greeting" {:get greeting}]]])

  ;; Table syntax - Works OK
  (start-with-routes #{["/greeting" :get `greeting]})

  ;; Table syntax - Fails with this error
  ;; Execution error (AssertionError) at
  ;; io.pedestal.http.route.definition.table/parse-route-name (table.clj:94).
  ;; Assert failed: In row 1, the last interceptor does not have a name and
  ;; there is no explicit :route-name.
  ;; The whole route was:
  ;; ["/greeting" :get #object[org.example$greeting 0x54b896a1 "org.example$greeting@54b896a1"]]
  ;; default-route-name
  (start-with-routes #{["/greeting" :get greeting]})

  ;
  )
The above is run with Pedestal 0.6.3. Am I misunderstanding something or is this a bug?

hlship21:03:26

I think it is just poorly documented; I’ve been addressing this in 0.7.x with a) proper specs (for that unambiguous descriptions) and b) better hand-written docs. Also, don’t use terse, use table syntax! Note that last error in the table syntax; the new docs address that better though I think somewhere in the 0.6 docs it does address that a function doesn’t provide enough information for Pedestal to assign a route name, but a Var or Symbol does.

hlship21:03:55

That’s generally the case, if you provide a function (not a Symbol or Var from which a function or interceptor can be acquired) then you are on the hook for providing a unique route name.

steffan12:03:05

Thanks, I look forward to the improvements 😄 To expand on your last point, adding a route name clause to the last example makes it work OK:

(start-with-routes #{["/greeting" :get greeting :route-name ::get-greeting]})