fukamachi / caveman

Lightweight web application framework for Common Lisp.
http://8arrow.org/caveman/
776 stars 62 forks source link

Support for content type negotiation #31

Closed ralcantaraperez closed 10 years ago

ralcantaraperez commented 10 years ago

It should be useful to have a way to define content type negotiation. E.g.:

(defroute "/" :content-type "text/html" ()
  (format nil "<div>Hello world!</div>"))

(defroute "/" :content-type "text/plain" ()
  (format nil "Hello world!</div>"))
fukamachi commented 10 years ago

I'm just thinking about the implementation of this feature. Only, in my mind, it should be more flexible. For example, to allow to introduce a new requirement in a web app.

Sinatra has a such system. http://www.sinatrarb.com/intro.html#Conditions

As Caveman2's defroute is only a macro for wrapping ningle:route, the implementation will be done in ningle.

fukamachi commented 10 years ago

Implemented in ningle.

https://github.com/fukamachi/ningle/commit/1eb0554027e010ca9835e99627274f28ef33f1f2

ralcantaraperez commented 10 years ago

Wow, that's warp 9 speed. Thank you very much ;) By the way, I have cloned the ningle git repository, and now... how do I use it from caveman? Thanks again ;)

fukamachi commented 10 years ago

Try this.

(defroute ("/" :content-type "text/html") ()
  "<div>Hello world!</div>")

(defroute ("/" :content-type "text/plain") ()
  "Hello world!")

The ("/" :content-type "text/html") part would be arguments for ningle:route.

ralcantaraperez commented 10 years ago

I tryed from Chrome and with curl (the next piece of code) and it returned a 404 page:

$ curl -H "Accept: text/plain" http://localhost:5000/

But now I've tested with curl like the next code and it returns the right thing:

$ curl -H "Content-Type: text/plain" http://localhost:5000/
Hello world!
$ curl -H "Content-Type: text/html" http://localhost:5000/
<div>Hello world!</div>

My question is, should not "Accept" be the right place to look for choosing the returned content type?

fukamachi commented 10 years ago

Hmm, it seems you're right. Sinatra has a routing condition :provides, it checks Accept header.

fukamachi commented 10 years ago

Okay, I changed the name to :accept.

(defroute ("/" :accept "text/html") ()
  "<div>Hello world!</div>")

(defroute ("/" :accept "text/plain") ()
  "Hello world!")

During that, I found a bug of Clack.Handler.Hunchentoot. It had been ignoring a Accept header. I also fixed it, so you need to clone the latest Clack for trying it.

ralcantaraperez commented 10 years ago

I've tested and it runs perfectly. Thank you very much ;)