Fork me on GitHub
#ring-swagger
<
2017-04-20
>
ikitommi08:04:53

@giaosudau hi, you can mount a middleware that does the caching. Somethig like:

(context "/db" []
  :middleware [my-cache-mw]
  ...

giaosudau12:04:43

@ikitommi can you recommend some cache libs that related? I just start clojure for 2 weeks. Still learning the language.

ikitommi12:04:14

@giaosudau welcome to clojure! I invited you to the ring channel too, mr. Reeves (creator of Ring) hangs out there, might be a good place for tips too. There is a big list of useful libs in https://www.clojure-toolbox.com/, I think we have rolled custom caching mw for projects that need those so not sure what is most relevant existing mw for that.

ikitommi13:04:03

Also, you might want to look at the Luminus template, which has good production settings (including mw) and uses compojure-api, something like lein new luminus swag +swagger. It has great docs too.

victor.andree13:04:27

i’m building an API with compojure-api where it’s a requirement that JSON responses are wrapped in a { body: { ... }, statusCode: 200, metadata: {} } structure. im new to clojure as a whole and cant quite figure out if i can put some middleware around compojure-api to easily do this? statusCode is the HTTP status code… any ideas?

sb17:04:42

I created a repo on github with http-kit , because lot of cases.. I read can’t compile with java.. so here is: https://github.com/damesek/swagger-http-kit-compojure-api

sb17:04:32

that work on http-kit.. with compojure-api etc.. if that is helpful for somebody..

juhoteperi17:04:32

@sb arttu's example you link to is 3 years old, the AOT problems have been most probably fixed in 1.0 or even before that

sb17:04:31

@juhoteperi yes, but I found just this repo and similar comments, therefore I dropped out.. my repo or maybe good to drop to official site a similar repo

sb17:04:05

(I’m not expert, I created for similar beginners)

plins17:04:54

good evening @ikitommi, regarding the issue about protecting the docs with custom validation, I've encountered another problem. here is the code i'm running

(defn authorized-for-docs? [handler]
  (fn [request]
    (if (= "42"
           (get (:query-params request) "secret"))
      (handler request)
      (res/forbidden
       {:error "'secret' query parameter is invalid"}))))


(def app
  (ring/api


   (ring/context "/docs" req
     :middleware [authorized-for-docs?]
     (docs/swagger-routes
       {:ui "/"
        :options {:ui {:swagger-docs "/docs/swagger.json"}}
        :spec "/swagger.json"
        :data {:info
               {:title " ... "
                :description "..."}}}))
the underlying issue is that when i hit /docs the browser redirects to /docs/index.html, but the second request lacks the auth param in the querystring so it gets blocked am I doing something wrong?

ikitommi18:04:30

@plins yes, the query-parameters are not copied to the redirect. Same will be for the /docs/swagger.json that the UI will be asking as a separate query to get the actual spec - it will not have the query parameter. I think you should use something that the server sends for all requests - like basic-auth or session auth.

ikitommi18:04:45

@victor.andree if you want to get the wrapped responses also to swagger docs, you have to modify both schemas and responses.

ikitommi18:04:58

I think with the data-driven resource you could do that in more generic way.

ikitommi18:04:23

with normal endpoints, something like:

(defn wrapped [schema]
  {:status Long, :body schema :meta {s/Any s/Any}})

(defn wrap [response meta]
  (let [body (-> response
                 (select-keys [:status :body])
                 (assoc :meta meta))]
    (assoc response :body body)))

(s/defschema User {:name String})

(def app
  (api
    {:swagger
     {:ui "/"
      :spec "/swagger.json"}}

    (POST "/echo" []
      :return (wrapped User)
      :body [user User]
      (wrap (ok user) {:some "meta"}))))

ikitommi18:04:52

(If I understood what you are trying to do).

ikitommi18:04:28

that returns data in:

{
  "status": 200,
  "body": {
    "name": "string"
  },
  "meta": {
    "some": "meta"
  }
}

ikitommi18:04:34

that’s the body.

victor.andree18:04:48

i was trying to find a way to do this in one place — all non-error responses should basically have this structure. so i started looking into restructuring the meta :return — but that doesn’t take care of wrapping the normal response.

plins19:04:53

@ikitommi, ive successfully managed to protect the docs with basic auth, and i'd like to post a snippet on the wiki for n00bs like me. here is what ive managed to do

(defn authorized-for-docs? [handler]
   (fn [request]
     (let [auth-header (get (:headers request) "authorization")]
       (prn auth-header)
       (cond
         (nil? auth-header)
         (-> (res/unauthorized)
             (res/header "WWW-Authenticate" "Basic realm=\"whattever\""))

         (= auth-header (:auth-secret-docs cfg))
         (handler request)

         :else
         (res/unauthorized
          {:error "header 'authorization' inválido"})))))


(def app
  (ring/api


   (ring/context "/docs" req
     :middleware [authorized-for-docs?]
     (docs/swagger-routes
       {:ui "/"
        :options {:ui {:swagger-docs "/docs/swagger.json"}}
        :spec "/swagger.json"
        :data {:info
               {:title "Title ..."
                :description "Foo Bar"}}}))

plins19:04:57

its ok to serve as an example? it could be improved or be more succinct?

mtkp19:04:19

thats pretty neat @plins . if its just an example, could probably simplify the authorized-for-docs? fn...

plins19:04:02

ok, great! i will simplify things a bit and post it on the wiki, thanks for the clarification!