Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Browse files

bump version; handle file uploads

  • Loading branch information...
commit 685bafa7f5b86bbd19d4bb56f533d9796cc4f07a 1 parent 9909b78
@xeqi authored
View
8 project.clj
@@ -1,14 +1,16 @@
-(defproject peridot "0.0.4"
+(defproject peridot "0.0.5-SNAPSHOT"
:description "a basic api for testing ring apps"
:url "https://github.com/xeqi/peridot"
:min-lein-version "2.0.0"
:dependencies [[org.clojure/clojure "1.3.0"]
[ring-mock "0.1.1"]
- [org.clojure/data.codec "0.1.0"]]
+ [org.clojure/data.codec "0.1.0"]
+ [org.apache.httpcomponents/httpmime "4.1.3"]]
:profiles {:test {:dependencies [[net.cgrand/moustache "1.1.0"
:exclusions
[[org.clojure/clojure]
[ring/ring-core]]]
- [ring/ring-core "1.0.2"]]}
+ [ring/ring-core "1.0.2"]]
+ :resource-paths ["test-resources"]}
:1.4 {:dependencies [[org.clojure/clojure "1.4.0-beta4"]]}}
:aliases {"all" ["with-profile" "test:test,1.4"]})
View
21 src/peridot/core.clj
@@ -2,6 +2,7 @@
(:use clojure.test)
(:require [ring.mock.request :as mock]
[peridot.cookie-jar :as cj]
+ [peridot.multipart :as multipart]
[clojure.data.codec.base64 :as base64]
[clojure.string :as string]))
@@ -11,7 +12,7 @@
(defn ^:private set-post-content-type [request]
(if (and (not (:content-type request))
(= :post (:request-method request)))
- (assoc request :content-type "application/x-www-form-urlencoded")
+ (mock/content-type request "application/x-www-form-urlencoded")
request))
(defn ^:private set-https-port [request]
@@ -19,13 +20,10 @@
(assoc request :server-port 443)
request))
-(defn ^:private to-header-key [k]
- (string/lower-case (str k)))
-
(defn ^:private add-headers [request headers]
(reduce (fn [req [k v]]
(if v
- (assoc-in req [:headers (to-header-key k)] v)
+ (mock/header req k v)
req))
request
headers))
@@ -35,10 +33,19 @@
request
env))
+(defn ^:private set-content-type [request content-type]
+ (if content-type
+ (mock/content-type request content-type)
+ request))
+
(defn ^:private build-request [uri env headers cookie-jar content-type]
(let [env (apply hash-map env)
params (:params env)
- request (mock/request :get uri params)]
+ request (if (multipart/multipart? params)
+ (merge-with merge
+ (multipart/build params)
+ (mock/request :get uri))
+ (mock/request :get uri params))]
(-> request
(add-headers (-> headers
(merge (cj/cookies-for cookie-jar
@@ -46,7 +53,7 @@
(:uri request)
(get-host request)))
(merge (:headers env))))
- (assoc :content-type content-type)
+ (set-content-type content-type)
(add-env (dissoc (dissoc env :params) :headers))
set-post-content-type
set-https-port)))
View
54 src/peridot/multipart.clj
@@ -0,0 +1,54 @@
+(ns peridot.multipart
+ (:import org.apache.http.entity.mime.MultipartEntity
+ org.apache.http.entity.mime.content.StringBody
+ org.apache.http.entity.mime.content.FileBody
+ java.io.PipedOutputStream
+ java.io.PipedInputStream
+ java.io.File
+ javax.activation.FileTypeMap))
+
+(defn multipart? [params]
+ (some #(instance? File %) (vals params)))
+
+(defmulti add-part
+ (fn [multipartentity key value] (type value)))
+
+(defmethod add-part File [m k f]
+ (.addPart m
+ k
+ (FileBody. f (.getContentType (FileTypeMap/getDefaultFileTypeMap)
+ f))))
+
+(defmethod add-part :default [m k v]
+ (.addPart m
+ k
+ (StringBody. (str v))))
+
+(defn entity [params]
+ (let [mpe (MultipartEntity.)]
+ (doseq [p params]
+ (apply add-part mpe p))
+ mpe))
+
+(defn build [params]
+ (let [mpe (entity params)]
+ {:body (let [in (PipedInputStream.)
+ out (PipedOutputStream. in)]
+ (future (do (.writeTo mpe out)
+ (.close out)))
+ in)
+ :content-length (.getContentLength mpe)
+ :content-type (.getValue (.getContentType mpe))
+ :headers {:content-type (.getValue (.getContentType mpe))
+ :content-length (.getContentLength mpe)}}))
+
+(comment
+ ;Add tests
+ ;does (content-type ...) interfere?
+ ;use below
+ (doto
+ (#(is (re-find #"multipart/form-data;"
+ (:content-type (:request %))))))
+ ;multiple files?
+ ;can we use rack-test tests?
+ )
View
1  test-resources/file.txt
@@ -0,0 +1 @@
+hi from file
View
39 test/peridot/test/multipart.clj
@@ -0,0 +1,39 @@
+(ns peridot.test.multipart
+ (:use [peridot.core]
+ [clojure.test])
+ (:require [peridot.multipart :as multipart]
+ [ring.util.response :as response]
+ [clojure.java.io :as io]))
+
+(deftest file-as-param-is-multipart
+ (is (multipart/multipart? {"file" (io/file (io/resource "file.txt"))}))
+ (is (not (multipart/multipart? {"file" "value"}))))
+
+(deftest uploading-a-file
+ (-> (session (constantly (response/response "ok")))
+ (request "/"
+ :request-method :post
+ :params {"file" (io/file (io/resource "file.txt"))})
+ (doto
+ (#(is (re-find #"multipart/form-data;"
+ (:content-type (:request %)))
+ "files shoul set content-type to multipart/form-data"))
+ (#(is (re-find #"hi from file" (slurp (:body (:request %)))))))))
+
+(deftest uploading-a-file-with-params
+ (-> (session (constantly (response/response "ok")))
+ (request "/"
+ :request-method :post
+ :params {"file" (io/file (io/resource "file.txt"))
+ "something" "else"})
+ (doto
+ (#(is (re-find #"multipart/form-data;"
+ (:content-type (:request %)))
+ "files should set content-type to multipart/form-data"))
+ ;;This is a simple test
+ ;;perhaps doing a roundtrip with multipart-params middleware
+ ;;and checking response would be better
+ (#(let [body (slurp (:body (:request %)))]
+ (is (re-find #"hi from file" body))
+ (is (re-find #"name=\"something\"" body))
+ (is (re-find #"\r\nelse\r\n--" body)))))))
Please sign in to comment.
Something went wrong with that request. Please try again.