EzDevInfo.com

liberator

Liberator is a Clojure library for building RESTful applications. Liberator - Welcome

clojure liberator - why would handle ok give handlers for other http methods than get

I am trying to get my head round clojure liberator and i have come across this type of code below:

  :handle-ok (by-method {
    :get (fn [ctx] (render-item (:item ctx)))
    :post (fn [ctx] (render-item (:item ctx)))
    :put (fn [ctx] (update-item-response coll-slug ctx))})

At first I thought that handle-ok was simply for GET requests but then I came across this.

Why would I provide handlers for post and put in the example above? Are these post-request handlers.


Source: (StackOverflow)

How do I handle some but not all http methods in compojure with Liberator?

I'm using liberator with compojure, and wanted to send multiple methods (but not all methods) to the save resource. Rather than repeating myself, I'd like to have something that defines multiple handlers at once.

An example:

(defroutes abc 
  (GET "/x" [] my-func)
  (HEAD "/x" [] my-func)
  (OPTIONS "/x" [] my-func))

Should be closer to:

(defroutes abc
  (GET-HEAD-OPTIONS "/x" [] my-func))

Source: (StackOverflow)

Advertisements

How to implement user authentication using clojure-liberator?

I'm not really understanding https://github.com/clojure-liberator/liberator and the list of decision points that it provides to the developer. How would one implement a basic auth/auth service using/alongside/on-top-of the library?


Source: (StackOverflow)

How to return json data from post! handler in clojure liberator?

How to return json-data with Clojure Liberator? This code doesn't work:

(defresource poster []
         :allowed-methods [:post :options]
         :available-media-types ["application/json"]
         :post!      (fn [ctx] (println "posting..."))
         :handle-created (fn [ctx] {:created "ok"}))

Should handle-created be called after post?


Source: (StackOverflow)

Converting compojure noir to Liberator

I'm fairly new to clojure/compojure, but really love it. Naturally, started my exploration with Noir stack. Have written a POC app. Then, discovered Liberator -- makes a whole lot of sense. Just wondering, if anybody has ever migrated Noir applications to Liberator before. Any references to articles/blogs that cover this would be highly appreciated.


Source: (StackOverflow)

How to return 401 code from post clause in clojure liberator?

I have such a code:

(defresource errors []
         :authorized? (fn [ctx] (authorized? ctx))
         :allowed-methods [:post :options]
         :available-media-types media-types
         :post!      (fn [ctx] (-> ctx
                                   parse-json
                                   errors/insert-error)))

authorized? function checks user token, but I have some other rules, which I want to check inside post! function. How to do it? I can throw an Exception from the post! function, but I would like to return 401 status code.


Source: (StackOverflow)

I use clojure for creating REST API. How to generate REST documentation automatically?

I'm writing clojure rest service (with ring, compojure and liberator) and would like to automatically generate API documentation for all my REST API. It's very tedious to generate it manually. Is there any way to use annotations or something like this? It will be cool if I can do it with lein gen-rest-docs.


Source: (StackOverflow)

Line-seq ignore \n in string

I have a problem with liberator body-as-string function and line-seq.

(println
    (line-seq
        (BufferedReader. (StringReader. (body-as-string ctx)))
    )
)

With this curl command the function return (h1,h2\nh3,h4\nh5,h6) instead of (h1,h2 h3,h4 h5,h6)

curl "localhost:3000/log" -X POST -H "Content-type:text/csv" -d "h1,h2\nh3,h4\nh5,h6"

EDIT :

I add body-as-string function :

(defn body-as-string
"Parcours le contexte de la requĂȘte pour en extraire le body"
[ctx]

    (timbre/debug "body-as-string")

    (if-let
        [body (get-in ctx [:request :body])]
        (condp instance? body
            java.lang.String body
            (slurp (io/reader body))
        )
    )

)

Maybe is it an encoding problem ?

Thank you !


Source: (StackOverflow)

Clojure Liberator: get request body twice

Let's assume, that I've got an endpoint POST /endpoint that takes JSON as input data:

POST /endpoint
{
  "resource": {
    "name": "great"
  }
}

Now, I want to check whether the incoming JSON is valid. I thought that :malformed? hook would be a great place for doing that.

So I came up with such a code:

