Skip to content

Commit

Permalink
Return an Error on Incorrect Content-Type for Search Requests
Browse files Browse the repository at this point in the history
Closes: #524
  • Loading branch information
alexanderkiel committed May 14, 2022
1 parent 49bcdf5 commit 575588a
Show file tree
Hide file tree
Showing 7 changed files with 122 additions and 17 deletions.
6 changes: 2 additions & 4 deletions modules/db-stub/src/blaze/db/api_stub.clj
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,7 @@
[blaze.db.tx-log.local]
[blaze.fhir.structure-definition-repo]
[blaze.test-util :refer [with-system]]
[integrant.core :as ig]
[java-time :as time]))
[integrant.core :as ig]))


(defn create-mem-node-system [node-config]
Expand All @@ -30,8 +29,7 @@
:resource-store (ig/ref :blaze.db/resource-store)
:kv-store (ig/ref :blaze.db/index-kv-store)
:resource-indexer (ig/ref :blaze.db.node/resource-indexer)
:search-param-registry (ig/ref :blaze.db/search-param-registry)
:poll-timeout (time/millis 10)}
:search-param-registry (ig/ref :blaze.db/search-param-registry)}
node-config)

::tx-log/local
Expand Down
4 changes: 2 additions & 2 deletions modules/db/test/blaze/db/api_test.clj
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
(ns blaze.db.api-test
"Main high-level test of all database API functions."
(:require
[blaze.anomaly :refer [when-ok]]
[blaze.anomaly :as ba :refer [when-ok]]
[blaze.anomaly-spec]
[blaze.async.comp :as ac]
[blaze.async.comp-spec]
Expand Down Expand Up @@ -482,7 +482,7 @@
(with-redefs
[resource-indexer/index-resources
(fn [_ _]
(ac/failed-future (ex-info "" {::anom/category ::anom/fault ::x ::y})))]
(ac/failed-future (ex-info "" (ba/fault "" ::x ::y))))]
(with-system [{:blaze.db/keys [node]} system]
(given-failed-future
(d/transact node [[:put {:fhir/type :fhir/Patient :id "0"}]])
Expand Down
3 changes: 2 additions & 1 deletion modules/db/test/blaze/db/node_test.clj
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
(ns blaze.db.node-test
(:require
[blaze.anomaly :as ba]
[blaze.async.comp :as ac]
[blaze.async.comp-spec]
[blaze.db.api :as d]
Expand Down Expand Up @@ -179,7 +180,7 @@
(with-redefs
[resource-indexer/index-resources
(fn [_ _]
(ac/failed-future (ex-info "" {::anom/category ::anom/fault ::x ::y})))]
(ac/failed-future (ex-info "" (ba/fault "" ::x ::y))))]

(testing "fetching the result immediately"
(with-system [{:blaze.db/keys [node]} resource-store-slow-on-put]
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
(ns blaze.rest-api.middleware.ensure-form-body
(:require
[blaze.anomaly :as ba]
[blaze.async.comp :as ac]
[ring.util.request :as request]))


(defn wrap-ensure-form-body [handler]
(fn [request]
(if (request/urlencoded-form? request)
(handler request)
(ac/completed-future
(ba/incorrect
(if (request/content-type request)
"Unsupported Content-Type header `application/fhir+json`. Please use `application/x-www-form-urlencoded`."
"Missing Content-Type header. Please use `application/x-www-form-urlencoded`.")
:http/status 415)))))
9 changes: 8 additions & 1 deletion modules/rest-api/src/blaze/rest_api/routes.clj
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
[blaze.middleware.fhir.error :as error]
[blaze.rest-api.middleware.auth-guard :as auth-guard]
[blaze.rest-api.middleware.batch-handler :as batch-handler]
[blaze.rest-api.middleware.ensure-form-body :as ensure-form-body]
[blaze.rest-api.middleware.forwarded :as forwarded]
[blaze.rest-api.middleware.output :as output]
[blaze.rest-api.middleware.resource :as resource]
Expand Down Expand Up @@ -47,6 +48,11 @@
:wrap db/wrap-db})


(def ^:private wrap-ensure-form-body
{:name :ensure-form-body
:wrap ensure-form-body/wrap-ensure-form-body})


(def ^:private wrap-sync
{:name :sync
:wrap
Expand Down Expand Up @@ -103,7 +109,8 @@
["/_search"
(cond-> {:name (keyword name "search") :conflicting true}
(contains? interactions :search-type)
(assoc :post {:middleware [[wrap-db node db-sync-timeout]]
(assoc :post {:middleware [wrap-ensure-form-body
[wrap-db node db-sync-timeout]]
:handler (-> interactions :search-type
:blaze.rest-api.interaction/handler)}))]
["/__page"
Expand Down
79 changes: 72 additions & 7 deletions modules/rest-api/test/blaze/rest_api_test.clj
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
(ns blaze.rest-api-test
(:require
[blaze.async.comp :as ac]
[blaze.db.api-stub :refer [mem-node-system]]
[blaze.db.impl.search-param]
[blaze.fhir.spec :as fhir-spec]
Expand All @@ -17,7 +18,10 @@
[juxt.iota :refer [given]]
[reitit.core :as reitit]
[reitit.ring]
[taoensso.timbre :as log]))
[ring.util.response :as response]
[taoensso.timbre :as log])
(:import
[java.io ByteArrayInputStream]))


(st/instrument)
Expand Down Expand Up @@ -157,7 +161,7 @@
"/Patient" :get [:params :output :error :forwarded :sync :db]
"/Patient" :post [:params :output :error :forwarded :sync :resource]
"/Patient/_history" :get [:params :output :error :forwarded :sync :db]
"/Patient/_search" :post [:params :output :error :forwarded :sync :db]
"/Patient/_search" :post [:params :output :error :forwarded :sync :ensure-form-body :db]
"/Patient/0" :get [:params :output :error :forwarded :sync :db]
"/Patient/0" :put [:params :output :error :forwarded :sync :resource]
"/Patient/0" :delete [:params :output :error :forwarded :sync]
Expand Down Expand Up @@ -302,19 +306,38 @@
(is (s/valid? :blaze.metrics/collector collector))))


(def system
(def ^:private success-handler
(constantly (ac/completed-future (response/status 200))))


(def ^:private system
(assoc mem-node-system
:blaze/rest-api
{:base-url "http://localhost:8080"
:version "0.1.0"
:structure-definition-repo (ig/ref ::empty-structure-definition-repo)
:structure-definition-repo (ig/ref :blaze.fhir/structure-definition-repo)
:node (ig/ref :blaze.db/node)
:search-param-registry (ig/ref :blaze.db/search-param-registry)
:db-sync-timeout 10000}
:db-sync-timeout 10000
:auth-backends []
:search-system-handler success-handler
:transaction-handler success-handler
:resource-patterns
[#:blaze.rest-api.resource-pattern
{:type :default
:interactions
{:read
#:blaze.rest-api.interaction
{:handler success-handler}
:delete
#:blaze.rest-api.interaction
{:handler success-handler}
:search-type
#:blaze.rest-api.interaction
{:handler success-handler}}}]}
:blaze.db/search-param-registry
{:structure-definition-repo (ig/ref :blaze.fhir/structure-definition-repo)}
:blaze.fhir/structure-definition-repo {}
::empty-structure-definition-repo {}))
:blaze.fhir/structure-definition-repo {}))


(defmethod ig/init-key ::empty-structure-definition-repo
Expand Down Expand Up @@ -392,3 +415,45 @@
:headers {"accept" "text/plain"}})
:status := 406
:body := nil)))


