• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

UiPath / uipathcli / 6442892572

07 Oct 2023 06:45PM UTC coverage: 67.119% (-23.3%) from 90.418%
6442892572

push

github

thschmitt
Upgrade to golang 1.21, update dependencies to latest versions

- Upgrade to golang 1.21
- Update all dependencies to latest versions

3068 of 4571 relevant lines covered (67.12%)

362.28 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

86.1
/parser/openapi_parser.go
1
package parser
2

3
import (
4
        "fmt"
5
        "net/url"
6
        "strings"
7

8
        "github.com/getkin/kin-openapi/openapi3"
9
)
10

11
const DefaultServerBaseUrl = "https://cloud.uipath.com"
12
const RawBodyParameterName = "$file"
13
const CustomParameterNameExtension = "x-name"
14

15
// The OpenApiParser parses OpenAPI (2.x and 3.x) specifications.
16
// It creates the Definition structure with all the information about the available
17
// operations and their parameters for the given service specification.
18
type OpenApiParser struct{}
19

20
func (p OpenApiParser) customParameterName(extensions map[string]interface{}) string {
7,469✔
21
        name := extensions[CustomParameterNameExtension]
7,469✔
22
        switch v := name.(type) {
7,469✔
23
        case string:
444✔
24
                return v
444✔
25
        default:
7,025✔
26
                return ""
7,025✔
27
        }
28
}
29

30
func (p OpenApiParser) contains(strs []string, str string) bool {
4,393✔
31
        for _, s := range strs {
8,286✔
32
                if s == str {
4,331✔
33
                        return true
438✔
34
                }
438✔
35
        }
36
        return false
3,955✔
37
}
38

39
func (p OpenApiParser) getDescription(document openapi3.T) string {
42✔
40
        if document.Info == nil {
81✔
41
                return ""
39✔
42
        }
39✔
43
        if document.Info.Description != "" {
6✔
44
                return document.Info.Description
3✔
45
        }
3✔
46
        return document.Info.Title
×
47
}
48

49
func (p OpenApiParser) getUri(document openapi3.T) (*url.URL, error) {
42✔
50
        server := DefaultServerBaseUrl
42✔
51
        if len(document.Servers) > 0 {
53✔
52
                server = document.Servers[0].URL
11✔
53
        }
11✔
54
        return url.Parse(server)
42✔
55
}
56

57
func (p OpenApiParser) formatName(name string) string {
9,215✔
58
        name = strings.ReplaceAll(name, "$", "")
9,215✔
59
        name = strings.ReplaceAll(name, "/", "-")
9,215✔
60
        name = strings.ReplaceAll(name, "_", "-")
9,215✔
61
        name = toSnakeCase(name)
9,215✔
62
        return strings.ToLower(name)
9,215✔
63
}
9,215✔
64

65
func (p OpenApiParser) getName(method string, route string, category *OperationCategory, operation openapi3.Operation) string {
880✔
66
        name := method + route
880✔
67
        if operation.OperationID != "" {
1,760✔
68
                name = operation.OperationID
880✔
69
        }
880✔
70
        name = p.formatName(name)
880✔
71
        if category != nil {
1,746✔
72
                name = strings.TrimPrefix(name, category.Name+"-")
866✔
73
        }
866✔
74
        return name
880✔
75
}
76

77
func (p OpenApiParser) getSchemaType(schema openapi3.Schema) string {
7,463✔
78
        if schema.Type == openapi3.TypeArray {
7,845✔
79
                itemType := schema.Items.Value.Type
382✔
80
                switch itemType {
382✔
81
                case openapi3.TypeBoolean:
×
82
                        return ParameterTypeBooleanArray
×
83
                case openapi3.TypeInteger:
92✔
84
                        return ParameterTypeIntegerArray
92✔
85
                case openapi3.TypeNumber:
×
86
                        return ParameterTypeNumberArray
×
87
                case openapi3.TypeObject:
219✔
88
                        return ParameterTypeObjectArray
219✔
89
                default:
71✔
90
                        return ParameterTypeStringArray
71✔
91
                }
92
        }
93

94
        switch schema.Type {
7,081✔
95
        case openapi3.TypeBoolean:
744✔
96
                return ParameterTypeBoolean
744✔
97
        case openapi3.TypeInteger:
2,220✔
98
                return ParameterTypeInteger
2,220✔
99
        case openapi3.TypeNumber:
10✔
100
                return ParameterTypeNumber
10✔
101
        case openapi3.TypeObject:
239✔
102
                return ParameterTypeObject
239✔
103
        default:
3,868✔
104
                if schema.Format == "binary" {
3,917✔
105
                        return ParameterTypeBinary
49✔
106
                }
49✔
107
                return ParameterTypeString
3,819✔
108
        }
109
}
110

