Skip to content

Commit 95ef1bf

Browse files
ehychewing328
authored andcommitted
Swift3: properly percent-escape path parameters (#6705)
* Add addiitional files from upstream * Remove mis-added files * Swift3: Properly percent-escape path parameters This change fixes the following issue: #6400 The problem was that path parameters were not properly percent-escaped before being placed into the URL path. This leads to creation of an invalid URL, which then fails. So therefore, in the API template where path parameters are handled, we propertly percent escape them, using the characters which are allowed in URL paths. In addition to this template change, then this PR includes the following changes: 1. Resulting changes in all generated code due to the above template change. 2. I added the objcCompatible run to the swift3-petstore-all.sh so that I could re-generated all of the generated code with a single script. 3. I added a unit test in UserAPITests.swift which verifies that paths are properly escaped. 4. In order to make the unit test work, then I needed access to RequestBuilder<T>.URLString to verify that the path was properly escaped. However, RequestBuilder<T>.URLString had "internal" access control so it was inaccessible from the unit test. So therefore, I made four contants in RequestBuilder<T> to be public. This should not harm anything, since they are constants ("let's") and cannot be changed from the outside of the class after initialization. 5. There were also some stray changes which look like they were caused by having not run bin/swift3-petstore-all.sh in a while.
1 parent bc302f7 commit 95ef1bf

File tree

84 files changed

+5188
-69
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

84 files changed

+5188
-69
lines changed

bin/swift3-petstore-all.sh

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,3 +42,7 @@ java $JAVA_OPTS -jar $executable $ags
4242
ags="$@ generate -t modules/swagger-codegen/src/main/resources/swift3 -i modules/swagger-codegen/src/test/resources/2_0/petstore-with-fake-endpoints-models-for-testing.yaml -l swift3 -c ./bin/swift3-petstore-unwraprequired.json -o samples/client/petstore/swift3/unwraprequired"
4343
echo "#### Petstore Swift API client (unwraprequired) ####"
4444
java $JAVA_OPTS -jar $executable $ags
45+
46+
ags="$@ generate -t modules/swagger-codegen/src/main/resources/swift3 -i modules/swagger-codegen/src/test/resources/2_0/petstore-with-fake-endpoints-models-for-testing.yaml -l swift3 -c ./bin/swift3-petstore-objcCompatible.json -o samples/client/petstore/swift3/objcCompatible"
47+
echo "#### Petstore Swift API client (objcCompatible) ####"
48+
java $JAVA_OPTS -jar $executable $ags

modules/swagger-codegen/src/main/resources/swift3/APIs.mustache

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -32,10 +32,10 @@ open class APIBase {
3232
open class RequestBuilder<T> {
3333
var credential: URLCredential?
3434
var headers: [String:String]
35-
let parameters: Any?
36-
let isBody: Bool
37-
let method: String
38-
let URLString: String
35+
public let parameters: Any?
36+
public let isBody: Bool
37+
public let method: String
38+
public let URLString: String
3939
4040
/// Optional block to obtain a reference to the request's progress instance when available.
4141
public var onProgressReady: ((Progress) -> ())?

modules/swagger-codegen/src/main/resources/swift3/api.mustache

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -120,7 +120,9 @@ open class {{classname}}: APIBase {
120120
*/
121121
open class func {{operationId}}WithRequestBuilder({{#allParams}}{{paramName}}: {{#isEnum}}{{#isContainer}}{{{dataType}}}{{/isContainer}}{{^isContainer}}{{{datatypeWithEnum}}}_{{operationId}}{{/isContainer}}{{/isEnum}}{{^isEnum}}{{{dataType}}}{{/isEnum}}{{^required}}? = nil{{/required}}{{#hasMore}}, {{/hasMore}}{{/allParams}}) -> RequestBuilder<{{#returnType}}{{{returnType}}}{{/returnType}}{{^returnType}}Void{{/returnType}}> {
122122
{{^pathParams}}let{{/pathParams}}{{#pathParams}}{{^secondaryParam}}var{{/secondaryParam}}{{/pathParams}} path = "{{{path}}}"{{#pathParams}}
123-
path = path.replacingOccurrences(of: "{{=<% %>=}}{<%baseName%>}<%={{ }}=%>", with: "\({{paramName}}{{#isEnum}}{{#isContainer}}{{{dataType}}}{{/isContainer}}{{^isContainer}}.rawValue{{/isContainer}}{{/isEnum}})", options: .literal, range: nil){{/pathParams}}
123+
let {{paramName}}PreEscape = "\({{paramName}}{{#isEnum}}{{#isContainer}}{{{dataType}}}{{/isContainer}}{{^isContainer}}.rawValue{{/isContainer}}{{/isEnum}})"
124+
let {{paramName}}PostEscape = {{paramName}}PreEscape.addingPercentEncoding(withAllowedCharacters: .urlPathAllowed) ?? ""
125+
path = path.replacingOccurrences(of: "{{=<% %>=}}{<%baseName%>}<%={{ }}=%>", with: {{paramName}}PostEscape, options: .literal, range: nil){{/pathParams}}
124126
let URLString = {{projectName}}API.basePath + path
125127
{{#bodyParam}}
126128
let parameters = {{paramName}}{{^required}}?{{/required}}.encodeToJSON()

samples/client/petstore/swift3/default/PetstoreClient/Classes/Swaggers/APIs.swift

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -32,10 +32,10 @@ open class APIBase {
3232
open class RequestBuilder<T> {
3333
var credential: URLCredential?
3434
var headers: [String:String]
35-
let parameters: Any?
36-
let isBody: Bool
37-
let method: String
38-
let URLString: String
35+
public let parameters: Any?
36+
public let isBody: Bool
37+
public let method: String
38+
public let URLString: String
3939

4040
/// Optional block to obtain a reference to the request's progress instance when available.
4141
public var onProgressReady: ((Progress) -> ())?

samples/client/petstore/swift3/default/PetstoreClient/Classes/Swaggers/APIs/AnotherFakeAPI.swift

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
//
2-
// AnotherFakeAPI.swift
2+
// AnotherfakeAPI.swift
33
//
44
// Generated by swagger-codegen
55
// https://github.com/swagger-api/swagger-codegen
@@ -9,7 +9,7 @@ import Foundation
99
import Alamofire
1010

1111

12-
open class AnotherFakeAPI: APIBase {
12+
open class AnotherfakeAPI: APIBase {
1313
/**
1414
To test special tags
1515
- parameter body: (body) client model

samples/client/petstore/swift3/default/PetstoreClient/Classes/Swaggers/APIs/Fake_classname_tags123API.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,7 @@ open class Fake_classname_tags123API: APIBase {
3737
open class func testClassnameWithRequestBuilder(body: Client) -> RequestBuilder<Client> {
3838
let path = "/fake_classname_test"
3939
let URLString = PetstoreClientAPI.basePath + path
40-
let parameters = body.encodeToJSON() as? [String:AnyObject]
40+
let parameters = body.encodeToJSON()
4141

4242
let url = NSURLComponents(string: URLString)
4343

samples/client/petstore/swift3/default/PetstoreClient/Classes/Swaggers/APIs/PetAPI.swift

Lines changed: 12 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -70,7 +70,9 @@ open class PetAPI: APIBase {
7070
*/
7171
open class func deletePetWithRequestBuilder(petId: Int64, apiKey: String? = nil) -> RequestBuilder<Void> {
7272
var path = "/pet/{petId}"
73-
path = path.replacingOccurrences(of: "{petId}", with: "\(petId)", options: .literal, range: nil)
73+
let petIdPreEscape = "\(petId)"
74+
let petIdPostEscape = petIdPreEscape.addingPercentEncoding(withAllowedCharacters: .urlPathAllowed) ?? ""
75+
path = path.replacingOccurrences(of: "{petId}", with: petIdPostEscape, options: .literal, range: nil)
7476
let URLString = PetstoreClientAPI.basePath + path
7577
let parameters: [String:Any]? = nil
7678

@@ -412,7 +414,9 @@ open class PetAPI: APIBase {
412414
*/
413415
open class func getPetByIdWithRequestBuilder(petId: Int64) -> RequestBuilder<Pet> {
414416
var path = "/pet/{petId}"
415-
path = path.replacingOccurrences(of: "{petId}", with: "\(petId)", options: .literal, range: nil)
417+
let petIdPreEscape = "\(petId)"
418+
let petIdPostEscape = petIdPreEscape.addingPercentEncoding(withAllowedCharacters: .urlPathAllowed) ?? ""
419+
path = path.replacingOccurrences(of: "{petId}", with: petIdPostEscape, options: .literal, range: nil)
416420
let URLString = PetstoreClientAPI.basePath + path
417421
let parameters: [String:Any]? = nil
418422

@@ -485,7 +489,9 @@ open class PetAPI: APIBase {
485489
*/
486490
open class func updatePetWithFormWithRequestBuilder(petId: Int64, name: String? = nil, status: String? = nil) -> RequestBuilder<Void> {
487491
var path = "/pet/{petId}"
488-
path = path.replacingOccurrences(of: "{petId}", with: "\(petId)", options: .literal, range: nil)
492+
let petIdPreEscape = "\(petId)"
493+
let petIdPostEscape = petIdPreEscape.addingPercentEncoding(withAllowedCharacters: .urlPathAllowed) ?? ""
494+
path = path.replacingOccurrences(of: "{petId}", with: petIdPostEscape, options: .literal, range: nil)
489495
let URLString = PetstoreClientAPI.basePath + path
490496
let formParams: [String:Any?] = [
491497
"name": name,
@@ -535,7 +541,9 @@ open class PetAPI: APIBase {
535541
*/
536542
open class func uploadFileWithRequestBuilder(petId: Int64, additionalMetadata: String? = nil, file: URL? = nil) -> RequestBuilder<ApiResponse> {
537543
var path = "/pet/{petId}/uploadImage"
538-
path = path.replacingOccurrences(of: "{petId}", with: "\(petId)", options: .literal, range: nil)
544+
let petIdPreEscape = "\(petId)"
545+
let petIdPostEscape = petIdPreEscape.addingPercentEncoding(withAllowedCharacters: .urlPathAllowed) ?? ""
546+
path = path.replacingOccurrences(of: "{petId}", with: petIdPostEscape, options: .literal, range: nil)
539547
let URLString = PetstoreClientAPI.basePath + path
540548
let formParams: [String:Any?] = [
541549
"additionalMetadata": additionalMetadata,

samples/client/petstore/swift3/default/PetstoreClient/Classes/Swaggers/APIs/StoreAPI.swift

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,9 @@ open class StoreAPI: APIBase {
3232
*/
3333
open class func deleteOrderWithRequestBuilder(orderId: String) -> RequestBuilder<Void> {
3434
var path = "/store/order/{order_id}"
35-
path = path.replacingOccurrences(of: "{order_id}", with: "\(orderId)", options: .literal, range: nil)
35+
let orderIdPreEscape = "\(orderId)"
36+
let orderIdPostEscape = orderIdPreEscape.addingPercentEncoding(withAllowedCharacters: .urlPathAllowed) ?? ""
37+
path = path.replacingOccurrences(of: "{order_id}", with: orderIdPostEscape, options: .literal, range: nil)
3638
let URLString = PetstoreClientAPI.basePath + path
3739
let parameters: [String:Any]? = nil
3840

@@ -130,7 +132,9 @@ open class StoreAPI: APIBase {
130132
*/
131133
open class func getOrderByIdWithRequestBuilder(orderId: Int64) -> RequestBuilder<Order> {
132134
var path = "/store/order/{order_id}"
133-
path = path.replacingOccurrences(of: "{order_id}", with: "\(orderId)", options: .literal, range: nil)
135+
let orderIdPreEscape = "\(orderId)"
136+
let orderIdPostEscape = orderIdPreEscape.addingPercentEncoding(withAllowedCharacters: .urlPathAllowed) ?? ""
137+
path = path.replacingOccurrences(of: "{order_id}", with: orderIdPostEscape, options: .literal, range: nil)
134138
let URLString = PetstoreClientAPI.basePath + path
135139
let parameters: [String:Any]? = nil
136140

samples/client/petstore/swift3/default/PetstoreClient/Classes/Swaggers/APIs/UserAPI.swift

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -128,7 +128,9 @@ open class UserAPI: APIBase {
128128
*/
129129
open class func deleteUserWithRequestBuilder(username: String) -> RequestBuilder<Void> {
130130
var path = "/user/{username}"
131-
path = path.replacingOccurrences(of: "{username}", with: "\(username)", options: .literal, range: nil)
131+
let usernamePreEscape = "\(username)"
132+
let usernamePostEscape = usernamePreEscape.addingPercentEncoding(withAllowedCharacters: .urlPathAllowed) ?? ""
133+
path = path.replacingOccurrences(of: "{username}", with: usernamePostEscape, options: .literal, range: nil)
132134
let URLString = PetstoreClientAPI.basePath + path
133135
let parameters: [String:Any]? = nil
134136

@@ -199,7 +201,9 @@ open class UserAPI: APIBase {
199201
*/
200202
open class func getUserByNameWithRequestBuilder(username: String) -> RequestBuilder<User> {
201203
var path = "/user/{username}"
202-
path = path.replacingOccurrences(of: "{username}", with: "\(username)", options: .literal, range: nil)
204+
let usernamePreEscape = "\(username)"
205+
let usernamePostEscape = usernamePreEscape.addingPercentEncoding(withAllowedCharacters: .urlPathAllowed) ?? ""
206+
path = path.replacingOccurrences(of: "{username}", with: usernamePostEscape, options: .literal, range: nil)
203207
let URLString = PetstoreClientAPI.basePath + path
204208
let parameters: [String:Any]? = nil
205209

@@ -306,7 +310,9 @@ open class UserAPI: APIBase {
306310
*/
307311
open class func updateUserWithRequestBuilder(username: String, body: User) -> RequestBuilder<Void> {
308312
var path = "/user/{username}"
309-
path = path.replacingOccurrences(of: "{username}", with: "\(username)", options: .literal, range: nil)
313+
let usernamePreEscape = "\(username)"
314+
let usernamePostEscape = usernamePreEscape.addingPercentEncoding(withAllowedCharacters: .urlPathAllowed) ?? ""
315+
path = path.replacingOccurrences(of: "{username}", with: usernamePostEscape, options: .literal, range: nil)
310316
let URLString = PetstoreClientAPI.basePath + path
311317
let parameters = body.encodeToJSON()
312318

samples/client/petstore/swift3/default/SwaggerClientTests/SwaggerClientTests/UserAPITests.swift

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -151,4 +151,14 @@ class UserAPITests: XCTestCase {
151151
self.waitForExpectations(timeout: testTimeout, handler: nil)
152152
}
153153

154+
func testPathParamsAreEscaped() {
155+
// The path for this operation is /user/{userId}. In order to make a usable path,
156+
// then we must make sure that {userId} is percent-escaped when it is substituted
157+
// into the path. So we intentionally introduce a path with spaces.
158+
let userRequestBuilder = UserAPI.getUserByNameWithRequestBuilder(username: "User Name With Spaces")
159+
let urlContainsSpace = userRequestBuilder.URLString.contains(" ")
160+
161+
XCTAssert(!urlContainsSpace, "Expected URL to be escaped, but it was not.")
162+
}
163+
154164
}

0 commit comments

Comments
 (0)