Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

How to extract the form data from a request in liberator? #317

Open
zendevil opened this issue Mar 4, 2020 · 1 comment
Open

How to extract the form data from a request in liberator? #317

zendevil opened this issue Mar 4, 2020 · 1 comment

Comments

@zendevil
Copy link

zendevil commented Mar 4, 2020

I have the following client-side request:

(let [form-data (doto
                       (js/FormData.)
                     (.append "filename" file))]
     (ajax-request
      {:uri "/some/uri"
       :method :post
       :body form-data
       :format (raw-request-format)
       :response-format (raw-response-format)})
     )

And on the server (with liberator):

(defresource some-resource [_]
  :allowed-methods [:get :post]
  :available-media-types ["application/json"]
  :exists? (fn [ctx]
             (prn "form-data " (-> ctx :request :body slurp)) ;prints
             (prn "form-data " (-> ctx :request :body slurp cheshire/decode)) ;doesn't print
             ))

At the server, I do get the print of the form-data like so:

"form-data " "------WebKitFormBoundaryI9CA2zKhFT0Stmx7\r\nContent-Disposition: form-data; name=\"new-name\"\r\n\r\n{:uploaded-file #object[File [object File]], :name \"somename\", :another \"1234\"}\r\n------WebKitFormBoundaryI9CA2zKhFT0Stmx7--\r\n"

But the next prn doesn't print anything where my goal is to extract the :uploaded-file. What am I doing wrong?

@tribals
Copy link

tribals commented Dec 21, 2023

I bet you should use ring.middleware.params/wrap-params to get form-data in :form-params map of request. Then, your form data will appear in this sub-map with keys corresponding to names of inputs you had specified in your HTML (I assume but omit such HTML):

(require '[ring.middleware.params :refer [wrap-params]])
(require '[liberator.core :refer [defresource]])
(require '[compojure.core :refer [defroutes ANY]])
(require '[expectations.clojure.test :refer [defexpect expect]])
(require '[ring.mock.request :as mock])

(defresource handle-form-uploads
  :allowed-methods #{:get :post}
  :available-media-types ["text/plain"]
  :handle-created (fn [ctx]
                    (str (get-in ctx [:request :form-params "greeting"]) ", "
                         (get-in ctx [:request :form-params "name"]) "!")))

(defroutes my-app-routes
  (ANY "/" [] handle-form-uploads))

(def my-app
  (wrap-params my-app-routes))

(defexpect handling-form-uploads
  (expect
    {
      :status 201
      :headers {"Content-Type" "text/plain;charset=UTF-8" "Vary" "Accept"}
      :body "Hello, Prikshet!"}
    (my-app (-> (mock/request :post "/")
                (mock/body {:name "Prikshet" :greeting "Hello"})))))

(handling-form-uploads)

deps.edn:

{
  :deps
  {
    liberator/liberator {:mvn/version "0.15.3"}
    ring/ring-core {:mvn/version "1.11.0-RC2"}
    compojure/compojure {:mvn/version "1.7.0"}
    expectations/clojure-test {:mvn/version "1.2.1"}
    ring/ring-mock {:mvn/version "0.4.0"}}}

Notice that "form" keys will appear in map as strings, not keywords.

Take a look at ring.middlewares.multipart-params if you want to process uploaded files as well.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants