Fork me on GitHub
#pedestal
<
2017-02-28
>
rui.yang12:02:07

hi, wonder if there is some examples of simulating multi-part form submission in testing pedestal application? eg. for testing file uploading. using pedestal's response-for macro.

kirill.salykin12:02:44

Hi, is it possible to use function to build routes? I am trying this:

::http/routes (build-routes)

(defn build-routes
  (route/expand-routes #{[…]})) 
But facing this:
You're trying to use something as an interceptor
that isn't supported by the protocol; Perhaps you need to extend it? {:t nil, :type nil}

kirill.salykin13:02:29

Is it good approach to build routes this way?

(def route-table
  #{["/"        :get  ['pages/root]]
    ["/sign-up" :get  ['pages/show-sign-up]]
    ["/sign-up" :post ['pages/sign-up]]
    ["/sign-in" :get  ['pages/show-sign-in]]
    ["/sign-in" :post ['pages/sign-in]]})


(def common-interceptors
  [http/html-body
   (using-component :db)
   (session {:store (cookie/cookie-store {:key "some-key12345678"})})])

(defn build-interceptors [verb interceptors]
  (let [interceptors (apply conj common-interceptors interceptors)]
    (if (= verb :get)
      interceptors
      (into [(body-params) keyword-params] interceptors))))

(defn browser-stack [[path verb interceptors]]
  [path verb (build-interceptors verb interceptors)])

(def routes
  (route/expand-routes (into #{} (map browser-stack route-table))))

ddeaguiar13:02:10

@kirill.salykin there's nothing wrong with building your routes programmatically, although given your example, I'd build the route-table explicitly. IMO it would be easier to reason about

ddeaguiar13:02:26

@kirill.salykin re: the error you're seeing, it may be due to how you refer to your handlers in the route table. Try using back-ticks instead of single quotes

ddeaguiar13:02:45

the symbols need to be fully qualified

kirill.salykin13:02:47

@ddeaguiar thanks for response Thought it makes no sens to repeat (body-params) etc

kirill.salykin13:02:29

I see this error only when I am trying to implemet routes as function defn routes []

ddeaguiar13:02:36

you can capture the common get interceptors in a var if you like

ddeaguiar13:02:09

but that's a matter of taste

ddeaguiar13:02:43

again, nothing wrong with programmatically building the routes

ddeaguiar14:02:59

@kirill.salykin also, you don't need to call route/expand-routes

kirill.salykin14:02:31

pedestal will do it for me because set used?

ddeaguiar14:02:15

so I suspect what's happening is that the verbose route map produced by expand routes is trying to be expanded again by Pedestal's internals

mtnygard14:02:37

@kirill.salykin The message you're getting includes the value and type that Pedestal is trying to convert to an interceptor. The value is nil, so I suspect that your interceptor vector after browser-stack may have some issues. Can you print the value of the set after (into #{} (map browser-stack route-table))?

kirill.salykin14:02:03

@mtnygard everything works I am facing issue if I am trying to use this:

(def routes
  (route/expand-routes (into #{} (map browser-stack route-table))))
as function, eg :
(defn routes []
  (route/expand-routes (into #{} (map browser-stack route-table))))

mtnygard14:02:37

Gotcha. Can you show me your service-map declaration?

kirill.salykin14:02:11

(defn build-routes []
  (fn []
    (doseq [ns-sym (modified-namespaces)]
      (require ns-sym :reload))
    routes))

(def pedestal-config
  {::http/host "0.0.0.0"
   ::http/port 8080
   ::http/type :jetty
   ::http/join? true
   ::http/resource-path "/public"
   ::http/routes (build-routes)})

kirill.salykin14:02:20

routes defined above

mtnygard14:02:15

OK, so you're using build-routes to do auto refresh. When you use (defn routes ...), did you change the last expression in build-routes to be a call to the routes function?

kirill.salykin14:02:38

yes I used this version

(defn build-routes []
  (fn []
    (doseq [ns-sym (modified-namespaces)]
      (require ns-sym :reload))
    (routes)))

mtnygard14:02:09

It never hurts to check to obvious stuff. 🙂

mtnygard14:02:17

Can you paste in the output of (build-routes) ?

kirill.salykin14:02:27

give me couple minutes

kirill.salykin14:02:13

#object[blog$build_routes$fn__16210 0x4aa430d9 "blog$build_routes$fn__16210@4aa430d9"]

mtnygard14:02:07

Well that's not terribly helpful...

mtnygard14:02:29

How about the output of ((build-routes))?

kirill.salykin14:02:50

clojure.lang.ExceptionInfo: You're trying to use something as an interceptor that isn't supported by the protocol; Perhaps you need to extend it?

mtnygard14:02:44

So then the problem is definitely with the data structure being passed to expand-routes. Can you show me the output of (into #{} (map browser-stack route-table))

kirill.salykin14:02:49

all route related declared in blog.web.routes when I calling (route) being in blog.web.routes this is returned:

({:path "/sign-in", :method :get, :path-re #"/\Qsign-in\E", :path-parts ["sign-in"], :interceptors [#Interceptor{:name :io.pedestal.http/html-body} #Interceptor{:name :io.pedestal.http.ring-middlewares/session} #Interceptor{:name :blog.system.pedestal/using-component} #Interceptor{:name :io.pedestal.http.params/keyword-params} #Interceptor{:name }], :route-name :blog.web.pages/show-sign-in, :path-params []} {:path "/sign-in", :method :post, :path-re #"/\Qsign-in\E", :path-parts ["sign-in"], :interceptors [#Interceptor{:name :io.pedestal.http.body-params/body-params} #Interceptor{:name :io.pedestal.http/html-body} #Interceptor{:name :io.pedestal.http.ring-middlewares/session} #Interceptor{:name :blog.system.pedestal/using-component} #Interceptor{:name :io.pedestal.http.params/keyword-params} #Interceptor{:name }], :route-name :blog.web.pages/sign-in, :path-params []} {:path "/sign-up", :method :post, :path-re #"/\Qsign-up\E", :path-parts ["sign-up"], :interceptors [#Interceptor{:name :io.pedestal.http.body-params/body-params} #Interceptor{:name :io.pedestal.http/html-body} #Interceptor{:name :io.pedestal.http.ring-middlewares/session} #Interceptor{:name :blog.system.pedestal/using-component} #Interceptor{:name :io.pedestal.http.params/keyword-params} #Interceptor{:name }], :route-name :blog.web.pages/sign-up, :path-params []} {:path "/sign-up", :method :get, :path-re #"/\Qsign-up\E", :path-parts ["sign-up"], :interceptors [#Interceptor{:name :io.pedestal.http/html-body} #Interceptor{:name :io.pedestal.http.ring-middlewares/session} #Interceptor{:name :blog.system.pedestal/using-component} #Interceptor{:name :io.pedestal.http.params/keyword-params} #Interceptor{:name }], :route-name :blog.web.pages/show-sign-up, :path-params []} {:path "/", :method :get, :path-re #"/\Q\E", :path-parts [""], :interceptors [#Interceptor{:name :io.pedestal.http/html-body} #Interceptor{:name :io.pedestal.http.ring-middlewares/session} #Interceptor{:name :blog.system.pedestal/using-component} #Interceptor{:name :io.pedestal.http.params/keyword-params} #Interceptor{:name }], :route-name :blog.web.pages/root, :path-params []})

kirill.salykin14:02:50

but, when invoking ((build-routes) being in blog namespace having this declaration [blog.web.routes :refer [routes] everything breaks

kirill.salykin14:02:57

can it be some name overlap?

mtnygard14:02:25

Maybe ... I'd need to see more of the code to know if that's the case.

mtnygard14:02:31

There is something odd about those routes though.

kirill.salykin14:02:40

I’ll push it to github a bit later

mtnygard14:02:49

The last interceptor in each vector just says #Interceptor {:name}.

mtnygard14:02:06

In your original table, were you using symbols or syntax-quoted names?

mtnygard14:02:47

With backticks?

kirill.salykin14:02:08

let me recheck, i have a feeling that i’ve used just ‘ symbol

kirill.salykin14:02:23

everything works

mtnygard14:02:26

A backtick would make Pedestal pick up the interceptor name from the var name.

mtnygard14:02:31

Oh, that fixed it?

kirill.salykin14:02:36

I am so sorry for this stupid error 😞

mtnygard14:02:57

Kudos to @ddeaguiar. He spotted that a while ago.

kirill.salykin14:02:25

but last-interceptor still has empty name

kirill.salykin14:02:40

((build-routes))
({:path "/sign-up", :method :get, :path-re #"/\Qsign-up\E", :path-parts ["sign-up"], :interceptors [#Interceptor{:name :io.pedestal.http/html-body} #Interceptor{:name :io.pedestal.http.ring-middlewares/session} #Interceptor{:name :blog.system.pedestal/using-component} #Interceptor{:name :io.pedestal.http.params/keyword-params} #Interceptor{:name }], :route-name :blog.web.pages/show-sign-up, :path-params []} {:path "/sign-up", :method :post, :path-re #"/\Qsign-up\E", :path-parts ["sign-up"], :interceptors [#Interceptor{:name :io.pedestal.http.body-params/body-params} #Interceptor{:name :io.pedestal.http/html-body} #Interceptor{:name :io.pedestal.http.ring-middlewares/session} #Interceptor{:name :blog.system.pedestal/using-component} #Interceptor{:name :io.pedestal.http.params/keyword-params} #Interceptor{:name }], :route-name :blog.web.pages/sign-up, :path-params []} {:path "/sign-in", :method :post, :path-re #"/\Qsign-in\E", :path-parts ["sign-in"], :interceptors [#Interceptor{:name :io.pedestal.http.body-params/body-params} #Interceptor{:name :io.pedestal.http/html-body} #Interceptor{:name :io.pedestal.http.ring-middlewares/session} #Interceptor{:name :blog.system.pedestal/using-component} #Interceptor{:name :io.pedestal.http.params/keyword-params} #Interceptor{:name }], :route-name :blog.web.pages/sign-in, :path-params []} {:path "/sign-in", :method :get, :path-re #"/\Qsign-in\E", :path-parts ["sign-in"], :interceptors [#Interceptor{:name :io.pedestal.http/html-body} #Interceptor{:name :io.pedestal.http.ring-middlewares/session} #Interceptor{:name :blog.system.pedestal/using-component} #Interceptor{:name :io.pedestal.http.params/keyword-params} #Interceptor{:name }], :route-name :blog.web.pages/show-sign-in, :path-params []} {:path "/", :method :get, :path-re #"/\Q\E", :path-parts [""], :interceptors [#Interceptor{:name :io.pedestal.http/html-body} #Interceptor{:name :io.pedestal.http.ring-middlewares/session} #Interceptor{:name :blog.system.pedestal/using-component} #Interceptor{:name :io.pedestal.http.params/keyword-params} #Interceptor{:name }], :route-name :blog.web.pages/root, :path-params []})

ddeaguiar14:02:56

hmm no they don't

ddeaguiar14:02:40

that's the handler, though

mtnygard14:02:16

Ah, I see what's happening. `pages/root gets turned into the fully-qualified symbol. If you had that directly in your route table it would still be a symbol when Pedestal turned it into an interceptor.

mtnygard14:02:59

Hrm, nevermind... I was on the wrong track there.

mtnygard14:02:49

I'm glad it's working. I'd be happy to take a closer look at the interceptor name thing later on when you've posted the code.

ddeaguiar14:02:29

np 🙂