Fork me on GitHub
#pedestal
<
2023-01-10
>
CarnunMP23:01:12

Hey all. Been stumped with this for a little while now... I have some routes which look like:

(def routes
  (route/expand-routes
    #{["/" :get [interceptors/redirect-home]]
      ["/:page-uid/:slug" :get [interceptors/get-pages]]
      ["/email-sub" :put [interceptors/upsert-sub]]}))
Any idea why the "/email-sub" route won't match/why I keep getting 404s? :thinking_face: Fwiw I have ::http/resource-path set on the service map, the interceptors all have :names, the other routes work just fine, and I'm using the http/default-interceptors. And another thing: upsert-sub's :enter never fires. The request never gets that far.

Joe R. Smith23:01:52

/email-sub doesn't match anything (unless you meant the last one to be /:c)

Joe R. Smith00:01:15

A PUT to /c doesn't invoke bar?

CarnunMP00:01:45

Sorry, was meant to be /c! Edited now. 🙂

CarnunMP00:01:53

And no, it doesn't.

Joe R. Smith00:01:51

hmm, doesn't match anything else

CarnunMP00:01:07

right? 😅

Joe R. Smith00:01:04

does it work w/ any other http verb? e.g., if you change it to :get ?

CarnunMP00:01:57

nope, same issue

Joe R. Smith00:01:05

so, really, you're saying a single component route with any http verb and any interceptor with an :enter never calls the enter fn?

Joe R. Smith00:01:44

the routes are a set, so order ostensibly doesn't matter

CarnunMP00:01:48

in the above case? yeah seems like it!

Joe R. Smith00:01:52

what's the output of expand-routes?

CarnunMP00:01:25

no reason to be coy about real names on reflection, ha...

