I don't think you need a macro here. In any case, I'd avoid using a macro as late as possible. See how far you get with just functions, and then maybe at the end, add one macro if you absolutely need it to add just a touch of syntactic sugar.
routes should clearly be some sort of data-structure, rather than side-effect setter functions. Maybe this: (with-fake-routes! optional-server-instance route-map) Where optional-server-instance, if it exists is, an object returned by ( fake-server/start!). If optional-server-instance is not passed in, then with-fake-routes! creates it's own and is free to call (shutdown!) on it automatically. And route-map is a Map of routes: { "/x" {:status 200 :content-type "application/json" :body (slurp (io/resource "my.json"))} {:path "/y" :query {:q "something")}} {:status 200 :content-type "application/json" :body (slurp (io/resource "my2.json"))} } Also, at the risk of scope creep, I could foresee wanting the response to be based on the input instead of just a static blob. So maybe the value of :body could be a string or a function of 1 arg, the route-- in your code test with (fn?). This gives you a single api, no macros, optional auto-server start/stop or explicit server management. marc On Tue, Mar 8, 2016 at 3:10 AM, Johan Haleby <johan.hal...@gmail.com> wrote: > Hi, > > I've just committed an embryo of an open source project > <https://github.com/johanhaleby/fake-http> to fake http requests by > starting an actual (programmable) HTTP server. Currently the API looks like > this (which in my eyes doesn't look very Clojure idiomatic): > > (let [fake-server (fake-server/start!) > (fake-route! fake-server "/x" {:status 200 :content-type > "application/json" :body (slurp (io/resource "my.json"))}) > (fake-route! fake-server {:path "/y" :query {:q "something")}} > {:status 200 :content-type "application/json" :body (slurp (io/resource > "my2.json"))})] > ; Do actual HTTP request > (shutdown! fake-server)) > > > fake-server/start! starts the HTTP server on a free port (and thus have > side-effects) then you add routes to it by using fake-route!. The first > route just returns an HTTP response with status code 200 and content-type > "application/json" and the specified response body if a request is made > with path "/x". The second line also matches that a query parameter called > "q" must be equal to "something. In the end the server is stopped. > > I'm thinking of converting all of this into a macro that is used like this: > > (with-fake-routes! > "/x" {:status 200 :content-type "application/json" :body (slurp > (io/resource "my.json"))} > {:path "/y" :query {:q "something")}} {:status 200 :content-type > "application/json" :body (slurp (io/resource "my2.json"))}) > > This looks better imho and it can automatically shutdown the webserver > afterwards but there are some potential problems. First of all, since > starting a webserver is (relatively) slow it you might want to do this once > for a number of tests. I'm thinking that perhaps as an alternative (both > options could be available) it could be possible to first start the > fake-server and then supply it to with-fake-routes! as an additional > parameter. Something like this: > > (with-fake-routes! > fake-server ; We pass the fake-server as the first argument in > order to have multiple tests sharing the same fake-server > "/x" {:status 200 :content-type "application/json" :body (slurp > (io/resource "my.json"))} > {:path "/y" :query {:q "something")}} {:status 200 :content-type > "application/json" :body (slurp (io/resource "my2.json"))}) > > If so you would be responsible for shutting it down just as in the initial > example. > > Another thing that concerns me a bit with the macro is that routes doesn't > compose. For example you can't define the route outside of the > with-fake-routes! > body and just supply it as an argument to the macro (or can you?). I.e. I > think it would be quite nice to be able to do something like this: > > (let [routes [["/x" {:status 200 :content-type "application/json" :body > (slurp (io/resource "my.json"))}] > [{:path "/y" :query {:q "something")}} {:status 200 > :content-type "application/json" :body (slurp (io/resource "my2.json"))}]]] > (with-fake-routes routes)) > > Would this be a good idea? Would it make sense to have overloaded variants > of the with-fake-routes! macro to accommodate this as well? Should it be > a macro in the first place? What do you think? > > Regards, > /Johan > > -- > You received this message because you are subscribed to the Google > Groups "Clojure" group. > To post to this group, send email to clojure@googlegroups.com > Note that posts from new members are moderated - please be patient with > your first post. > To unsubscribe from this group, send email to > clojure+unsubscr...@googlegroups.com > For more options, visit this group at > http://groups.google.com/group/clojure?hl=en > --- > You received this message because you are subscribed to the Google Groups > "Clojure" group. > To unsubscribe from this group and stop receiving emails from it, send an > email to clojure+unsubscr...@googlegroups.com. > For more options, visit https://groups.google.com/d/optout. > -- You received this message because you are subscribed to the Google Groups "Clojure" group. To post to this group, send email to clojure@googlegroups.com Note that posts from new members are moderated - please be patient with your first post. To unsubscribe from this group, send email to clojure+unsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/group/clojure?hl=en --- You received this message because you are subscribed to the Google Groups "Clojure" group. To unsubscribe from this group and stop receiving emails from it, send an email to clojure+unsubscr...@googlegroups.com. For more options, visit https://groups.google.com/d/optout.