diff --git a/etp-backend/src/main/clj/solita/etp/api/palveluvayla.clj b/etp-backend/src/main/clj/solita/etp/api/palveluvayla.clj index 96fc90ef5..b04991a31 100644 --- a/etp-backend/src/main/clj/solita/etp/api/palveluvayla.clj +++ b/etp-backend/src/main/clj/solita/etp/api/palveluvayla.clj @@ -1,5 +1,6 @@ (ns solita.etp.api.palveluvayla - (:require [schema.core :as s] + (:require [clojure.string :as str] + [schema.core :as s] [solita.etp.api.response :as api-response] [solita.etp.schema.common :as schema.common] [solita.etp.schema.energiatodistus :as schema.energiatodistus] @@ -7,18 +8,35 @@ (def accept-language-header {(s/optional-key :accept-language) schema.common/AcceptLanguage}) +(def energiatodistus-id-parameter {:id schema.common/EnergiatodistusId}) + +(defn- parse-lang + "Parse a language from language tag i.e. drop subtags such as region separated by -" + [s] + (-> s (str/split #"-") first)) + +(defn- parse-locale [s] + (let [parts (str/split s #";q=")] + (case (count parts) + 1 [(parse-lang s) 1.0] + 2 [(-> parts first parse-lang) (Double/parseDouble (second parts))]))) + +(defn- parse-accept-language [s] + (map parse-locale (map str/trim (str/split s #",")))) + (defn parse-preferred-language-order "Sort Accept-Language headers by quality and return only the languages tags in order of preference" [accept-language] (some->> accept-language + (parse-accept-language) (sort-by second) (reverse) (map first))) (def routes ["/v1/energiatodistukset" ["/pdf/:id" - ["" {:get {:summary "Hae PDF-muotoinen energiatodistus tunnuksen id:llä" - :parameters {:path {:id schema.common/Key} + ["" {:get {:summary "Hae PDF-muotoinen energiatodistus tunnisteella" + :parameters {:path energiatodistus-id-parameter :header accept-language-header} :responses {200 {:body nil} 404 {:body s/Str}} @@ -35,14 +53,14 @@ :format "binary"}}}}}}}}]] ["/json" ["/any" - ["" {:get {:summary "Hae energiatodistuksia json-muodossa. Palauttaa jaetut kentät sekä 2013, että 2018 lain mukaisista energiatodistuksista" + ["" {:get {:summary "Hae energiatodistusten perustietoja. Palauttaa tiedot sekä 2013, että 2018 lain mukaisista energiatodistuksista. Tarkemmat tiedot saa hakemalla todistuksen oikean version" :parameters {:query {:rakennustunnus schema.common/Rakennustunnus}} :responses {200 {:body [schema.energiatodistus/EnergiatodistusForAnyLaatija]}} :handler (fn [{{:keys [query]} :parameters :keys [db]}] (api-response/get-response (service.palveluvayla/search-by-rakennustunnus (:rakennustunnus query) schema.energiatodistus/EnergiatodistusForAnyLaatija db) (str "Virhe haussa")))}}] - ["/:id" {:get {:summary "Hae yksittäinen energiatodistus todistuksen tunnuksen perusteella. Vastaus sisältää vain kentät jotka ovat yhteisiä 2013 ja 2018 versioille." + ["/:id" {:get {:summary "Hae yksittäinen energiatodistus todistuksen tunnuksen perusteella. Palauttaa perustiedot sekä 2013, että 2018 lain mukaisista energiatodistuksista. Tarkemmat tiedot saa hakemalla todistuksen oikean version" :parameters {:path {:id schema.common/Key}} :responses {200 {:body schema.energiatodistus/EnergiatodistusForAnyLaatija} 404 {:body s/Str}} @@ -51,14 +69,14 @@ (service.palveluvayla/get-by-id id db) (str "Energiatodistus " id " does not exists.")))}}]] ["/2013" - ["" {:get {:summary "Hae energiatodistuksia, jotka on laadittu vuoden 2013 säännösten mukaan" + ["" {:get {:summary "Hae json-muotoisia energiatodistuksia, jotka on laadittu vuoden 2013 säännösten mukaan" :parameters {:query {:rakennustunnus schema.common/Rakennustunnus}} :responses {200 {:body [schema.energiatodistus/Energiatodistus2013]}} :handler (fn [{{:keys [query]} :parameters :keys [db]}] (api-response/get-response (service.palveluvayla/search-by-rakennustunnus (:rakennustunnus query) schema.energiatodistus/Energiatodistus2013 db 2013) (str "Virhe haussa")))}}] - ["/:id" {:get {:summary "Hae yksittäinen vuoden 2013 säännösten mukainen energiatodistus todistuksen tunnuksen perusteella" + ["/:id" {:get {:summary "Hae yksittäinen vuoden 2013 säännösten mukainen energiatodistus todistuksen tunnuksen perusteella json-muodossa" :parameters {:path {:id schema.common/Key}} :responses {200 {:body schema.energiatodistus/Energiatodistus2013} 404 {:body s/Str}} @@ -67,14 +85,14 @@ (service.palveluvayla/get-by-id id db 2013) (str "Energiatodistus " id " does not exists.")))}}]] ["/2018" - ["" {:get {:summary "Hae energiatodistuksia, jotka on laadittu vuoden 2018 säännösten mukaan" + ["" {:get {:summary "Hae json-muotoisia energiatodistuksia, jotka on laadittu vuoden 2018 säännösten mukaan" :parameters {:query {:rakennustunnus schema.common/Rakennustunnus}} :responses {200 {:body [schema.energiatodistus/Energiatodistus2018]}} :handler (fn [{{:keys [query]} :parameters :keys [db]}] (api-response/get-response (service.palveluvayla/search-by-rakennustunnus (:rakennustunnus query) schema.energiatodistus/Energiatodistus2018 db 2018) (str "Virhe haussa")))}}] - ["/:id" {:get {:summary "Hae yksittäinen vuoden 2018 säännösten mukainen energiatodistus todistuksen tunnuksen perusteella" + ["/:id" {:get {:summary "Hae yksittäinen vuoden 2018 säännösten mukainen energiatodistus todistuksen tunnuksen perusteella json-muodossa" :parameters {:path {:id schema.common/Key}} :responses {200 {:body schema.energiatodistus/Energiatodistus2018} 404 {:body s/Str}} diff --git a/etp-backend/src/main/clj/solita/etp/handler.clj b/etp-backend/src/main/clj/solita/etp/handler.clj index 0aebe8fba..59bc8075b 100644 --- a/etp-backend/src/main/clj/solita/etp/handler.clj +++ b/etp-backend/src/main/clj/solita/etp/handler.clj @@ -180,17 +180,12 @@ :handler (openapi/create-openapi-handler)}}] (openapi-id "Palveluväylä" palveluvayla/routes)])]) -(def default-string-coercion-options-with-project-specific-ones - "Add more schemas that support coercion to default configuration in addition to those supported by schema coercion out of the box" - (assoc-in reitit.coercion.schema/default-options [:matchers :string :default] (some-fn (some-fn {schema.common/AcceptLanguage (schema.coerce/safe schema.common/parse-accept-language)}) - (get-in reitit.coercion.schema/default-options [:matchers :string :default])))) - (def route-opts {;; Uncomment line below to see diffs of requests in middleware chain ;;:reitit.middleware/transform dev/print-request-diffs :exception pretty/exception :validate rs/validate - :data {:coercion (reitit.coercion.schema/create default-string-coercion-options-with-project-specific-ones) + :data {:coercion reitit.coercion.schema/coercion :muuntaja m/instance :middleware [openapi/openapi-feature parameters/parameters-middleware diff --git a/etp-backend/src/main/clj/solita/etp/schema/common.clj b/etp-backend/src/main/clj/solita/etp/schema/common.clj index 501060932..5ee929fe1 100644 --- a/etp-backend/src/main/clj/solita/etp/schema/common.clj +++ b/etp-backend/src/main/clj/solita/etp/schema/common.clj @@ -1,5 +1,6 @@ (ns solita.etp.schema.common (:require [clojure.string :as str] + [schema-tools.core :as schema-tools] [schema-tools.walk :as walk] [solita.common.schema :as xschema] [schema.core :as schema])) @@ -198,24 +199,12 @@ (def Language (schema/enum "fi" "sv")) -(schema/defschema WeightedLocale - "A single locale with weight for Accept-Language header" - [(schema/one (schema/constrained schema/Str #(re-matches #"(?i)([*]|[a-z]{2,3})" %)) "lang") (schema/one (schema/constrained schema/Num #(and (>= % 0) (<= % 1))) "weight")]) - (schema/defschema AcceptLanguage "Define a schema for Accept-Language header. The header can contain multiple locales with preferred weights, for example Accept-Language: fr-CH, fr;q=0.9, en;q=0.8, de;q=0.7, *;q=0.5" - [WeightedLocale]) - -(defn parse-lang - "Parse a language from language tag i.e. drop subtags such as region separated by -" - [s] - (-> s (str/split #"-") first)) - -(defn parse-locale [s] - (let [parts (str/split s #";q=")] - (case (count parts) - 1 [(parse-lang s) 1.0] - 2 [(-> parts first parse-lang) (Double/parseDouble (second parts))]))) + (schema-tools/schema + ; Matches the docstring above. Case invariant (?i) list of languages (like fr or *), with optional region (like -CH) and optional weight (;q=0.9) separated by optional comma and optional whitespace. + (schema/constrained schema/Str #(re-matches #"(?i)(([*]|([a-z]{2,3}(-[a-z]{2,3})?))(;q=\d.\d)?,?\s?)+" %)) + {:openapi/description "Standardin mukainen Accept-Language otsikko. Jos otsikkoa ei ole asetettu, palautetaan ensisijaisesti suomenkielinen todistus" + :openapi/example "Accept-Language: fi-FI,sv;q=0.5"})) -(defn parse-accept-language [s] - (map parse-locale (map str/trim (str/split s #",")))) +(schema/defschema EnergiatodistusId (schema-tools/schema Key {:openapi/description "Energiatodistuksen tunniste"}))