summaryrefslogtreecommitdiff
path: root/compojure-3.2/src/compojure/http/request.clj
blob: 8c09616822d6d2633dca495707610810da9b7983 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
;; Copyright (c) James Reeves. All rights reserved.
;; The use and distribution terms for this software are covered by the Eclipse
;; Public License 1.0 (http://opensource.org/licenses/eclipse-1.0.php) which
;; can be found in the file epl-v10.html at the root of this distribution. By
;; using this software in any fashion, you are agreeing to be bound by the
;; terms of this license. You must not remove this notice, or any other, from
;; this software.

(ns compojure.http.request
  "Functions for pulling useful data out of a HTTP request map."
  (:use compojure.control
        compojure.encodings
        compojure.map-utils
        compojure.str-utils
        clojure.contrib.duck-streams
        clojure.contrib.str-utils)
  (:import java.net.URLDecoder
           java.io.InputStreamReader))

(defn- parse-params
  "Parse parameters from a string into a map."
  [param-string separator]
  (reduce
    (fn [param-map s]
      (if-let [[_ key val] (re-matches #"([^=]+)=(.*)" s)]
        (assoc-vec param-map
          (keyword (urldecode key))
          (urldecode (or val "")))
        param-map))
    {}
    (remove blank?
      (re-split separator param-string))))

(defn parse-query-params
  "Parse parameters from the query string."
  [request]
  (if-let [query (request :query-string)]
    (parse-params query #"&")))

(defn get-character-encoding
  "Get the character encoding, or use the default from duck-streams."
  [request]
  (or (request :character-encoding) *default-encoding*))

(defn- slurp-body
  "Slurp the request body into a string."
  [request]
  (let [encoding (get-character-encoding request)]
    (if-let [body (request :body)]
      (slurp* (InputStreamReader. body encoding)))))

(defn urlencoded-form?
  "Does a request have a urlencoded form?"
  [request]
  (if-let [type (:content-type request)]
    (.startsWith type "application/x-www-form-urlencoded")))

(defn parse-form-params
  "Parse urlencoded form parameters from the request body."
  [request]
  (if (urlencoded-form? request)
    (if-let [body (slurp-body request)]
      (parse-params body #"&"))))

(defn- get-merged-params
  "Get a map of all the parameters merged together."
  [request]
  (merge (:query-params request)
         (:form-params request)
         (:params request)))

(defn- assoc-func
  "Associate the result of a (func request) with a key on the request map."
  [request key func]
  (if (contains? request key)
    request
    (assoc request key (or (func request) {}))))

(defn assoc-params
  "Associate urlencoded parameters with a request. The following keys are added
  to the request map: :query-params, :form-params and :params."
  [request]
  (-> request
    (assoc-func :query-params parse-query-params)
    (assoc-func :form-params  parse-form-params)
    (assoc-func :params       get-merged-params)))

(defn with-request-params
  "Decorator that adds urlencoded parameters to the request map."
  [handler]
  (fn [request]
    (handler (assoc-params request))))

(defn parse-cookies
  "Pull out a map of cookies from a request map."
  [request]
  (if-let [cookies (get-in request [:headers "cookie"])]
    (parse-params cookies #";\s*")))

(defn assoc-cookies
  "Associate cookies with a request map."
  [request]
  (assoc-func request :cookies parse-cookies))

(defn with-cookies
  "Decorator that adds cookies to a request map."
  [handler]
  (fn [request]
    (handler (assoc-cookies request))))