From 93e3b13ccc6ac4fa483babf5da3a538599495e8b Mon Sep 17 00:00:00 2001 From: "Yann Esposito (Yogsototh)" Date: Mon, 26 Aug 2024 02:34:01 +0200 Subject: [PATCH] Really allow everything --- project.clj | 6 ++-- src/fuck_cors/core.clj | 26 ++++++++-------- test/fuck_cors/core_test.clj | 59 ++++++++++++++++++++++++++++++++++-- 3 files changed, 74 insertions(+), 17 deletions(-) diff --git a/project.clj b/project.clj index f776a1b..3eccac5 100644 --- a/project.clj +++ b/project.clj @@ -1,6 +1,6 @@ -(defproject fuck-cors "0.1.7" - :description "Fuck CORS and open all to everyone" +(defproject fuck-cors "0.1.8" + :description "Fuck CORS and open your API to everyone" :url "http://github.com/yogsototh/fuck-cors" :license {:name "MIT" :url "http://opensource.org/licences/MIT"} - :dependencies [[org.clojure/clojure "1.9.0"]]) + :dependencies [[org.clojure/clojure "1.11.4"]]) diff --git a/src/fuck_cors/core.clj b/src/fuck_cors/core.clj index 59b02ad..5bba833 100644 --- a/src/fuck_cors/core.clj +++ b/src/fuck_cors/core.clj @@ -1,4 +1,5 @@ -(ns fuck-cors.core) +(ns fuck-cors.core + (:require [clojure.string :as string])) (defn- host-from-req [request] @@ -10,29 +11,30 @@ [request header-name] (let [rawref (get-in request [:headers header-name])] (if rawref - (clojure.string/replace rawref #"(http://[^/]*).*$" "$1") + (string/replace rawref #"(http://[^/]*).*$" "$1") nil))) (defn wrap-open-cors "Open your Origin Policy to Everybody, no limit" [handler] (fn [request] - (let [origin (get-header request "origin") + (let [origin (get-header request "origin") referer (get-header request "referer") - host (host-from-req request) + host (host-from-req request) origins (if origin origin (if referer referer host)) - headers {"Access-Control-Allow-Origin" origins - "Access-Control-Allow-Headers" "Origin, X-Requested-With, Content-Type, Accept, Cache-Control, Accept-Language, Accept-Encoding, Authorization" - "Access-Control-Allow-Methods" "HEAD, GET, POST, PUT, DELETE, OPTIONS, TRACE" - "Access-Control-Allow-Credentials" "true" - "Access-Control-Expose-Headers" "content-length" - "Vary" "Accept-Encoding, Origin, Accept-Language"}] - (-> (handler request) - (update-in [:headers] #(into % headers)))))) + {:keys [headers] :as original-response} (handler request) + resp-cors-headers + {"Access-Control-Allow-Origin" origins + "Access-Control-Allow-Headers" (string/join "," (keys headers)) + "Access-Control-Allow-Methods" "HEAD, GET, PATCH, POST, CONNECT, PUT, DELETE, OPTIONS, TRACE" + "Access-Control-Allow-Credentials" "true" + "Access-Control-Expose-Headers" (string/join "," (keys headers))}] + (-> original-response + (update-in [:headers] #(into % resp-cors-headers)))))) (defn wrap-preflight "Add a preflight answer. Will break any OPTIONS handler, beware. diff --git a/test/fuck_cors/core_test.clj b/test/fuck_cors/core_test.clj index 24a8b23..d2ab2b2 100644 --- a/test/fuck_cors/core_test.clj +++ b/test/fuck_cors/core_test.clj @@ -1,6 +1,7 @@ (ns fuck-cors.core-test - (:require [clojure.test :refer :all] - [fuck-cors.core :refer :all])) + (:require [clojure.test :refer [deftest testing is]] + [fuck-cors.core :refer [wrap-open-cors]] + [clojure.string :as string])) (def host-from-req (ns-resolve 'fuck-cors.core 'host-from-req)) @@ -10,3 +11,57 @@ :scheme :http}] (is (= "http://yannesposito.com" (host-from-req request)))))) + +(deftest wrap-open-cors-test + (testing "Can use any header" + (let [request-1 + {:server-port 443 + :server-name "yannesposito.com" + :remote-addr "127.0.0.1" + :uri "https://yannesposito.com/about/" + :scheme :https + :request-method :post + :headers {"host" "yannesposito.com" + "authorization" "Bearer 1337" + "Content-Type" "application/json; utf-8"} + :body "{\"foo\":\"bar\"}"} + + handler + (fn [_] + {:status 200 + :headers {"Origin" "https://yannesposito.com" + "Content-Type" "application/json; utf-8" + "X-SPECIFIC-HEADER" "42"} + :body "{\"foo\":\"bar\"}"}) + + wrapped (wrap-open-cors handler) + response-1 (wrapped request-1) + response-allowed-headers (some-> (get-in response-1 [:headers "Access-Control-Allow-Headers"]) + (string/split #",") + (set)) + response-expose-headers (some-> (get-in response-1 [:headers "Access-Control-Allow-Headers"]) + (string/split #",") + (set))] + + (is (contains? response-allowed-headers "Origin") + "Should contain the Origin header") + (is (contains? response-allowed-headers "X-SPECIFIC-HEADER") + "Can contain any strange custom made headers returned by the response") + + (is (contains? response-expose-headers "Origin") + "Should contain the Origin header") + (is (contains? response-expose-headers "X-SPECIFIC-HEADER") + "Can contain any strange custom made headers returned by the response") + + ;; full response for example purpose + (is (= {:status 200 + :headers {"Origin" "https://yannesposito.com" + "Content-Type" "application/json; utf-8" + "X-SPECIFIC-HEADER" "42" + "Access-Control-Allow-Origin" "https://yannesposito.com" + "Access-Control-Allow-Headers" "Origin,Content-Type,X-SPECIFIC-HEADER" + "Access-Control-Allow-Methods" "HEAD, GET, PATCH, POST, CONNECT, PUT, DELETE, OPTIONS, TRACE" + "Access-Control-Allow-Credentials" "true" + "Access-Control-Expose-Headers" "Origin,Content-Type,X-SPECIFIC-HEADER"} + :body "{\"foo\":\"bar\"}"} + response-1)))))