({:path "/:page-uid/:slug",
  :method :get,
  :path-constraints {:page-uid "([^/]+)", :slug "([^/]+)"},
  :path-re #"/([^/]+)/([^/]+)",
  :path-parts [:page-uid :slug],
  :interceptors [#io.pedestal.interceptor.Interceptor{:name :get-pages,
                                                      :enter #object[carnun.com.server.interceptors$fn__44626 "0x32682328" "carnun.com.server.interceptors$fn__44626@32682328"],
                                                      :leave nil,
                                                      :error nil,
                                                      :carnun/doc "If the `single` query param is present, returns 'raw' page html for the URL's primary page. Otherwise,\n               returns html for all of the pages (primary + `pages`) wrapped in boilerplate — i.e. the full site."}],
  :route-name :get-pages,
  :path-params [:page-uid :slug]}
 {:path "/email-sub",
  :method :put,
  :path-re #"/\Qemail-sub\E",
  :path-parts ["email-sub"],
  :interceptors [#io.pedestal.interceptor.Interceptor{:name :upsert-sub, :enter #object[carnun.com.server.interceptors$fn__44629 "0x6f35f49" "carnun.com.server.interceptors$fn__44629@6f35f49"], :leave nil, :error nil}],
  :route-name :upsert-sub,
  :path-params []}
 {:path "/",
  :method :get,
  :path-re #"/\Q\E",
  :path-parts [""],
  :interceptors [#io.pedestal.interceptor.Interceptor{:name :redirect-home, :enter #object[carnun.com.server.interceptors$fn__44624 "0x106aac72" "carnun.com.server.interceptors$fn__44624@106aac72"], :leave nil, :error nil}],
  :route-name :redirect-home,
  :path-params []})

Joe R. Smith00:01:34

this one, I'm guessing:

{:path "/email-sub",
  :method :put,
  :path-re #"/\Qemail-sub\E",
  :path-parts ["email-sub"],
  :interceptors [#io.pedestal.interceptor.Interceptor{:name :upsert-sub, :enter #object[carnun.com.server.interceptors$fn__44629 "0x6f35f49" "carnun.com.server.interceptors$fn__44629@6f35f49"], :leave nil, :error nil}],
  :route-name :upsert-sub,
  :path-params []}

CarnunMP00:01:47

this weirdness holds with the redirect-home route omitted too, fwiw

CarnunMP00:01:54

and yes, that's the one

Joe R. Smith00:01:14

just ... bizarre

Joe R. Smith00:01:53

looking at a pedestal service of my own, I see no difference for a single component route

Joe R. Smith00:01:45

anything special about :upsert-sub ?

CarnunMP00:01:56

> just ... bizarre you can say that again

CarnunMP00:01:39

certainly not right now!

(def upsert-sub
  {:name :upsert-sub
   :enter (fn [ctx]
            (let [db (xt/db (get-in ctx path/xtdb-node))]
              (prn "foo")
              (def ctx ctx)
              #_(email/upsert-sub)
              ;; save contact to db
              ;; send confirmation email
              (assoc ctx :response {:status 200
                                    :body "yo"
                                    :headers {"Content-Type" "text/plain"}})))})

CarnunMP00:01:43

The idea that :enter here never fires is based on never seeing the prn output and ctx remaining unbound, fwiw.

Joe R. Smith00:01:15

seems pretty solid

Joe R. Smith00:01:32

don't names have to be ns-qualified?

Joe R. Smith00:01:40

e.g. ::upsert-sub

CarnunMP00:01:26

hmm, that isn't an issue with the other routes/interceptors

CarnunMP00:01:41

but idk, you might be right!

Joe R. Smith00:01:56

I've never not qualified them, so I'm just going off of experience. Probably not an issue

Joe R. Smith00:01:10

:name should be optional

CarnunMP00:01:32

iirc they just have to be unique, which qualification increases the chances of 😛

Joe R. Smith00:01:42

possible you're throwing an exception from your xt/db call and then swallowing that exception?

Joe R. Smith00:01:02

can you move your prn and def to before the let ?

Joe R. Smith00:01:22

I'm ... out of ideas. 😄

❤️ 2
CarnunMP00:01:23

well... it was worth a shot

CarnunMP00:01:25

really appreciate the help regardless man 😄

👍 2
Joe R. Smith00:01:25

please tell me what it was when you figure it out so I can share in the facepalming for whatever simple thing we both missed

CarnunMP00:01:44

oh, goes without saying

CarnunMP00:01:20

(I'm heading to bed now, 🤞 I dream the solution...)

2
CarnunMP21:01:52

Thanks for the suggestion @U2J4FRT2T! But I'm not sure where they'd come in here (given the below)... Do you have an idea? 🙂

CarnunMP21:01:29

*(given the below, and that I'm not landing on any other routes either 😕 )

CarnunMP21:01:50

Huh! It seems things work just fine when I prefix both routes, e.g. with /blog/ and /api/ like so:

(def routes
  (route/expand-routes
    #{["/" :get [interceptors/redirect-home]]
      ["/blog/:page-uid/:slug" :get [interceptors/get-pages]]
      ["/api/email-sub" :put [interceptors/upsert-sub]]}))
But why? :thinking_face:

2
ajones18:01:37

from recommendations I was given years back around wild card routes and path params in pedestal it makes a lot of sense that it was having those problems (though been a while since I’ve read through the routers). where the /:page-uid/:slug is probably conflicting with the /email-sub route with them being at the same level, and the path param parsing of /:page-uid/:slug would interfere with the identification of the email-sub route. doing what you did and grouping the route for /:page-uid/:slug under some prefix, is the same recommendation I’d be giving people at work. the prefix for just the /blog/:page-uid/:slug route should be the only one needed. ran a few tests with a dummy pedestal-service template and things check out so far. looks like I’m more than a bit late to the convo (maybe you’ve already found the answer 🤷), though hopefully this helps someone in the future.

❤️ 2
CarnunMP15:02:47

@UE4SAM0A0 I went with the prefixing, yep! 🙂

💯 2
Joe R. Smith05:02:58

I didn’t think of it at the time we last chatted, but there are also multiple routers with different routing semantics, see the table in this section of the docs: http://pedestal.io/reference/routing-quick-reference#_routers

👍 2
🙏 2