summaryrefslogtreecommitdiff
path: root/src/weepinbell/webserver/handler.clj
blob: 70c26d28481487185de921b2650e0eb761c5b28b (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
(ns weepinbell.webserver.handler
  "Handler define routes and wrap responses. It pass request to other specific handlers.
  Other handlers are receiver, retriever and feed."
  (:require [clojure.spec.alpha :as s]
            [compojure.core :refer [routes POST GET context]]
            [compojure.route :as route]
            [ring.middleware.defaults :refer [wrap-defaults api-defaults]]
            [ring.middleware.json :refer [wrap-json-response]]))

(s/def ::services
  (s/and (s/keys :req-un [::receive ::retrieve-by-url ::retrieve-by-domain
                          ::retrieve-by-id ::retrieve-by-pair ::gen-feed
                          ::count-by-domain ::count-by-url])
         #(every? fn? (vals %))))
(s/def ::api-meta
  (s/keys :req-un [::wmc ::store ::config ::services]))

(defn- make-api
  "Receives webmention channel, storage vtable and config map.
   Returns a vector of compojure route handlers. Some may be nil."
  [api-meta]
  {:pre [(s/valid? ::api-meta api-meta)]
   :post [sequential?]}
  (let [{:keys [wmc store config services]} api-meta
        {:keys [receive retrieve-by-url retrieve-by-domain
                retrieve-by-id retrieve-by-pair
                count-by-domain count-by-url gen-feed]} services]
    [;; receiver endpoint
     (POST (:endpoint config) [source target]
       (receive {:s source :t target} wmc config))
    ;; query API routes
     (context "/api" []
       ;; TODO /api/send is temporarily an alias of /endpoint 
       ;; will be a full webmention sender in the future
       (POST "/send" [source target]
         (receive {:s source :t target} wmc config))
     ;; query webmention list
       (context "/mentions" [page jf2type]
         (GET "/" [url]
           (retrieve-by-url url page store
                            {:type jf2type}))
         (GET "/:domain" [domain]
           (retrieve-by-domain domain page store
                               {:type jf2type})))
      ;; query count of webmention list 
       (context "/count" [jf2type]
         (GET "/" [url]
           (count-by-url url store {:type jf2type}))
         (GET "/:domain" [domain]
           (count-by-domain domain store {:type jf2type})))
      ;; query one specific webmention
       (context "/mention" []
         (GET "/:id" [id] (retrieve-by-id id store))
         (GET "/" [source target] (retrieve-by-pair source target store))))
    ;; RSS feed
     (GET "/feed/:domain" [domain] (gen-feed domain store config))
    ;; host proxied avatars (jf2 photos)
     (route/files "/avatars/" {:root "data/avatars"})
    ;; 404
     (route/not-found "Not Found")]))

(defn- make-handler
  "Receive a vector of handlers. Remove nil elements.
   Combine them in one handler using compojure routes."
  [api]
  (->> api (remove nil?) (apply routes)))

(defn app
  "Receive webmention channel, storage vtable and config map. 
   Returns an app handler."
  [api-meta]
  (-> (make-api api-meta)
      make-handler
      (wrap-json-response)
      (wrap-defaults api-defaults)))