diff --git a/modules/rest-api/src/blaze/rest_api/middleware/output.clj b/modules/rest-api/src/blaze/rest_api/middleware/output.clj
index f8ad56654..b131777be 100644
--- a/modules/rest-api/src/blaze/rest_api/middleware/output.clj
+++ b/modules/rest-api/src/blaze/rest_api/middleware/output.clj
@@ -4,7 +4,6 @@
[blaze.fhir.spec :as fhir-spec]
[clojure.data.xml :as xml]
[clojure.java.io :as io]
- [clojure.string :as str]
[muuntaja.parse :as parse]
[prometheus.alpha :as prom]
[ring.util.response :as ring]
@@ -42,38 +41,48 @@
(generate-xml* body)))
-(defn- encode-response-json [response]
+(defn- encode-response-json [response content-type]
(-> (update response :body generate-json)
- (ring/content-type "application/fhir+json;charset=utf-8")))
+ (ring/content-type content-type)))
-(defn- encode-response-xml [response]
+(defn- encode-response-xml [response content-type]
(-> (update response :body generate-xml)
- (ring/content-type "application/fhir+xml;charset=utf-8")))
-
-
-(defn- json-format? [format]
- (or (str/includes? format "json") (#{"*/*" "application/*" "text/*"} format)))
+ (ring/content-type content-type)))
(defn- format-key [format]
- (cond
- (json-format? format) :json
- (str/includes? format "xml") :xml))
+ (condp = format
+ "application/fhir+json" :fhir+json
+ "application/fhir+xml" :fhir+xml
+ "application/json" :json
+ "application/xml" :xml
+ "text/json" :text-json
+ "text/xml" :text-xml
+ "*/*" :fhir+json
+ "application/*" :fhir+json
+ "text/*" :text-json
+ "json" :fhir+json
+ "xml" :fhir+xml
+ nil))
(defn- request-format
[{{:strs [accept]} :headers {format "_format"} :query-params}]
(or (some-> format format-key)
- (if-let [first-accept (first (parse-accept accept))]
- (format-key first-accept)
- :json)))
+ (if-let [accept (parse-accept accept)]
+ (some format-key accept)
+ :fhir+json)))
(defn- encode-response [opts request response]
(case (request-format request)
- :json (encode-response-json response)
- :xml (encode-response-xml response)
+ :fhir+json (encode-response-json response "application/fhir+json;charset=utf-8")
+ :fhir+xml (encode-response-xml response "application/fhir+xml;charset=utf-8")
+ :json (encode-response-json response "application/json;charset=utf-8")
+ :xml (encode-response-xml response "application/xml;charset=utf-8")
+ :text-json (encode-response-json response "text/json;charset=utf-8")
+ :text-xml (encode-response-xml response "text/xml;charset=utf-8")
(when (:accept-all? opts) (dissoc response :body))))
diff --git a/modules/rest-api/test/blaze/rest_api/middleware/output_test.clj b/modules/rest-api/test/blaze/rest_api/middleware/output_test.clj
index a5d01c14c..3cb055f7a 100644
--- a/modules/rest-api/test/blaze/rest_api/middleware/output_test.clj
+++ b/modules/rest-api/test/blaze/rest_api/middleware/output_test.clj
@@ -1,16 +1,17 @@
(ns blaze.rest-api.middleware.output-test
(:require
+ [blaze.fhir.spec :as fhir-spec]
[blaze.fhir.spec-spec]
[blaze.rest-api.middleware.output :refer [wrap-output]]
[blaze.test-util :as tu]
[blaze.test-util.ring :refer [call]]
+ [clojure.data.xml :as xml]
+ [clojure.java.io :as io]
[clojure.spec.test.alpha :as st]
[clojure.test :as test :refer [are deftest is testing]]
[juxt.iota :refer [given]]
[ring.util.response :as ring]
- [taoensso.timbre :as log])
- (:import
- [java.nio.charset StandardCharsets]))
+ [taoensso.timbre :as log]))
(st/instrument)
@@ -34,74 +35,153 @@
(respond (ring/response {:fhir/type :fhir/Patient :id "0"})))))
-(defn- bytes->str [^bytes bs]
- (String. bs StandardCharsets/UTF_8))
+(defn- parse-json [body]
+ (fhir-spec/conform-json (fhir-spec/parse-json body)))
(deftest json-test
(testing "JSON is the default"
(testing "without accept header"
(given (call resource-handler {})
- [:body bytes->str] := "{\"id\":\"0\",\"resourceType\":\"Patient\"}"))
+ [:headers "Content-Type"] := "application/fhir+json;charset=utf-8"
+ [:body parse-json] := {:fhir/type :fhir/Patient :id "0"}))
(testing "with accept header"
- (are [accept] (given (call resource-handler {:headers {"accept" accept}})
- [:body bytes->str] := "{\"id\":\"0\",\"resourceType\":\"Patient\"}")
- "*/*"
- "application/*"
- "text/*")))
+ (are [accept content-type]
+ (given (call resource-handler {:headers {"accept" accept}})
+ [:headers "Content-Type"] := content-type
+ [:body parse-json] := {:fhir/type :fhir/Patient :id "0"})
+ "*/*" "application/fhir+json;charset=utf-8"
+ "application/*" "application/fhir+json;charset=utf-8"
+ "text/*" "text/json;charset=utf-8")))
(testing "possible accept headers"
- (are [accept]
+ (are [accept content-type]
(given (call resource-handler {:headers {"accept" accept}})
- [:body bytes->str] := "{\"id\":\"0\",\"resourceType\":\"Patient\"}")
- "application/fhir+json"
- "application/json"
- "text/json"
- "application/fhir+xml;q=0.9, application/fhir+json;q=1.0"))
+ [:headers "Content-Type"] := content-type
+ [:body parse-json] := {:fhir/type :fhir/Patient :id "0"})
+ "application/fhir+json" "application/fhir+json;charset=utf-8"
+ "application/json" "application/json;charset=utf-8"
+ "text/json" "text/json;charset=utf-8"
+ "application/fhir+xml;q=0.9, application/fhir+json;q=1.0" "application/fhir+json;charset=utf-8"))
(testing "_format overrides"
- (are [accept format]
+ (are [accept format content-type]
(given (call resource-handler
{:headers {"accept" accept}
:query-params {"_format" format}})
- [:body bytes->str] := "{\"id\":\"0\",\"resourceType\":\"Patient\"}")
- "application/fhir+xml" "application/fhir+json"
- "application/fhir+xml" "application/json"
- "application/fhir+xml" "text/json"
- "application/fhir+xml" "json"
- "*/*" "application/fhir+json"
- "*/*" "application/json"
- "*/*" "text/json"
- "*/*" "json")))
+ [:headers "Content-Type"] := content-type
+ [:body parse-json] := {:fhir/type :fhir/Patient :id "0"})
+ "application/fhir+xml"
+ "application/fhir+json"
+ "application/fhir+json;charset=utf-8"
+
+ "application/fhir+xml"
+ "application/json"
+ "application/json;charset=utf-8"
+
+ "application/fhir+xml"
+ "text/json"
+ "text/json;charset=utf-8"
+
+ "application/fhir+xml"
+ "json"
+ "application/fhir+json;charset=utf-8"
+
+ "*/*"
+ "application/fhir+json"
+ "application/fhir+json;charset=utf-8"
+
+ "*/*"
+ "application/json"
+ "application/json;charset=utf-8"
+
+ "*/*"
+ "text/json"
+ "text/json;charset=utf-8"
+
+ "*/*"
+ "json"
+ "application/fhir+json;charset=utf-8")))
+
+
+(defn- parse-xml [body]
+ (with-open [reader (io/reader body)]
+ (fhir-spec/conform-xml (xml/parse reader))))
(deftest xml-test
(testing "possible accept headers"
- (are [accept]
+ (are [accept content-type]
(given (call resource-handler {:headers {"accept" accept}})
- [:body bytes->str] :=
- "")
+ [:headers "Content-Type"] := content-type
+ [:body parse-xml] := {:fhir/type :fhir/Patient :id "0"})
"application/fhir+xml"
+ "application/fhir+xml;charset=utf-8"
+
"application/xml"
+ "application/xml;charset=utf-8"
+
"text/xml"
- "application/fhir+json;q=0.9, application/fhir+xml;q=1.0"))
+ "text/xml;charset=utf-8"
+
+ "application/fhir+json;q=0.9, application/fhir+xml;q=1.0"
+ "application/fhir+xml;charset=utf-8"
+
+ ;; Safari
+ "text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8"
+ "application/xml;charset=utf-8"
+
+ ;; Chrome
+ "text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9"
+ "application/xml;charset=utf-8"
+
+ ;; Edge
+ "text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9"
+ "application/xml;charset=utf-8"
+
+ ;; Firefox
+ "text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,*/*;q=0.8"
+ "application/xml;charset=utf-8"))
(testing "_format overrides"
- (are [accept format]
+ (are [accept format content-type]
(given (call resource-handler
{:headers {"accept" accept}
:query-params {"_format" format}})
- [:body bytes->str] :=
- "")
- "application/fhir+json" "application/fhir+xml"
- "application/fhir+json" "application/xml"
- "application/fhir+json" "text/xml"
- "application/fhir+json" "xml"
- "*/*" "application/fhir+xml"
- "*/*" "application/xml"
- "*/*" "text/xml"
- "*/*" "xml")))
+ [:headers "Content-Type"] := content-type
+ [:body parse-xml] := {:fhir/type :fhir/Patient :id "0"})
+ "application/fhir+json"
+ "application/fhir+xml"
+ "application/fhir+xml;charset=utf-8"
+
+ "application/fhir+json"
+ "application/xml"
+ "application/xml;charset=utf-8"
+
+ "application/fhir+json"
+ "text/xml"
+ "text/xml;charset=utf-8"
+
+ "application/fhir+json"
+ "xml"
+ "application/fhir+xml;charset=utf-8"
+
+ "*/*"
+ "application/fhir+xml"
+ "application/fhir+xml;charset=utf-8"
+
+ "*/*"
+ "application/xml"
+ "application/xml;charset=utf-8"
+
+ "*/*"
+ "text/xml"
+ "text/xml;charset=utf-8"
+
+ "*/*"
+ "xml"
+ "application/fhir+xml;charset=utf-8")))
(deftest not-acceptable-test