Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Resources and Liberator

Marcin Kulik edited this pageJan 8, 2017 ·4 revisions

Resources

Compojure-api also allows http-endpoints to be modeled as data-driven resources, using enhancedRing-Swagger resource definitions. Resources might be good in the following cases:

  1. Wanting to add swagger-docs and/or schema-based coercion to your existing resource-based apis, like theLiberator.
  2. Generate endpoints based on external data, e.g.
  • generate REST or CRUD-apis from (database) entity definitions
  • generate RPC-apis from function/data definitions

Usage

Resources are created with functioncompojure.api.resource/resource, which is also imported in thecompojure.api.sweet namespace. Both request & response coercion can be disabled for resources, so that they can be used just to generate swagger-docs on top of existing/legacy apis.

Resources are routed withcontext.

(context"/hello" []:middleware [[require-role:admin]]  (resource    {:description"hello-resource":responses {200 {:schema {:message s/Str}}}:post {:summary"post-hello":parameters {:body-params {:name s/Str}}:handler (fnk [[:body-params name]]                       (ok {:message (format"hello, %s!" name)}))}:get {:summary"get-hello":parameters {:query-params {:name s/Str}}:handler (fnk [[:query-params name]]                      (ok {:message (format"hello, %s!" name)}))}}))

Source code

(defnresource"Creates a nested compojure-api Route from enhanced ring-swagger operations map and options.  By default, applies both request- and response-coercion based on those definitions.  Options:  - **:coercion**       A function from request->type->coercion-matcher, used                        in resource coercion for :body, :string and :response.                        Setting value to `(constantly nil)` disables both request- &                        response coercion. See tests and wiki for details.  Enhancements to ring-swagger operations map:  1) :parameters use ring request keys (query-params, path-params, ...) instead of  swagger-params (query, path, ...). This keeps things simple as ring keys are used in  the handler when destructuring the request.  2) at resource root, one can add any ring-swagger operation definitions, which will be  available for all operations, using the following rules:    2.1) :parameters are deep-merged into operation :parameters    2.2) :responses are merged into operation :responses (operation can fully override them)    2.3) all others (:produces, :consumes, :summary,...) are deep-merged by compojure-api  3) special key `:handler` either under operations or at top-level. Value should be a  ring-handler function, responsible for the actual request processing. Handler lookup  order is the following: operations-level, top-level.  4) request-coercion is applied once, using deep-merged parameters for a given  operation or resource-level if only resource-level handler is defined.  5) response-coercion is applied once, using merged responses for a given  operation or resource-level if only resource-level handler is defined.  Note: Swagger operations are generated only from declared operations (:get, :post, ..),  despite the top-level handler could process more operations.  Example:  (resource    {:parameters {:query-params {:x Long}}     :responses {500 {:schema {:reason s/Str}}}     :get {:parameters {:query-params {:y Long}}           :responses {200 {:schema {:total Long}}}           :handler (fn [request]                      (ok {:total (+ (-> request :query-params :x)                                     (-> request :query-params :y))}))}     :post {}     :handler (constantly                (internal-server-error {:reason\"not implemented\"}))})"  ([info]   (resource info {}))  ([info options]   (let [info (merge-parameters-and-responses info)         root-info (swaggerize (root-info info))         childs (create-childs info)         handler (create-handler info options)]     (routes/createnilnil root-info childs handler))))

More examples

Hello World

(resource  {:handler (constantly (ok"hello world"))})

Shared parameters, more swagger-info & a fallback-handler

(resource  {:description"shared description, can be overridden":parameters {:path-params {:id Long}}:get {:description"get user":summary"get-user ftw!":handler get-user}:put {:parameters {:body-params User}:responses {200 {:schema User}}:handler modify-user}:delete {:description"delete's a user":handler delete-user}:handler (constantly              (internal-server-error                {:reason"other methods not implemented"}))})

Integrated with routing

Inlined (as a closure):

(context"/plus" []:middleware [require-admin]  (resource    {:get {:parameters {:query-params {:x Long,:y Long}}:responses {200 {:schema {:total Long}}}:handler my-plus-request-handler-with-coerced-inputs-and-outputs}}))

Predefined (bit faster):

(defplus-resource  (resource    {:get {:parameters {:query-params {:x Long,:y Long}}:responses {200 {:schema {:total Long}}}:handler my-plus-request-handler-with-coerced-inputs-and-outputs}}))(context"/plus" []:middleware [require-admin]  plus-resource)

More examples

Integration with Liberator

  • set the Liberator resource as top-level handler
  • return raw responses to enable response coercion via:as-response orring-response, see theguide
  • read the coerced parameters from the liberator context:(get-in ctx [:request :body-parameters])
  • optionally disable coercion on resource just to get just swagger-docs
(defuser-resource  (resource    {:parameters {:path-params {:id Long}}:get {:parameters {:query-params {(s/optional-key:fields) [String]}}:responses {200 {:schema User}}:summary"returns a User (or fields of it)"}:put {:parameters {:body-params User}:responses {200 {:schema User}}:summary"Updates a user"}:delete {:summary"Deletes a user"}:handler my-liberator-resource};; add this if you just want the swagger-docs    {:coercion (constantlynil)}))(context"/user" []  user-resource)

Feel free to update this guide. Initial discussionhere.

Clone this wiki locally

[8]ページ先頭

©2009-2025 Movatter.jp