111
func (p OpenApiParser) getType(schemaRef *openapi3.SchemaRef) string {
7,469✔
112
        if schemaRef == nil {
7,475✔
113
                return ParameterTypeString
6✔
114
        }
6✔
115
        return p.getSchemaType(*schemaRef.Value)
7,463✔
116
}
117

118
func (p OpenApiParser) parseSchema(fieldName string, schemaRef *openapi3.SchemaRef, in string, requiredFieldnames []string, visitedSchemas map[*openapi3.SchemaRef]bool) *Parameter {
4,719✔
119
        _, visited := visitedSchemas[schemaRef]
4,719✔
120
        if visited {
5,045✔
121
                return nil
326✔
122
        }
326✔
123
        visitedSchemas[schemaRef] = true
4,393✔
124

4,393✔
125
        name := p.formatName(fieldName)
4,393✔
126
        _type := p.getType(schemaRef)
4,393✔
127
        required := p.contains(requiredFieldnames, fieldName)
4,393✔
128
        parameters := []Parameter{}
4,393✔
129
        description := ""
4,393✔
130
        var defaultValue interface{}
4,393✔
131
        var allowedValues []interface{}
4,393✔
132
        if schemaRef != nil {
8,786✔
133
                customName := p.customParameterName(schemaRef.Value.Extensions)
4,393✔
134
                if customName != "" {
4,393✔
135
                        name = customName
×
136
                }
×
137
                description = schemaRef.Value.Description
4,393✔
138
                defaultValue = p.getDefaultValue(schemaRef.Value)
4,393✔
139
                allowedValues = p.getAllowedValues(schemaRef.Value)
4,393✔
140
                if required && defaultValue == nil && len(allowedValues) == 1 {
4,393✔
141
                        defaultValue = allowedValues[0]
×
142
                }
×
143
                propertiesSchemas := p.getPropertiesSchemas(schemaRef.Value)
4,393✔
144
                parameters = p.parseSchemas(propertiesSchemas, in, schemaRef.Value.Required, visitedSchemas)
4,393✔
145
        }
146
        return NewParameter(name, _type, description, in, fieldName, required, defaultValue, allowedValues, parameters)
4,393✔
147
}
148

149
func (p OpenApiParser) parseSchemas(schemas openapi3.Schemas, in string, requiredFieldnames []string, visitedSchemas map[*openapi3.SchemaRef]bool) []Parameter {
7,810✔
150
        result := []Parameter{}
7,810✔
151
        for fieldName, schemaRef := range schemas {
12,529✔
152
                parsed := p.parseSchema(fieldName, schemaRef, in, requiredFieldnames, visitedSchemas)
4,719✔
153
                if parsed != nil {
9,112✔
154
                        result = append(result, *parsed)
4,393✔
155
                }
4,393✔
156
        }
157
        return result
7,810✔
158
}
159

160
func (p OpenApiParser) getDefaultValue(schema *openapi3.Schema) interface{} {
7,463✔
161
        if schema.Default != nil {
7,541✔
162
                return schema.Default
78✔
163
        }
78✔
164
        for _, s := range schema.AllOf {
7,385✔
165
                if s.Value.Default != nil {
×
166
                        return s.Value.Default
×
167
                }
×
168
        }
169
        return nil
7,385✔
170
}
171

172
func (p OpenApiParser) getAllowedValues(schema *openapi3.Schema) []interface{} {
7,463✔
173
        result := []interface{}{}
7,463✔
174
        result = append(result, schema.Enum...)
7,463✔
175
        for _, s := range schema.AllOf {
7,463✔
176
                result = append(result, s.Value.Enum...)
×
177
        }
×
178
        return result
7,463✔
179
}
180

