1+ // Package filter provides functionality to filter OpenAPI specs based
2+ // on config. It allows filtering of paths, methods, components,
3+ // and other OpenAPI elements while maintaining the integrity of the spec.
14package filter
25
36import (
@@ -10,14 +13,18 @@ import (
1013 "github.com/zguydev/openapi-filter/internal/config"
1114)
1215
16+ // OpenAPISpecFilter is the main type that handles filtering of OpenAPI specs.
1317type OpenAPISpecFilter struct {
14- cfg * config.FilterConfig
15- logger * zap.Logger
16- loader * openapi3.Loader
18+ cfg * config.FilterConfig
19+ logger * zap.Logger
20+ loader * openapi3.Loader
21+ collector * RefsCollector
1722
18- filtered , doc * openapi3.T
23+ doc , filtered * openapi3.T
1924}
2025
26+ // NewOpenAPISpecFilter creates a new OpenAPISpecFilter instance with the
27+ // provided configuration and logger. It initializes the OpenAPI loader.
2128func NewOpenAPISpecFilter (
2229 cfg * config.Config ,
2330 logger * zap.Logger ,
@@ -28,12 +35,23 @@ func NewOpenAPISpecFilter(
2835 }
2936
3037 return & OpenAPISpecFilter {
31- cfg : & cfg .FilterConfig ,
32- logger : logger ,
33- loader : loader ,
38+ cfg : & cfg .FilterConfig ,
39+ logger : logger ,
40+ loader : loader ,
41+ collector : NewRefsCollector (),
3442 }
3543}
3644
45+ // Filter processes an OpenAPI spec file according to the configured
46+ // filters and writes the filtered result to the specified output path.
47+ // It handles loading, filtering, and writing of the spec while
48+ // maintaining all necessary references and components.
49+ //
50+ // Parameters:
51+ // - inputSpecPath: Path to the input OpenAPI spec file
52+ // - outSpecPath: Path where the filtered spec will be written
53+ //
54+ // Returns an error if any step of the filtering process fails.
3755func (oaf * OpenAPISpecFilter ) Filter (inputSpecPath , outSpecPath string ) error {
3856 var err error
3957 oaf .doc , err = loadSpecFromFile (oaf .loader , inputSpecPath )
@@ -49,11 +67,10 @@ func (oaf *OpenAPISpecFilter) Filter(inputSpecPath, outSpecPath string) error {
4967 Paths : & openapi3.Paths {},
5068 }
5169
52- collector := NewRefsCollector ()
53-
54- oaf .filterPaths (collector )
70+ oaf .filterPaths ()
5571 oaf .filterComponents ()
5672 oaf .filterOther ()
73+ oaf .filterRefs ()
5774 if isEmptyComponents (oaf .filtered .Components ) {
5875 oaf .filtered .Components = nil
5976 }
@@ -67,7 +84,10 @@ func (oaf *OpenAPISpecFilter) Filter(inputSpecPath, outSpecPath string) error {
6784 return nil
6885}
6986
70- func (oaf * OpenAPISpecFilter ) filterPaths (collector * RefsCollector ) {
87+ // filterPaths processes the paths specified in the configuration and filters them
88+ // according to the allowed methods. It also collects all references used in the
89+ // filtered paths.
90+ func (oaf * OpenAPISpecFilter ) filterPaths () {
7191 for path , methods := range oaf .cfg .Paths {
7292 pathItem := oaf .doc .Paths .Find (path )
7393 if pathItem == nil {
@@ -80,37 +100,41 @@ func (oaf *OpenAPISpecFilter) filterPaths(collector *RefsCollector) {
80100 op := oaf .getOperation (pathItem , method , path )
81101 if op == nil {
82102 oaf .logger .Warn ("method not exists for specified path" ,
83- zap .String ("path " , path ),
84- zap .String ("method " , method ))
103+ zap .String ("method " , method ),
104+ zap .String ("path " , path ))
85105 continue
86106 }
87107 if ! oaf .setOperation (newPathItem , method , path , op ) {
88108 continue
89109 }
90- collector .CollectOperation (op )
110+ oaf . collector .CollectOperation (op )
91111 }
92112
93113 oaf .filtered .Paths .Set (path , newPathItem )
94114 }
95-
96- oaf .filterRefs (collector .Refs ())
97115}
98116
117+ // getOperation safely retrieves an operation from a PathItem for the specified
118+ // method. It handles unknown HTTP methods gracefully and returns nil if the
119+ // method is invalid.
99120func (oaf * OpenAPISpecFilter ) getOperation (
100121 p * openapi3.PathItem ,
101122 method , path string ,
102123) (op * openapi3.Operation ) {
103124 defer func () {
104125 if r := recover (); r != nil {
105126 oaf .logger .Warn ("unknown HTTP method in filter config" ,
106- zap .String ("path " , path ),
107- zap .String ("method " , method ))
127+ zap .String ("method " , method ),
128+ zap .String ("path " , path ))
108129 op = nil
109130 }
110131 }()
111132 return p .GetOperation (strings .ToUpper (method ))
112133}
113134
135+ // setOperation safely sets an operation in a PathItem for the specified method.
136+ // It handles unknown HTTP methods gracefully and returns false if the method
137+ // is invalid.
114138func (oaf * OpenAPISpecFilter ) setOperation (
115139 p * openapi3.PathItem ,
116140 method , path string ,
@@ -119,21 +143,25 @@ func (oaf *OpenAPISpecFilter) setOperation(
119143 defer func () {
120144 if r := recover (); r != nil {
121145 oaf .logger .Warn ("unknown HTTP method in spec" ,
122- zap .String ("path " , path ),
123- zap .String ("method " , method ))
146+ zap .String ("method " , method ),
147+ zap .String ("path " , path ))
124148 ok = false
125149 }
126150 }()
127151 p .SetOperation (strings .ToUpper (method ), operation )
128152 return true
129153}
130154
131- func (oaf * OpenAPISpecFilter ) filterRefs (refs map [string ]struct {}) {
132- for ref := range refs {
155+ // filterRefs processes all collected references and ensures they are properly
156+ // included in the filtered spec.
157+ func (oaf * OpenAPISpecFilter ) filterRefs () {
158+ for ref := range oaf .collector .refs {
133159 oaf .filterRef (ref )
134160 }
135161}
136162
163+ // filterRef processes a single reference and copies the referenced component
164+ // to the filtered spec.
137165func (oaf * OpenAPISpecFilter ) filterRef (ref string ) {
138166 if oaf .doc .Components == nil {
139167 return
@@ -148,39 +176,49 @@ func (oaf *OpenAPISpecFilter) filterRef(ref string) {
148176 compType , ok := ComponentDefToType (def )
149177 if ! ok {
150178 oaf .logger .Warn ("unknown component definition" ,
151- zap .String ("def" , def ), zap .String ("ref" , ref ))
179+ zap .String ("def" , def ),
180+ zap .String ("name" , name ),
181+ zap .String ("ref" , ref ))
152182 return
153183 }
154- if ! processCopyComponent (
155- oaf .doc .Components ,
184+ if ! processCopyComponent (oaf .doc .Components ,
156185 oaf .filtered .Components ,
157- compType , name ) {
186+ compType ,
187+ name ,
188+ ) {
158189 oaf .logger .Warn ("component not found" ,
159- zap .String ("name" , name ),
160190 zap .String ("def" , def ),
191+ zap .String ("name" , name ),
161192 zap .String ("ref" , ref ))
162193 }
163194}
164195
196+ // filterComponents processes all components specified in the configuration and
197+ // copies them to the filtered spec.
165198func (oaf * OpenAPISpecFilter ) filterComponents () {
166199 if oaf .cfg .Components == nil || oaf .doc .Components == nil {
167200 return
168201 }
169202
170203 for _ , compTyp := range ComponentTypes () {
171204 for _ , name := range ComponentTypeToCfgNames (oaf .cfg .Components , compTyp ) {
172- if ! processCopyComponent (
173- oaf .doc .Components ,
205+ if ! processCopyComponent (oaf .doc .Components ,
174206 oaf .filtered .Components ,
175- compTyp , name ) {
207+ compTyp ,
208+ name ,
209+ ) {
176210 oaf .logger .Warn ("component not found" ,
177- zap .String ("name" , name ),
178- zap .String ("def" , ComponentTypeToDef (compTyp )))
211+ zap .String ("def" , ComponentTypeToDef (compTyp )),
212+ zap .String ("name" , name ))
213+ continue
179214 }
215+ CollectComponent (oaf .collector , oaf .doc .Components , compTyp , name )
180216 }
181217 }
182218}
183219
220+ // filterOther processes additional OpenAPI elements specified in the configuration,
221+ // including servers, security requirements, tags, and external documentation.
184222func (oaf * OpenAPISpecFilter ) filterOther () {
185223 if oaf .cfg .Servers {
186224 oaf .filtered .Servers = oaf .doc .Servers
0 commit comments