(defn empty-input-stream []
(ByteArrayInputStream. (byte-array 0)))


(deftest search-type-test
(testing "using POST"
(with-system [{:blaze/keys [rest-api]} system]
(given (call rest-api {:request-method :post :uri "/Patient/_search"
:headers {"content-type" "application/x-www-form-urlencoded"}
:body (empty-input-stream)})
:status := 200))

(testing "without Content-Type header"
(with-system [{:blaze/keys [rest-api]} system]
(let [request {:request-method :post :uri "/Patient/_search"
:body (empty-input-stream)}
{:keys [status body]} (call rest-api request)]

(is (= 415 status))

(given (fhir-spec/parse-json body)
:resourceType := "OperationOutcome"
[:issue 0 :severity] := "error"
[:issue 0 :code] := "invalid"
[:issue 0 :diagnostics] := "Missing Content-Type header. Please use `application/x-www-form-urlencoded`."))))

(testing "with unsupported media-type"
(with-system [{:blaze/keys [rest-api]} system]
(let [request {:request-method :post :uri "/Patient/_search"
:headers {"content-type" "application/fhir+json"}
:body (empty-input-stream)}
{:keys [status body]} (call rest-api request)]

(is (= 415 status))

(given (fhir-spec/parse-json body)
:resourceType := "OperationOutcome"
[:issue 0 :severity] := "error"
[:issue 0 :code] := "invalid"
[:issue 0 :diagnostics] := "Unsupported Content-Type header `application/fhir+json`. Please use `application/x-www-form-urlencoded`."))))))
21 changes: 19 additions & 2 deletions test/blaze/system_test.clj
Original file line number Diff line number Diff line change
Expand Up @@ -211,8 +211,7 @@
(deftest batch-unsupported-media-type-test
(with-system [{:blaze/keys [rest-api]} system]
(given (call rest-api {:request-method :post :uri ""
:headers {"content-type" "text/plain"}
:body ""})
:headers {"content-type" "text/plain"}})
:status := 415
[:body fhir-spec/parse-json :resourceType] := "OperationOutcome")))

Expand All @@ -235,6 +234,24 @@
[:body fhir-spec/parse-json :resourceType] := "Bundle")))


(deftest search-type-test
(testing "using POST"
(with-system [{:blaze/keys [rest-api]} system]
(given (call rest-api {:request-method :post :uri "/Patient/_search"
:headers {"content-type" "application/x-www-form-urlencoded"}
:body (input-stream (byte-array 0))})
:status := 200
[:body fhir-spec/parse-json :resourceType] := "Bundle"))

(testing "with unsupported media-type"
(with-system [{:blaze/keys [rest-api]} system]
(given (call rest-api {:request-method :post :uri "/Patient/_search"
:headers {"content-type" "application/fhir+json"}
:body (input-stream (byte-array 0))})
:status := 415
[:body fhir-spec/parse-json :resourceType] := "OperationOutcome")))))


(deftest redirect-slash-test
(with-system [{:blaze/keys [rest-api]} system]
(given (call rest-api {:request-method :get :uri "/Patient/"})
Expand Down

0 comments on commit 575588a

Please sign in to comment.