3
votes

I am using liberator with ring/compojure and would like to handle authorization using the liberator defresource macros. I can easily get handle-ok to output html that is recognized by the browser, but handle-unauthorized will have the html output in pre tags.

I'm suspecting that my not being able to find out how to do this means that there is a good reason not to do it this way. All the examples I see online show handle-unauthorized returning text, but I was hoping to display a custom page.

Here is (one version of) the code I was using. I am using Hiccup:

(defresource deny-all
  :authorized? (fn [_] false)
  :available-media-types ["text/html"]
  :handle-ok (fn [ctx] (html5 [:body [:h1 "Yes!"]])))
  :handle-unauthorized (fn [ctx] (html5 [:body [:h1 "Noooo!"]])))

What I get back from the browser is a literal

<!DOCTYPE html>
<html><body><h1>Noooo!</h1></body></html>
</pre>

If I change authorized? to return true, then it outputs the html correctly.

I've tried returning ring-style responses, but those raise errors too. What am I missing?

1

1 Answers

3
votes

In REST talk, html is one of many possible representations of a resource. Since the resource is unauthorized, no representation should be returned, html or otherwise. Instead, the client, instructed by the 401 status error, should take a different course of action, such as requesting a login page.

Most apps written in web frameworks will not return a 401, but instead redirect to the authorization page. This is possible in Liberator too, because nothing stops you from handling the authorization in the resource itself (handle-ok with logic).

This might be a breach of practice. I posted an issue on Liberator's github to ask for the opinion of people more knowledgeable in the recipes of RESTful cooking.

At any rate, the reason you see your html wrapped in a pre tag is the result of the following factors:

  1. Content negotiation is not available for unauthorized resources in Liberator. The 401's body is always of type text/plain.
  2. When you specify a html string as the response, it will render as is.
  3. When using Chrome development tools, upon inspecting the source, you will see the html string wrapped in a pre tag.

I hope this helps.