This page is not created by, affiliated with, or supported by Slack Technologies, Inc.
2017-04-06
Channels
- # architecture (2)
- # aws (6)
- # bangalore-clj (3)
- # beginners (7)
- # boot (29)
- # cider (26)
- # cljs-dev (52)
- # cljsrn (1)
- # clojure (249)
- # clojure-dev (9)
- # clojure-italy (2)
- # clojure-norway (3)
- # clojure-russia (178)
- # clojure-uk (30)
- # clojureremote (6)
- # clojurescript (91)
- # core-async (4)
- # cursive (8)
- # datascript (3)
- # datavis (1)
- # datomic (6)
- # emacs (3)
- # figwheel (2)
- # hoplon (14)
- # incanter (6)
- # luminus (8)
- # mount (7)
- # off-topic (22)
- # om (25)
- # onyx (41)
- # pedestal (7)
- # re-frame (9)
- # ring (1)
- # spacemacs (4)
- # sql (1)
- # uncomplicate (1)
- # unrepl (37)
- # untangled (90)
- # yada (77)
Is is possible to change the interceptor chain during a request? A context has an interceptor chain, so I think I can just call yada.handler/append-interceptor
on it (although the argument is called res
, the key in the resource and context is the same)
No, or not without doing a subresource (which is a dynamic 'get out of jail' feature for anything super-dynamic)
Pedestal has that feature, I haven't come across a big need
Ah, so changing the interceptor chain on the next context doesn’t affect anything. Then why does a context have an interceptor chain?
Once the handler is created, the interceptors are fixed - this doesn't have to be the final design, and if you can argue a use-case then please do
Hmm - not sure - it inherits all the handler entries
I already solved this using two interceptors. I thought it was clever to remove the second interceptor based on a condition, so I wouldn’t have to check the condition in the second interceptor, but anyway, that’s probably too clever. I’m fine with the current design, just wondered if it was possible like in Pedestal.
I never used something like this in Pedestal either. In the last couple of days I’ve been comparing Yada with Pedestal, but we settled on Yada now as it suits or use case the best. More batteries included. We need Swagger. Tried Pedestal-API but it’s very macro oriented and made passing components to our routes awkward.
What made me wonder about Pedestal vs Yada: Pedestal has enter + leave functions in the interceptor while in Yada an interceptor is just a function from context to context and the chain and everything after i/invoke-method
in the chain works on the response if I understand correctly. A much simpler design which I like. But maybe it doesn’t matter that much.
Pedestals interceptors are all about adding/removing the next set of interceptors to use dynamically. It's how the router works for example.
Yada is really a curated set of interceptors that combine to offer increasing alignment to the HTTP specs. Pedestal leaves HTTP compliance an an exercise for the programming, giving them the tools to do so. My own opinion is that developers are too busy to have to read HTTP specs, it's the wrong abstraction for them to be working at.
> My own opinion is that developers are too busy to have to read HTTP specs, Very true, but the sad part is, they don't, so you get quite some wrongly implemented api's > it's the wrong abstraction for them to be working at. ... which yada solves: the dev shouldn't worry about the http spec. Yeah, I like yada a lot.
problem being, in my experience, the average developer couldn't care less about correct HTTP / REST behaviour, and is perfectly fine using URI's as commands, rather than resource locations
In our Ring based app we had this:
(defn no-cache
[response]
(-> response
(resp/header
"Cache-Control" "no-cache, max-age=0, must-revalidate, no-store")
(resp/header
"Pragma" "no-cache")
(resp/header
"Expires" “0”)))
How do I apply this in a Yada resource?I need a Yada resource, because in the returned HTML I want to include a link which I retrieved using (yada/url-for ctx ::home)
which I cannot do with a plain Ring handler
In your response function, if you return the actual response (start with (:response ctx)
) then yada will know that you're returning an actual response
You can then set the headers explicitly and they'll be merged into the response headers
The reason for this design is that in Liberator we had this problem of how Liberator might recognise the difference between a Ring response and a normal map. There are situations in yada where you want to return a normal map (it might be a JSON response), etc.
So the response in ctx is actually a Clojure Record - and remains the same record type even when you assoc/merge/conj into it
But, another valid approach is to code your own interceptor
Ah I was trying to do this:
:produces #{"application/html"}
:methods {:get (fn [ctx] {:headers … :body …})}
which didn’t work, because it tried to serialize a clojure map to html thereYou can add your own data to a yada resource record - just make sure you namespace the keys
@borkdude - yes, that's exactly the problem - how can yada know you mean a Ring response? Perhaps it could guess it from the keys, but really that's a nasty surprise lurking there
so the compromise is to use Clojure records - it works well, because you can treat records more or less like maps
so if you don’t use :methods but only :response directly in resource it will work with a Ring response?
fish out the response record from the request context and modify it as you like
no - use :methods
but each method has a response function
if you want this on every method, even OPTIONS, then write an interceptor
but I guess you'll only want no-cache on GETs
I don't think proxies will cache other methods anyway
so if you use a :response key+fn, it’s a Ring response, if you pass a fn it’s a function of ctx to data which Yada will then coerce to the right format
no, not quite
if you use a :response key and fn, the fn will be called. If you return a normal map, it will be coerced to the negotiated content-type, if you want to be explicit about the response, you return a response record
You do that by getting the response record from the request context (it's under the :response key) and modifying it as you like
e.g. (assoc-in (:response ctx) [:headers "cache-control"] "no-cache")
I thought I did this, but maybe (merge (:response ctx) ring-resp)
doesn’t return the right type. I’ll be back later.
ah - I thought merge didn't affect the type. I know dissoc will change a record to a map
Seems to be the case:
(comment
(type yada-resp) ;; yada.context.Response
(type ring-resp) ;; clojure.lang.PersistentArrayMap
(type (merge yada-resp ring-resp)) ;; yada.context.Response
)
I had some other mistake on my resource: “application/html” which caused the page to appear as a download, hehe 😖
In bidi, what is the string that is matched against the regular expression? Is it just the segment or the whole path?
e.g. [ [ "foo/" [ #"\d+" :id ] "/bar" ] :handler ]
which would match the string foo/123/bar
but not foo/abc/bar
.
foo/a123/bar
doesn't match
I'm just a bit confused as to what it's being passed
as if I make the regex #"^\d+$"
then it doesn't match foo/123/bar
does bidi turn the entire route path vector into a regex to match against? and use capturing groups to get the values for each regex?
In the example #"\d"
only applies to :id
If you want the whole pattern to be matched with a regex then use a regex for the pattern. But you'll lose the bidirectionality
@dominicm bidi does apply regexes to segments.
Sorry, I meant, bidi doesn't pay any special mind to path segments (it's not aware). Or is that wrong?
It is aware. Not sure what you mean
Whatever it matches gets captured in :id
, then the matching continues
@malcolmsparks exactly! bidi doesn't break up the url by segment was my meaning. It matches the path like a string.
Ah, right
If your regex is too greedy it will capture the /bar
as well
And then the overall pattern will fail
Thanks, I think I understand
So using #"^\d+$"
would be roughly equivalent to trying to write a regex foo\/(^\d+$)\/bar
?
which would fail
I have been wondering if it would be cool to build a router on top of https://github.com/cgrand/regex