From 90f2c68c6e718f60f7b84f4ea8c840801245ddc8 Mon Sep 17 00:00:00 2001 From: eltrac Date: Wed, 6 May 2026 11:56:09 +0800 Subject: refactor(processor): separate verification from processor logic --- src/weepinbell/processor.clj | 28 ++++++---------------------- src/weepinbell/utils.clj | 6 ------ src/weepinbell/verifier.clj | 39 +++++++++++++++++++++++++++++++++++++++ 3 files changed, 45 insertions(+), 28 deletions(-) create mode 100644 src/weepinbell/verifier.clj (limited to 'src') diff --git a/src/weepinbell/processor.clj b/src/weepinbell/processor.clj index fe2d600..4466745 100644 --- a/src/weepinbell/processor.clj +++ b/src/weepinbell/processor.clj @@ -1,29 +1,13 @@ (ns weepinbell.processor + "Process in-coming webmentions. + If no such webmention exists and request is verified, create. + If exists and verification fails, delete it. + If exists and verification passes, update it." (:require [clojure.core.async :refer [go-loop = status 200) (< status 300)) - ;; TODO needs to be more robust - (if (includes? (str body) target) - true - (do (timbre/error "Target link not found in source body.") false)) - (do (timbre/error "Source returned status:" status) false))) - (catch Exception e - (timbre/error "Error verifying mention:" (.getMessage e)) - false))) - (defn process-new-webmention "Store new webmention if verifed. Do nothing otherwise." [source target callbacks storage] @@ -62,7 +46,7 @@ (let [{:keys [s t]} wm] ;; first check Content-Types of both urls ;; only proceed when it's HTML or plain text - (if (validate-content-types s t) + (if (verify-content-types s t) ;; second check if such webmention exists ;; if so, update it or delete it ;; if not, write to data diff --git a/src/weepinbell/utils.clj b/src/weepinbell/utils.clj index 9afcc49..4611225 100644 --- a/src/weepinbell/utils.clj +++ b/src/weepinbell/utils.clj @@ -43,12 +43,6 @@ (string/includes? content-type "text/plain") :text :else false)) -(defn validate-content-types [source target] - (let [validate #(-> % get-content-type plain-or-html? boolean) - source-valid (validate source) - target-valid (validate target)] - (and source-valid target-valid))) - (defn javamap->map [map] (->> (seq map) (into {}) walk/keywordize-keys)) diff --git a/src/weepinbell/verifier.clj b/src/weepinbell/verifier.clj new file mode 100644 index 0000000..0928fb5 --- /dev/null +++ b/src/weepinbell/verifier.clj @@ -0,0 +1,39 @@ +(ns weepinbell.verifier + "Verifies in-coming webmentions after receiver checks URL. + This makes sure: + 1) source contains target URL. + 2) source respond with 2** status code. + 3) source's Content-Type is either HTML or plain text." + (:require [weepinbell.utils :refer [get-content-type plain-or-html?]] + [clojure.string :refer [includes?]] + [clj-http.client :as client] + [taoensso.timbre :as timbre])) + +(defn verify-content-types [source target] + (let [validate #(-> % get-content-type plain-or-html? boolean)] + (and (validate source) (validate target)))) + +(defn verify-mention + "Get source and follow redirects to check if target link is present." + [source target] + (try + (timbre/info (str "Verifying mention from: " source)) + ;; get first 1MB of source URL and verify + (let [{:keys [status body]} (client/get source {:throw false + :headers {"Range" "bytes=0-1048575"}})] + ;; Verify status code + (if (and (>= status 200) (< status 300)) + ;; Verify inclusion of target URL + ;; TODO needs to be more robust + (if (includes? (str body) target) + true + (do + (timbre/error "Target link not found in source body.") + false)) + (do + (timbre/error "Source returned status:" status) + false))) + (catch Exception e + (timbre/error "Error verifying mention:" (.getMessage e)) + false))) + -- cgit v1.2.3