(ANY "/endpoint" [] 
     (resource
      :allowed-methods [:post]
      :available-media-types ["application/json"]
      :malformed? (fn [ctx] (let [body (get-body-from-request ctx)
                                   is-malformed (not (is-body-valid body))]
                                is-malformed)
      :post! (fn [ctx] (let [body (get-body-from-request ctx)]
                          (create-an-object body)))
      :handle-created (fn [ctx] {:method :post :body (:body @request)})))

So my intention was:

  • get the body from request, check if it's valid (is-body-valid)
  • in post! hook, use the body again and do real work (create-an-object)

The problem here is the get-body-from-request function:

(defn get-body-from-request [ctx]
  (json/read-str (slurp (get-in ctx [:request :body])) :key-fn keyword))

It works perfectly but the body is an InputStream, so I can read it only once.

Is there a way to use body of the request in more than one hook NOT using atoms?

The solutions coming to my mind:

  1. A middleware wrapper that adds a string version of body to the ctx param.
  2. Pass the result of malformed? to post!...
  3. Use atoms.

Thanks!


Source: (StackOverflow)

Liberator: Setting :representation :media-type in :media-type-available?

I wanted to use a decision point :media-type-available? but I failed...

I know I have to set the :representation :media-type but I don't really know how to do it.

So far, my code looks as the following:

(defresource test-resource []
  :media-type-available (fn [req]
    (assoc req :representation {:media-type "application/json"}))
  :available-media-types ["application/json" "text/html"]
  :handle-ok (fn [req] {:ok true})
)

Remarks:

  1. (assoc req :representation {:media-type "application/json"}) produces a correct map with "changed" req object.
  2. in :handle-ok's req object, the :representation value is {}

I have no idea how to set it (it's not a mutable object, is it?) and looking at the liberator's source code doesn't really help...

Thanks, Karol


Source: (StackOverflow)

How to validate form POST data with Liberator?

Where in the Liberator decision tree should I validate form input?

:malformed? seems to aimed at detecting invalid JSON or invalid form bodies.


Source: (StackOverflow)

Clojure - url "format" in json response

I write a REST API with Clojure liberator, and I have this function, in order to build the URL:

(defn build-entry-url [request]
   (URL. (format "%s://%s:%s%s"
           (name (:scheme request))
           (:server-name request)
           (:server-port request)
           (:context request))))

Then I use halresource for representing resources and cheshire to parse the json. When I use curl, in json response the URL is showed as:

http:\/\/localhost:8080\/api\/customer\/1

But if I use some tool, like Postman, the URL is showed correctly

Any suggestion?

UPDATE: I re-checked and all json is generated correctly, but when I use curl, or trying access the end-point via browser, the URL is showed as: http:\/\/localhost:8080\/api\/customer\/1


Source: (StackOverflow)

key delete! invoked when the method is PUT

I'm trying to build a simple rest api, using liberator and monger :

(ns tm.place.endpoint
  (:require [liberator.core :refer [defresource]]
            [monger [collection :as mc] [query :as mq]]
            [clojure.data [json :as json]]
            monger.json))

(defresource entity-place-resource [id]
  :available-media-types ["application/json"]
  :allowed-methods [:get :put :delete]
  :exists? (if-let [place (mc/find-map-by-id "place" id)] {:place place})
  :handle-ok :place
;  :handle-created (fn [ctx] 
;                     (let [body (-> ctx :request :body)]
;                       (assoc body :_id id)))
  :handle-not-found []
  :handle-not-acceptable "Should accept application/json"
  :handle-method-not-allowed (json/write-str 
                              {:message "Can only handle get, put and delete"})
;  :handle-not-implemented
;  :handle-no-content
  :put! (fn [ctx] 
          (let [body (-> ctx :request :body)]
            (mc/update-by-id "place" id (assoc body :_id id))))
  :delete! (mc/remove-by-id "place" id)
  :can-put-to-missing? false)

I'm using advanced rest client to see if it works. If the method is :get or :delete, it does perfectly what I want (It first check if a document is exists, and then do the appropriate action). However, if the method is :put, it simply spits out http 201 created, which I think the request is success, but the corresponding document is deleted, not updated.

If I comment out the :delete! line, the :put! is work as expected, so I'm guessing the culprit is the :delete! line, but I have no idea why because since I'm using :put method, I'm assuming :delete! should remain untouched. Any idea why?


Source: (StackOverflow)

Render resource when PUT

I am using liberator to build a API using Clojure. Given the follow code:

(defresource single-customer [id]
  :allowed-methods [:get, :put]
  :exists? (fn [_]
             (let [e (get @cust/customers (keyword id))]
               (if-not (nil? e)
                 {::entry e})))
  :existed? (fn [_] (nil? (get @cust/customers (keyword id) ::sentinel)))
  :available-media-types ["application/json"]
  :can-put-to-missing? false
  :put! (fn [q] (cust/set-as-fraudulent id))
  :handle-ok ::entry)

Someone when can tell me if is possible, like the GET request, when I send a PUT request it be redirected to the resource ? "/customer/1" (for example) ?


Source: (StackOverflow)

Getting a clojure map with keywords from a POST using Liberator

I'm using Liberator, and am having a hard time getting my POSTed data into a map using with keywords as the keys. Here is my resource, with a few printlines for testing:

(defresource finish_validation
             :allowed-methods [:post]
             :available-media-types ["application/json"]
             :post! (fn [context]
                      (let [params (slurp (get-in context [:request :body]))
                            mapped_params (cheshire/parse-string params)]

                        (println (type params))
                        (println (type mapped_params))
                        (validation/finish mapped_params)))
             :handle-created (println ))

For testing, I'm posting the data using curl:

curl -H "Content-Type: application/json" -X POST -d '{"email":"test@foo.com","code":"xyz"}' http://localhost:8080/validate

cheshire converts the params into a map, but the keys are not keywords: I get {email test@foo.com, code xyz} as the output, instead of the hoped-for {:email test@foo.com, :code xyz}.

Should I be doing something differently? Is this even the right approach to getting the data?


Source: (StackOverflow)