cmiles74 / bishop

A Webmachine-like library for Clojure
Other
95 stars 10 forks source link

Do you recommend Bishop for production systems? #18

Closed hussein closed 12 years ago

hussein commented 12 years ago

Hi, I'm sorry to use "Issues" to ask a question. I need to code a REST API and Bishop totally captivated me. Do you recommend it to production systems, or it is better to fall back to Compojure at this moment? Thanks a lot.

cmiles74 commented 12 years ago

No worries! :-)

I feel that Bishop is suitable for use in production systems and I recommend it for anyone building a web service. Bishop provides unique advantages in that it concentrates on providing a small library for building web services (as opposed to a general web application solution), functions are provided for parsing out "Accept" headers, ensuring that HTTP verbs are handled reasonably, and making it easy to provide the correct cache control headers. That's not to say that other tools couldn't be used as well, Bishop is provided as Ring handler and it can be combined it with many other libraries.

Right now I have used the Bishop library in one production system and am working on using it in a second project, also destined for production. I use this library to quickly build-up web services in my professional capacity as Senior Software Engineer at TNR Global, as such I have dedicated time to fix bugs and add new functionality.

The speed of the library has been acceptable for me, but so far my development efforts have concentrated on functionality. I suspect that the overhead of using Bishop is minimal, however, I should really get some numbers together. The plan is to begin looking at performance next. I haven't done much in the way of benchmarking or comparing to other, similar libraries but this is something I am looking forward to doing.

Future plans also involve taking another look at the routing provided by Bishop and making it easier to replace with something else. You can do so now (there's an example in the README using Moustache) but I think there's potential to improve this.

You should take a look at the code for this library and judge for yourself! It's decently commented and I've tried to keep it easy to read. I welcome pull requests and I try to turn them around as quickly as possible. Any feedback you can provide would be greatly appreciated.

hussein commented 12 years ago

Thanks, that is great to help. I have a couple of questions:

If a resource (list-todos) is defined with defresource, is it safe to:

(def routes
  {
    ["todo"] todo-api/list-todos
  })

?

How to map a path such:

/app/operation/:op/ticket/:ticket

How to map a path such:

/app/operation/:op/ticket/:ticket/?addAt=:pos
cmiles74 commented 12 years ago

You'll want to use the "wrap-params" Ring middleware. Ring will then parse out the query parameters into a map and place that under the :params key of your request map.

(defn main
  "Exposes the main function for bootstrapping the application."
  [& args]
  (run-jetty (-> (bishop/handler service/routes)
                 wrap-params)
             {:port 3000}))

With your query parameters handled, you won't need to signal that in your route, so it'll look a little simpler.

(def routes
  {["app" "operation" :op "ticket" :ticket] ticket-resource})

(I updated the route above to be correct, in my original reply I incorrectly wrote it as a string instead of a sequence)

In your handling function, you can get at the query parameters under the request's :param key and the other two URL parameters will be under the :path-info key of your request.

(bishop/defresource ticket-resource
  {;; HTML handler
   "text/html"
   (fn [request]
     {:body (xhtml {:lang "en" }
                   [:body [:p (str "OP: " (:op (:path-info request)) 
                                   ", TICKET:  " (:ticket (:path-info request)) 
                                   ", ADDAT: " ((:params request) "addAt" )]])})})
hussein commented 12 years ago

Hi again,

I had this:

(defn list-all [request]
  {:status 200 :body "Hi!"})

(defn create [request])

(bishop/defresource broker
  {
    "application/json"
    (fn [request]
      (let [request-method (:request-method request)]
        (log/info request-method)
        (case request-method
          :get  (list-all request)
          :post (create request))))
  }

  {
    :allowed-methods (fn [request] [:get :post])
  })
(def routes
  {
    ["api/broker"] broker
  })

(def bishop-handler (bishop/handler routes))

(ring-jetty/run-jetty (-> bishop-handler 
                            ring-middleware-params/wrap-params 
                            ring-middleware-multipart-params/wrap-multipart-params)
                      {:port 4444})

I'm using RESTest OSX client, pointed to: http://localhost:4444/api/broker , GET method, content-type is application/json but I got:

Resource not found

Same result when using a browser.

Any idea what is going wrong?

Thanks for help and time.

hussein commented 12 years ago

I tracked it to: https://github.com/tnr-global/bishop/blob/master/src/com/tnrglobal/bishop/core.clj#L148 But I don't know why the route isn't being picked up

hussein commented 12 years ago

Falling back to:

(def routes
  {
    ["broker"] broker
  })

works.

But I don't know what is the problem when URIs are having slashes.

cmiles74 commented 12 years ago

Hello,

Clearly the documentation on this could better! You're route should be a vector or sequence...

["api" "broker"]

This is modeled on the routing of webmachine: http://wiki.basho.com/Webmachine-Dispatching.html.

I'll add some text to the read-me to make this more clear.

hussein commented 12 years ago

Oh, I see. Then how to handle this?

/app/operation/:op/ticket/:ticket
/app/operation/:op/ticket/:ticket/?addAt=:pos

I followed what you suggested here: https://github.com/tnr-global/bishop/issues/18#issuecomment-8375061

Thanks!

cmiles74 commented 12 years ago

Yeah, sorry, that was my bad. I was rushing and was sloppy. :-$

["app" "operation" :op "ticket" :ticket]

The parameters can be handled with that Ring middleware.

hussein commented 12 years ago

It works now! My brain cores back to normal :D For future questions, what is best place to ask? Thanks for help.

cmiles74 commented 12 years ago

You can always shoot me an email: twitch@nervestaple.com. I'm also often on IRC over at Freenode in the #clojure channel, my username is "cmiles74".