Fork me on GitHub
#pedestal
<
2023-02-08
>
Jacob Molin10:02:33

Hi! I'm trying to host a swagger-ui on a pedestal route which depends on manually written documentation, i.e. a swagger.json file. I've looked at https://github.com/frankiesardo/route-swagger/blob/8ebab45d03cb43fdec323b955f5ae4c152814d39/src/route_swagger/interceptor.clj and I've gotten it to work by autogenerating the swagger.json file as described in route-swagger. However, I haven't figured out how I can make it depend on a manually written swagger.json file that I've hosted myself on a different endpoint (I've solved the hosting of a manually written swagger.json). I've also looked at using the https://github.com/metosin/ring-swagger-ui directly to wrap the swagger-ui middleware in a Pedestal interceptor, but haven't succeded. This would be my preferred method, if possible. Anyone got any suggestions? And please let me know if something's unclear or there's an even better way! Here's an example of what I would like to achieve in building the Pedestal routes table:

(ns nice.nm
  (:require [cheshire.core :as json]
            [ring.swagger.swagger-ui :refer :all]
            [ring.swagger.swagger-ui/swagger-ui]))

(def swagger-json
  {:name ::swagger-json-interceptor
   :enter (fn [context]
            (assoc context :response {:status  200
                                      :headers {"Content-Type" "application/json; charset=utf-8"}
                                      :body (cheshire.core/parse-string (slurp "<path-to-dir>/swagger.json"))}))})

(def swagger-ui
  {:name ::swagger-ui-interceptor
   :enter (fn [context]
            (ring.swagger.swagger-ui/swagger-ui {:path "/test"
                                                 :swagger-docs "/applications/api/v1/swagger-json-static"}))})

(defn routes
  []
  #{["/endpoint1"
     :post [interceptor1
            endpoint1-handler]
     :route-name :endpoint1]
    ["/endpoint2"
     :get [endpoint2]
     :route-name :endpoint2] 
    ["/manually-written-swagger.json"
       :get [swagger-json]
       :route-name :swagger-json]
    ["/swagger-ui"
       :get [swagger-ui]
       :route-name :swagger-ui]})

popeye14:02:38

@U04GATKRD35, even I am trying to do it now, one thing is swagger-json is not creating an interceptor, it supposed to bound between (interceptor/interceptor right ?

popeye14:02:08

may be I am wrong! I am trying it first time

Jacob Molin12:03:39

You're right!

Jacob Molin12:03:45

In the end I actually just used the Swagger-UI as a static resource by placing the content of the Swagger-UI /dist folder in the "resources/public" directory in my project, as explained in the https://github.com/swagger-api/swagger-ui#general (last line in General section: "If you are looking for plain ol' HTML/JS/CSS, https://github.com/swagger-api/swagger-ui/releases/latest and copy the contents of the /dist folder to your server."). You can read about static routes in Pedestal http://pedestal.io/cookbook/index#_how_to_serve_static_resources.

h0bbit16:11:53

Thanks for the instructions @U04GATKRD35, I went down this route as well. Adding one more change I needed to make to get everything working: I added

::http/secure-headers
{:content-security-policy-settings "object-src 'none'; script-src 'self' 'unsafe-inline' 'unsafe-eval' https: http:;"}
to the service map, because the browser refused to load
<script src="./swagger-ui-bundle.js" charset="UTF-8"> </script>
    <script src="./swagger-ui-standalone-preset.js" charset="UTF-8"> </script>
    <script src="./swagger-initializer.js" charset="UTF-8"> </script>
in /dist/index.html due to the default Content Security Policy. What I’ve changed in content-security-policy-settings is adding 'self' in script-src. Everything else is the default.