181
func (p OpenApiParser) getPropertiesSchemas(schema *openapi3.Schema) openapi3.Schemas {
7,810✔
182
        result := openapi3.Schemas{}
7,810✔
183
        for n, p := range schema.Properties {
11,186✔
184
                result[n] = p
3,376✔
185
        }
3,376✔
186
        for _, s := range schema.AllOf {
7,810✔
187
                for n, p := range s.Value.Properties {
×
188
                        result[n] = p
×
189
                }
×
190
        }
191
        itemsSchemas := p.getItemsPropertiesSchemas(schema)
7,810✔
192
        for n, p := range itemsSchemas {
9,153✔
193
                result[n] = p
1,343✔
194
        }
1,343✔
195
        return result
7,810✔
196
}
197

198
func (p OpenApiParser) getItemsPropertiesSchemas(schema *openapi3.Schema) openapi3.Schemas {
7,810✔
199
        result := openapi3.Schemas{}
7,810✔
200
        if schema.Items != nil {
8,196✔
201
                for n, p := range schema.Items.Value.Properties {
1,729✔
202
                        result[n] = p
1,343✔
203
                }
1,343✔
204
        }
205
        for _, s := range schema.AllOf {
7,810✔
206
                if s.Value.Items != nil {
×
207
                        for n, p := range s.Value.Items.Value.Properties {
×
208
                                result[n] = p
×
209
                        }
×
210
                }
211
        }
212
        return result
7,810✔
213
}
214

215
func (p OpenApiParser) parseRequestBodyParameters(requestBody *openapi3.RequestBodyRef) (string, []Parameter) {
880✔
216
        parameters := []Parameter{}
880✔
217
        if requestBody == nil {
1,413✔
218
                return "", parameters
533✔
219
        }
533✔
220
        content := requestBody.Value.Content.Get("application/json")
347✔
221
        if content != nil {
681✔
222
                propertiesSchemas := p.getPropertiesSchemas(content.Schema.Value)
334✔
223
                return "application/json", p.parseSchemas(propertiesSchemas, ParameterInBody, content.Schema.Value.Required, map[*openapi3.SchemaRef]bool{})
334✔
224
        }
334✔
225
        content = requestBody.Value.Content.Get("application/x-www-form-urlencoded")
13✔
226
        if content != nil {
13✔
227
                propertiesSchemas := p.getPropertiesSchemas(content.Schema.Value)
×
228
                return "application/x-www-form-urlencoded", p.parseSchemas(propertiesSchemas, ParameterInBody, content.Schema.Value.Required, map[*openapi3.SchemaRef]bool{})
×
229
        }
×
230
        content = requestBody.Value.Content.Get("multipart/form-data")
13✔
231
        if content != nil {
26✔
232
                propertiesSchemas := p.getPropertiesSchemas(content.Schema.Value)
13✔
233
                return "multipart/form-data", p.parseSchemas(propertiesSchemas, ParameterInForm, content.Schema.Value.Required, map[*openapi3.SchemaRef]bool{})
13✔
234
        }
13✔
235
        content = requestBody.Value.Content.Get("application/octet-stream")
×
236
        if content != nil {
×
237
                parameter := p.parseSchema(RawBodyParameterName, content.Schema, ParameterInBody, []string{RawBodyParameterName}, map[*openapi3.SchemaRef]bool{})
×
238
                return "application/octet-stream", []Parameter{*parameter}
×
239
        }
×
240
        return "", parameters
×
241
}
242

243
func (p OpenApiParser) parseParameter(param openapi3.Parameter) Parameter {
3,076✔
244
        fieldName := param.Name
3,076✔
245
        name := p.formatName(fieldName)
3,076✔
246
        customName := p.customParameterName(param.Extensions)
3,076✔
247
        if customName != "" {
3,520✔
248
                name = customName
444✔
249
        }
444✔
250
        _type := p.getType(param.Schema)
3,076✔
251
        required := param.Required
3,076✔
252
        parameters := []Parameter{}
3,076✔
253
        var defaultValue interface{}
3,076✔
254
        var allowedValues []interface{}
3,076✔
255
        if param.Schema != nil {
6,146✔
256
                defaultValue = p.getDefaultValue(param.Schema.Value)
3,070✔
257
                allowedValues = p.getAllowedValues(param.Schema.Value)
3,070✔
258
                if required && defaultValue == nil && len(allowedValues) == 1 {
3,090✔
259
                        defaultValue = allowedValues[0]
20✔
260
                }
20✔
261
                propertiesSchemas := p.getPropertiesSchemas(param.Schema.Value)
3,070✔
262
                parameters = p.parseSchemas(propertiesSchemas, param.In, param.Schema.Value.Required, map[*openapi3.SchemaRef]bool{})
3,070✔
263
        }
264
        return *NewParameter(name, _type, param.Description, param.In, fieldName, required, defaultValue, allowedValues, parameters)
3,076✔
265
}
266

