oliyh / martian

The HTTP abstraction library for Clojure/script, supporting OpenAPI, Swagger, Schema, re-frame and more
MIT License
525 stars 42 forks source link

Route-level params and $ref params are ignored #112

Closed onetom closed 2 years ago

onetom commented 3 years ago

Given the following schema excerpt (taken from https://raw.githubusercontent.com/XeroAPI/Xero-OpenAPI/master/xero_accounting.yaml):

paths:
  '/Reports/ProfitAndLoss':
    parameters:
      - $ref: '#/components/parameters/requiredHeader'
    get:
      security:
        - OAuth2: [accounting.reports.read]
      tags:
        - Accounting
      operationId: getReportProfitAndLoss
      summary: Retrieves report for profit and loss
      parameters:
        - $ref: '#/components/parameters/FromDate'
        - $ref: '#/components/parameters/ToDate'
        # ...
# ...
components:
  parameters:
    requiredHeader:
      in: header
      name: xero-tenant-id
      x-snake: xero_tenant_id
      description: Xero identifier for Tenant
      example: YOUR_XERO_TENANT_ID
      schema:
        type: string
      required: true
# ...

When I look at the handlers compiled from it with

(def xero-api
  (->> "xero_accounting.json" slurp clojure.data.json/read-str
       (martian/bootstrap-openapi "https://api.xero.com/api.xro/2.0"))

  (->> xero-api :handlers
       (filter #(-> % :route-name (= :get-report-profit-and-loss))))

I get the following API definition:

({:description nil,
  :method :get,
  :produces [],
  :path-schema {},
  :query-schema {#schema.core.OptionalKey{:k :periods} Int,
                 #schema.core.OptionalKey{:k :timeframe} (enum "YEAR" "MONTH" "QUARTER"),
                 #schema.core.OptionalKey{:k :trackingCategoryID} java.lang.String,
                 #schema.core.OptionalKey{:k :trackingCategoryID2} java.lang.String,
                 #schema.core.OptionalKey{:k :trackingOptionID} java.lang.String,
                 #schema.core.OptionalKey{:k :trackingOptionID2} java.lang.String,
                 #schema.core.OptionalKey{:k :standardLayout} java.lang.Boolean,
                 #schema.core.OptionalKey{:k :paymentsOnly} java.lang.Boolean},
  :parameter-aliases {:periods :periods,
                      :timeframe :timeframe,
                      :tracking-category-id :trackingCategoryID,
                      :tracking-category-id-2 :trackingCategoryID2,
                      :tracking-option-id :trackingOptionID,
                      :tracking-option-id-2 :trackingOptionID2,
                      :standard-layout :standardLayout,
                      :payments-only :paymentsOnly},
  :form-schema {},
  :path-parts ["/Reports/ProfitAndLoss"],
  :headers-schema {},
  :openapi-definition {:operationId "getReportProfitAndLoss",
                       :parameters [{:$ref "#/components/parameters/FromDate"}
                                    {:$ref "#/components/parameters/ToDate"}
                                    ,,,
                                    {:description "Return cash only basis for the ProfitAndLoss report",
                                     :example "false",
                                     :in "query",
                                     :name "paymentsOnly",
                                     :schema {:type "boolean"},
                                     :x-snake "payments_only"}],
                       :responses {:200 {:content #:application{:json {:schema {:$ref "#/components/schemas/ReportWithRows"}}},
                                         :description "Success - return response of type ReportWithRows"}},
                       :security [{:OAuth2 ["accounting.reports.read"]}],
                       :summary "Retrieves report for profit and loss",
                       :tags ["Accounting"]},
  :consumes [nil],
  :summary "Retrieves report for profit and loss",
  :body-schema nil,
  :route-name :get-report-profit-and-loss,
  :response-schemas [{:status (eq 200), :body nil}]})

I was expecting the :xero-tenant-id parameter to be handled, but it's missing from the :query-schema, :parameter-aliases and [:openapi-definition :parameters], so it's simply omitted from the response:

  (martian/request-for
    xero-api :get-report-profit-and-loss
    {:paymentsOnly   true
     :xero-tenant-id "b05477b3-f02c-4cbb-ad62-87edcd42b095"})

returns

{:method :get,
 :url "https://api.xero.com/api.xro/2.0/Reports/ProfitAndLoss",
 :query-params {:paymentsOnly true},
 :as :text,
 :headers {"Accept" "application/json"}}

and the :xero-tenant-id is nowhere to be seen.

oliyh commented 3 years ago

Hello,

Thanks for reporting this, it does indeed seem to be a big, I'll look into it.

Cheers

onetom commented 3 years ago

I'm not sure how to automatically link it to this issue, but I've opened a draft PR: https://github.com/oliyh/martian/pull/113 Not tests yet and only 1-level of indirection is resolved. Next feature would be to merge the route-level params into the method-level params.

oliyh commented 2 years ago

I've pushed 0.1.21-SNAPSHOT with this feature, if you could test and let me know that would be very helpful, thanks.