Skip to content

Commit c022ce6

Browse files
committed
Fix URISyntaxException while reading OpenAPI from windows file path location
1 parent 20de7a2 commit c022ce6

File tree

3 files changed

+291
-10
lines changed

3 files changed

+291
-10
lines changed

modules/swagger-parser-v3/src/main/java/io/swagger/v3/parser/OpenAPIV3Parser.java

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -207,6 +207,9 @@ public SwaggerParseResult readWithInfo(String location, List<AuthorizationValue>
207207

208208
private SwaggerParseResult resolve(SwaggerParseResult result, List<AuthorizationValue> auth, ParseOptions options,
209209
String location) {
210+
if (location != null) {
211+
location = location.replace('\\', '/');
212+
}
210213
try {
211214
if (options != null) {
212215
if (options.isResolve() || options.isResolveFully()) {
@@ -284,7 +287,7 @@ private ObjectMapper getRightMapper(String data) {
284287
}
285288

286289
private String readContentFromLocation(String location, List<AuthorizationValue> auth) {
287-
final String adjustedLocation = location.replaceAll("\\\\", "/");
290+
final String adjustedLocation = location.replace('\\', '/');
288291
try {
289292
if (adjustedLocation.toLowerCase().startsWith("http")) {
290293
return RemoteUrl.urlToString(adjustedLocation, auth);

modules/swagger-parser-v3/src/test/java/io/swagger/v3/parser/test/OpenAPIV3ParserTest.java

Lines changed: 41 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,38 @@
4343
public class OpenAPIV3ParserTest {
4444
List<AuthorizationValue> auths = new ArrayList<>();
4545

46+
// @Test
47+
// public void windowsFilePathProducesUriError() {
48+
// String spec = "openapi: 3.1.1\n" +
49+
// "info:\n" +
50+
// " title: Test\n" +
51+
// " version: '1.0'\n" +
52+
// "paths: {}\n" +
53+
// "components:\n" +
54+
// " schemas:\n" +
55+
// " regionId:\n" +
56+
// " type: string\n" +
57+
// " main:\n" +
58+
// " type: object\n" +
59+
// " properties:\n" +
60+
// " regionId:\n" +
61+
// " $ref: '#/components/schemas/regionId'\n";
62+
// ParseOptions options = new ParseOptions();
63+
// options.setResolve(true);
64+
// SwaggerParseResult result = new OpenAPIV3Parser().readContents(spec, null, options, "C:\\\\fake\\path\\openapi.yaml");
65+
//
66+
// Assert.assertTrue(result.getMessages().stream()
67+
// .anyMatch(m -> m.contains("Illegal character in opaque part")),
68+
// "Expected URISyntaxException message for Windows paths");
69+
// }
70+
71+
@Test
72+
public void testWindowsFilePathRead() {
73+
OpenAPIV3Parser openApiParser = new OpenAPIV3Parser();
74+
OpenAPI openAPI = openApiParser.read("\\issue-2223\\openapi.yaml");
75+
assertNotNull(openAPI, "OpenAPI object should not be null (no errors during read())");
76+
}
77+
4678
@Test
4779
public void testFailedToResolveResponseReferences() {
4880
OpenAPIV3Parser openApiParser = new OpenAPIV3Parser();
@@ -51,7 +83,7 @@ public void testFailedToResolveResponseReferences() {
5183
SwaggerParseResult parseResult = openApiParser.readLocation("issue-2037/openapi.yaml", null, options);
5284
OpenAPI openAPI = parseResult.getOpenAPI();
5385

54-
Assert.assertTrue(openAPI.getPaths().get("/get").get$ref() == null);
86+
assertNull(openAPI.getPaths().get("/get").get$ref());
5587
Assert.assertEquals(openAPI.getPaths().get("/get").getGet().getResponses().get("200").getContent().get("application/json").getSchema().get$ref(), "#/components/schemas/ResponsesRef");
5688
}
5789

@@ -64,13 +96,13 @@ public void testFailedToResolveExternalReferences() {
6496
SwaggerParseResult parseResult = openApiParser.readLocation("resolve-external-ref/failedToResolveExternalRefs.yaml", null, options);
6597
OpenAPI openAPI = parseResult.getOpenAPI();
6698

67-
Assert.assertTrue(openAPI.getPaths().get("/permAssignments").get$ref() == null);
68-
Assert.assertEquals(openAPI.getPaths().get("/permAssignments").getGet().getResponses().get("202").getContent().get("application/vnd.api+json").getSchema().get$ref(),"#/components/schemas/schemaResponseSuccess");
69-
Assert.assertTrue(openAPI.getPaths().get("/permAssignmentChangeRequests").get$ref() == null);
70-
Assert.assertEquals(openAPI.getPaths().get("/permAssignmentChangeRequests").getGet().getResponses().get("202").getContent().get("application/vnd.api+json").getSchema().get$ref(),"#/components/schemas/schemaResponseSuccess");
71-
Assert.assertTrue(openAPI.getPaths().get("/permAssignmentChange").get$ref() == null);
72-
Assert.assertEquals(openAPI.getPaths().get("/permAssignmentChange").getGet().getResponses().get("201").getContent().get("application/vnd.api+json").getSchema().get$ref(),"#/components/schemas/Error");
73-
Assert.assertEquals(openAPI.getPaths().get("/permAssignmentChange").getGet().getResponses().get("404").getContent().get("application/vnd.api+json").getSchema().get$ref(),"#/components/schemas/RemoteError");
99+
assertNull(openAPI.getPaths().get("/permAssignments").get$ref());
100+
assertEquals(openAPI.getPaths().get("/permAssignments").getGet().getResponses().get("202").getContent().get("application/vnd.api+json").getSchema().get$ref(),"#/components/schemas/schemaResponseSuccess");
101+
assertNull(openAPI.getPaths().get("/permAssignmentChangeRequests").get$ref());
102+
assertEquals(openAPI.getPaths().get("/permAssignmentChangeRequests").getGet().getResponses().get("202").getContent().get("application/vnd.api+json").getSchema().get$ref(),"#/components/schemas/schemaResponseSuccess");
103+
assertNull(openAPI.getPaths().get("/permAssignmentChange").get$ref());
104+
assertEquals(openAPI.getPaths().get("/permAssignmentChange").getGet().getResponses().get("201").getContent().get("application/vnd.api+json").getSchema().get$ref(),"#/components/schemas/Error");
105+
assertEquals(openAPI.getPaths().get("/permAssignmentChange").getGet().getResponses().get("404").getContent().get("application/vnd.api+json").getSchema().get$ref(),"#/components/schemas/RemoteError");
74106

75107
}
76108

@@ -3429,4 +3461,4 @@ public void testVersion(){
34293461
SwaggerParseResult parseResult = openApiParser.readLocation("version-missing.yaml", null, options);
34303462
assertEquals(parseResult.getMessages().get(0), "attribute info.version is missing");
34313463
}
3432-
}
3464+
}
Lines changed: 246 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,246 @@
1+
openapi: 3.1.1
2+
info:
3+
title: Ferguson Customer Public API
4+
description: Services that provide access to Ferguson's customer information
5+
contact:
6+
name: Ferguson Middleware Services team
7+
license:
8+
name: Ferguson Services
9+
url: 'https://ferguson.com/licenses/LICENSE-1.0.html'
10+
version: v1.0
11+
servers:
12+
- url: https://localhost:8083/customer-publicapi-v1/svc
13+
description: Development
14+
tags:
15+
- name: domain
16+
description: Customer
17+
- name: visibility
18+
description: public
19+
paths:
20+
/{mainCustomerId}/billToZip/{billToZipCode}:
21+
get:
22+
operationId: getMainCustomerInfoBillZipcode
23+
summary: Service to get Customer information from main Customer account and associated billTo zipcode
24+
description: Service to get related Customer information
25+
parameters:
26+
- $ref: '#/components/parameters/transId'
27+
- $ref: '#/components/parameters/mainCustomerId'
28+
- $ref: '#/components/parameters/billToZipCode'
29+
30+
responses:
31+
'200':
32+
description: Request Successful
33+
headers:
34+
trans-id:
35+
$ref: '#/components/headers/trans-id'
36+
content:
37+
application/json:
38+
schema:
39+
$ref: '#/components/schemas/customerInfoResponse'
40+
41+
'400':
42+
description: Bad request
43+
headers:
44+
trans-id:
45+
$ref: '#/components/headers/trans-id'
46+
content:
47+
application/json:
48+
schema:
49+
$ref: '#/components/schemas/validationErrors'
50+
51+
'404':
52+
description: Not Found
53+
headers:
54+
trans-id:
55+
$ref: '#/components/headers/trans-id'
56+
'500':
57+
description: Internal Error
58+
headers:
59+
trans-id:
60+
$ref: '#/components/headers/trans-id'
61+
fe-resp-code:
62+
$ref: '#/components/headers/fe-resp-code'
63+
fe-resp-msg:
64+
$ref: '#/components/headers/fe-resp-msg'
65+
66+
components:
67+
schemas:
68+
regionId:
69+
type: string
70+
description: Region Id
71+
example: "RICH"
72+
branchId:
73+
type: string
74+
description: Branch Id
75+
example: "1350"
76+
customerType:
77+
type: string
78+
enum:
79+
- MASTER
80+
- MAIN
81+
- JOB
82+
customerName:
83+
type: string
84+
description: Account name
85+
example: "WP CLARKS FARM LLC"
86+
contractIds:
87+
type: array
88+
items:
89+
type: string
90+
description: Contract Id
91+
customerNumber:
92+
type: string
93+
description: Customer Id
94+
example: "276962"
95+
jobName:
96+
type: string
97+
description: Job name
98+
example: "OTIS HATFIELD"
99+
jobNumber:
100+
type: string
101+
description: Customer Id of the Job
102+
example: "93738"
103+
billingAddress:
104+
description: Billing address of the account
105+
type: object
106+
properties:
107+
streets:
108+
title: Line(s) of Street Address
109+
type: array
110+
items:
111+
type: string
112+
example: "1250 W. Mockingbird Lane"
113+
city:
114+
title: City
115+
type: string
116+
example: "Newport News"
117+
state:
118+
title: State Code
119+
type: string
120+
example: VA
121+
postalCode:
122+
title: Postal Code
123+
type: string
124+
example: 23606
125+
126+
customerInfoResponse:
127+
title: Customer Info Response with master, main and job info
128+
type: object
129+
properties:
130+
masterCustomerNumber:
131+
type: string
132+
description: Master customer number
133+
example: '371394'
134+
customerType:
135+
$ref: '#/components/schemas/customerType'
136+
mainCustomers:
137+
type: array
138+
items:
139+
$ref: '#/components/schemas/mainCustomer'
140+
mainCustomer:
141+
type: object
142+
properties:
143+
customerType:
144+
$ref: '#/components/schemas/customerType'
145+
regionId:
146+
$ref: '#/components/schemas/regionId'
147+
branchId:
148+
$ref: '#/components/schemas/branchId'
149+
customerName:
150+
$ref: '#/components/schemas/customerName'
151+
contractIds:
152+
$ref: '#/components/schemas/contractIds'
153+
customerNumber:
154+
$ref: '#/components/schemas/customerNumber'
155+
billingAddress:
156+
type: array
157+
items:
158+
$ref: '#/components/schemas/billingAddress'
159+
mainCustomerJobs:
160+
type: array
161+
items:
162+
$ref: '#/components/schemas/mainCustomerJob'
163+
164+
mainCustomerJob:
165+
type: object
166+
properties:
167+
customerType:
168+
$ref: '#/components/schemas/customerType'
169+
regionId:
170+
$ref: '#/components/schemas/regionId'
171+
branchId:
172+
$ref: '#/components/schemas/branchId'
173+
jobName:
174+
$ref: '#/components/schemas/jobName'
175+
contractIds:
176+
$ref: '#/components/schemas/contractIds'
177+
jobNumber:
178+
$ref: '#/components/schemas/jobNumber'
179+
billingAddress:
180+
type: array
181+
items:
182+
$ref: '#/components/schemas/billingAddress'
183+
validationError:
184+
title: Parameter Validation Error
185+
type: object
186+
x-allArgsConstructor: true
187+
properties:
188+
errorCode:
189+
title: Error Code
190+
description: Error Code indicating the nature of the error.
191+
type: string
192+
example: dataerror.k8.app.zipcode.invalid
193+
errorMsg:
194+
title: Error Message
195+
description: Human readable message associated with the errorCode.
196+
type: string
197+
example: invalid zipcode format
198+
field:
199+
title: Parameter in Error
200+
type: string
201+
example: billToZipCode
202+
validationErrors:
203+
title: List of Validation Errors
204+
type: array
205+
minItems: 1
206+
items:
207+
$ref: '#/components/schemas/validationError'
208+
headers:
209+
fe-resp-code:
210+
schema:
211+
type: string
212+
example: severe.error
213+
description: Response code
214+
fe-resp-msg:
215+
schema:
216+
type: string
217+
example: Severe Error
218+
description: Response message
219+
trans-id:
220+
schema:
221+
type: string
222+
description: Transaction Id (passed in by consumer or generated by the service)
223+
224+
parameters:
225+
transId:
226+
name: trans-id
227+
in: header
228+
description: Transaction Id (Provided by service consumer)
229+
required: false
230+
schema:
231+
type: string
232+
mainCustomerId:
233+
name: mainCustomerId
234+
in: path
235+
description: Main Customer id
236+
required: true
237+
schema:
238+
type: string
239+
billToZipCode:
240+
name: billToZipCode
241+
in: path
242+
description: Billed to zip code associated with the Main Account
243+
required: true
244+
schema:
245+
type: string
246+
pattern: '^(\\d{5})([-\\s]*\\d{4})?$'

0 commit comments

Comments
 (0)