267
func (p OpenApiParser) parseParameters(params openapi3.Parameters) []Parameter {
1,760✔
268
        parameters := []Parameter{}
1,760✔
269
        for _, param := range params {
4,836✔
270
                parameter := p.parseParameter(*param.Value)
3,076✔
271
                parameters = append(parameters, parameter)
3,076✔
272
        }
3,076✔
273
        return parameters
1,760✔
274
}
275

276
func (p OpenApiParser) parseOperationParameters(operation openapi3.Operation, routeParameters openapi3.Parameters) (string, []Parameter) {
880✔
277
        contentType, parameters := p.parseRequestBodyParameters(operation.RequestBody)
880✔
278
        parameters = append(parameters, p.parseParameters(routeParameters)...)
880✔
279
        return contentType, append(parameters, p.parseParameters(operation.Parameters)...)
880✔
280
}
880✔
281

282
func (p OpenApiParser) getCategory(operation openapi3.Operation, document openapi3.T) *OperationCategory {
880✔
283
        if len(operation.Tags) > 0 {
1,746✔
284
                name := operation.Tags[0]
866✔
285
                description := ""
866✔
286
                tag := document.Tags.Get(name)
866✔
287
                if tag != nil {
866✔
288
                        description = tag.Description
×
289
                }
×
290
                return NewOperationCategory(p.formatName(name), description)
866✔
291
        }
292
        return nil
14✔
293
}
294

295
func (p OpenApiParser) parseOperation(method string, baseUri url.URL, route string, operation openapi3.Operation, routeParameters openapi3.Parameters, document openapi3.T) Operation {
880✔
296
        category := p.getCategory(operation, document)
880✔
297
        name := p.getName(method, route, category, operation)
880✔
298
        contentType, parameters := p.parseOperationParameters(operation, routeParameters)
880✔
299
        return *NewOperation(name, operation.Summary, operation.Description, method, baseUri, route, contentType, parameters, nil, false, category)
880✔
300
}
880✔
301

302
func (p OpenApiParser) parsePath(baseUri url.URL, route string, pathItem openapi3.PathItem, document openapi3.T) []Operation {
732✔
303
        operations := []Operation{}
732✔
304
        for method := range pathItem.Operations() {
1,612✔
305
                operation := pathItem.GetOperation(method)
880✔
306
                operations = append(operations, p.parseOperation(method, baseUri, route, *operation, pathItem.Parameters, document))
880✔
307
        }
880✔
308
        return operations
732✔
309
}
310

311
func (p OpenApiParser) parse(name string, document openapi3.T) (*Definition, error) {
42✔
312
        uri, err := p.getUri(document)
42✔
313
        if err != nil {
42✔
314
                return nil, fmt.Errorf("Error parsing server URL: %w", err)
×
315
        }
×
316
        operations := []Operation{}
42✔
317
        for path := range document.Paths {
774✔
318
                pathItem := document.Paths.Find(path)
732✔
319
                operations = append(operations, p.parsePath(*uri, path, *pathItem, document)...)
732✔
320
        }
732✔
321
        description := p.getDescription(document)
42✔
322
        return NewDefinition(name, description, operations), nil
42✔
323
}
324

325
func (p OpenApiParser) Parse(name string, data []byte) (*Definition, error) {
42✔
326
        loader := openapi3.NewLoader()
42✔
327
        document, err := loader.LoadFromData(data)
42✔
328
        if err != nil {
42✔
329
                return nil, err
×
330
        }
×
331
        return p.parse(name, *document)
42✔
332
}
333

334
func NewOpenApiParser() *OpenApiParser {
39✔
335
        return &OpenApiParser{}
39✔
336
}
39✔
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2025 Coveralls, Inc