summaryrefslogtreecommitdiff
path: root/compojure-3.2/src/compojure/http/helpers.clj
blob: f60eeb9ac9f7d60e8e48ec02b11fd6b8a21b3ce4 (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
;; 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.helpers
  "Helper functions for things like redirection, serving files, 404s, etc."
  (:use compojure.encodings
        compojure.str-utils
        clojure.contrib.def
        clojure.contrib.str-utils
        clojure.contrib.duck-streams)
  (:import java.io.File))

(defn- encode-cookie
  "Encode sequence of key/value pairs a cookie."
  [name value attrs]
  (str-join "; "
    (cons (str (urlencode name) "=" (urlencode value))
          (for [[key val] attrs] (str* key "=" val)))))

(defn set-cookie
  "Return a Set-Cookie header."
  ([name value]
    {:headers {"Set-Cookie" (encode-cookie name value nil)}})
  ([name value & attrs]
    {:headers {"Set-Cookie" (encode-cookie name value (partition 2 attrs))}}))

(defn content-type
  "Retuns a Content-Type header given a type string."
  [type]
  {:headers {"Content-Type" type}})

(defn redirect-to
  "A shortcut for a '302 Moved' HTTP redirect."
  [location]
  [302 {:headers {"Location" location}}])
 
(defn page-not-found
  "A shortcut to create a '404 Not Found' HTTP response."
  ([]
    (page-not-found "public/404.html"))
  ([filename]
    [404 (File. filename)]))

(defn- find-index-file
  "Search the directory for index.*"
  [dir]
  (first
    (filter
      #(.startsWith (.toLowerCase (.getName %)) "index.")
       (.listFiles dir))))

(defn safe-path?
  "Is a filepath safe for a particular root?"
  [root path]
  (.startsWith (.getCanonicalPath (File. root path))
               (.getCanonicalPath (File. root))))

(defn serve-file
  "Attempts to serve up a static file from a directory, which defaults to
  './public'. Nil is returned if the file does not exist. If the file is a
  directory, the function looks for a file in the directory called 'index.*'."
  ([path]
    (serve-file "public" path))
  ([root path]
    (let [filepath (File. root path)]
      (if (safe-path? root path)
        (cond 
          (.isFile filepath)
            filepath
          (.isDirectory filepath)
            (find-index-file filepath))))))