Handle when response is a file URL. (#6469)

This is the equivalent change in the swift4 module which was made in the swift3 module in this PR:

https://github.com/swagger-api/swagger-codegen/pull/6274

This updates AlamofireImplementations.mustache to handle when the response is an URL. It also makes changes in the generated sample code for:

* default configuration (no promisekit or rxswift)
* promisekit
* rxswift

Also, in order to build, the generated code needed to be updated with the change in CodableHelper which changes dataDecodingStrategy to ".base64" from its previous definition in earlier Xcode 9 betas.
*
This commit is contained in:
ehyche 2017-09-11 23:37:39 -07:00 committed by wing328
parent d639b38d0d
commit 8067612e06
7 changed files with 446 additions and 6 deletions

View File

@ -142,6 +142,56 @@ open class AlamofireRequestBuilder<T>: RequestBuilder<T> {
nil nil
) )
}) })
case is URL.Type:
validatedRequest.responseData(completionHandler: { (dataResponse) in
cleanupRequest()
do {
guard !dataResponse.result.isFailure else {
throw DownloadException.responseFailed
}
guard let data = dataResponse.data else {
throw DownloadException.responseDataMissing
}
guard let request = request.request else {
throw DownloadException.requestMissing
}
let fileManager = FileManager.default
let urlRequest = try request.asURLRequest()
let documentsDirectory = fileManager.urls(for: .documentDirectory, in: .userDomainMask)[0]
let requestURL = try self.getURL(from: urlRequest)
var requestPath = try self.getPath(from: requestURL)
if let headerFileName = self.getFileName(fromContentDisposition: dataResponse.response?.allHeaderFields["Content-Disposition"] as? String) {
requestPath = requestPath.appending("/\(headerFileName)")
}
let filePath = documentsDirectory.appendingPathComponent(requestPath)
let directoryPath = filePath.deletingLastPathComponent().path
try fileManager.createDirectory(atPath: directoryPath, withIntermediateDirectories: true, attributes: nil)
try data.write(to: filePath, options: .atomic)
completion(
Response(
response: dataResponse.response!,
body: (filePath as! T)
),
nil
)
} catch let requestParserError as DownloadException {
completion(nil, ErrorResponse.Error(400, dataResponse.data, requestParserError))
} catch let error {
completion(nil, ErrorResponse.Error(400, dataResponse.data, error))
}
return
})
case is Void.Type: case is Void.Type:
validatedRequest.responseData(completionHandler: { (voidResponse) in validatedRequest.responseData(completionHandler: { (voidResponse) in
cleanupRequest() cleanupRequest()
@ -191,6 +241,66 @@ open class AlamofireRequestBuilder<T>: RequestBuilder<T> {
} }
return httpHeaders return httpHeaders
} }
fileprivate func getFileName(fromContentDisposition contentDisposition : String?) -> String? {
guard let contentDisposition = contentDisposition else {
return nil
}
let items = contentDisposition.components(separatedBy: ";")
var filename : String? = nil
for contentItem in items {
let filenameKey = "filename="
guard let range = contentItem.range(of: filenameKey) else {
break
}
filename = contentItem
return filename?
.replacingCharacters(in: range, with:"")
.replacingOccurrences(of: "\"", with: "")
.trimmingCharacters(in: .whitespacesAndNewlines)
}
return filename
}
fileprivate func getPath(from url : URL) throws -> String {
guard var path = NSURLComponents(url: url, resolvingAgainstBaseURL: true)?.path else {
throw DownloadException.requestMissingPath
}
if path.hasPrefix("/") {
path.remove(at: path.startIndex)
}
return path
}
fileprivate func getURL(from urlRequest : URLRequest) throws -> URL {
guard let url = urlRequest.url else {
throw DownloadException.requestMissingURL
}
return url
}
}
fileprivate enum DownloadException : Error {
case responseDataMissing
case responseFailed
case requestMissing
case requestMissingPath
case requestMissingURL
} }
public enum AlamofireDecodableRequestBuilderError: Error { public enum AlamofireDecodableRequestBuilderError: Error {

View File

@ -142,6 +142,56 @@ open class AlamofireRequestBuilder<T>: RequestBuilder<T> {
nil nil
) )
}) })
case is URL.Type:
validatedRequest.responseData(completionHandler: { (dataResponse) in
cleanupRequest()
do {
guard !dataResponse.result.isFailure else {
throw DownloadException.responseFailed
}
guard let data = dataResponse.data else {
throw DownloadException.responseDataMissing
}
guard let request = request.request else {
throw DownloadException.requestMissing
}
let fileManager = FileManager.default
let urlRequest = try request.asURLRequest()
let documentsDirectory = fileManager.urls(for: .documentDirectory, in: .userDomainMask)[0]
let requestURL = try self.getURL(from: urlRequest)
var requestPath = try self.getPath(from: requestURL)
if let headerFileName = self.getFileName(fromContentDisposition: dataResponse.response?.allHeaderFields["Content-Disposition"] as? String) {
requestPath = requestPath.appending("/\(headerFileName)")
}
let filePath = documentsDirectory.appendingPathComponent(requestPath)
let directoryPath = filePath.deletingLastPathComponent().path
try fileManager.createDirectory(atPath: directoryPath, withIntermediateDirectories: true, attributes: nil)
try data.write(to: filePath, options: .atomic)
completion(
Response(
response: dataResponse.response!,
body: (filePath as! T)
),
nil
)
} catch let requestParserError as DownloadException {
completion(nil, ErrorResponse.Error(400, dataResponse.data, requestParserError))
} catch let error {
completion(nil, ErrorResponse.Error(400, dataResponse.data, error))
}
return
})
case is Void.Type: case is Void.Type:
validatedRequest.responseData(completionHandler: { (voidResponse) in validatedRequest.responseData(completionHandler: { (voidResponse) in
cleanupRequest() cleanupRequest()
@ -191,6 +241,66 @@ open class AlamofireRequestBuilder<T>: RequestBuilder<T> {
} }
return httpHeaders return httpHeaders
} }
fileprivate func getFileName(fromContentDisposition contentDisposition : String?) -> String? {
guard let contentDisposition = contentDisposition else {
return nil
}
let items = contentDisposition.components(separatedBy: ";")
var filename : String? = nil
for contentItem in items {
let filenameKey = "filename="
guard let range = contentItem.range(of: filenameKey) else {
break
}
filename = contentItem
return filename?
.replacingCharacters(in: range, with:"")
.replacingOccurrences(of: "\"", with: "")
.trimmingCharacters(in: .whitespacesAndNewlines)
}
return filename
}
fileprivate func getPath(from url : URL) throws -> String {
guard var path = NSURLComponents(url: url, resolvingAgainstBaseURL: true)?.path else {
throw DownloadException.requestMissingPath
}
if path.hasPrefix("/") {
path.remove(at: path.startIndex)
}
return path
}
fileprivate func getURL(from urlRequest : URLRequest) throws -> URL {
guard let url = urlRequest.url else {
throw DownloadException.requestMissingURL
}
return url
}
}
fileprivate enum DownloadException : Error {
case responseDataMissing
case responseFailed
case requestMissing
case requestMissingPath
case requestMissingURL
} }
public enum AlamofireDecodableRequestBuilderError: Error { public enum AlamofireDecodableRequestBuilderError: Error {

View File

@ -16,7 +16,7 @@ open class CodableHelper {
var returnedError: Error? = nil var returnedError: Error? = nil
let decoder = JSONDecoder() let decoder = JSONDecoder()
decoder.dataDecodingStrategy = .base64Decode decoder.dataDecodingStrategy = .base64
if #available(iOS 10.0, *) { if #available(iOS 10.0, *) {
decoder.dateDecodingStrategy = .iso8601 decoder.dateDecodingStrategy = .iso8601
} }
@ -38,7 +38,7 @@ open class CodableHelper {
if prettyPrint { if prettyPrint {
encoder.outputFormatting = .prettyPrinted encoder.outputFormatting = .prettyPrinted
} }
encoder.dataEncodingStrategy = .base64Encode encoder.dataEncodingStrategy = .base64
if #available(iOS 10.0, *) { if #available(iOS 10.0, *) {
encoder.dateEncodingStrategy = .iso8601 encoder.dateEncodingStrategy = .iso8601
} }

View File

@ -142,6 +142,56 @@ open class AlamofireRequestBuilder<T>: RequestBuilder<T> {
nil nil
) )
}) })
case is URL.Type:
validatedRequest.responseData(completionHandler: { (dataResponse) in
cleanupRequest()
do {
guard !dataResponse.result.isFailure else {
throw DownloadException.responseFailed
}
guard let data = dataResponse.data else {
throw DownloadException.responseDataMissing
}
guard let request = request.request else {
throw DownloadException.requestMissing
}
let fileManager = FileManager.default
let urlRequest = try request.asURLRequest()
let documentsDirectory = fileManager.urls(for: .documentDirectory, in: .userDomainMask)[0]
let requestURL = try self.getURL(from: urlRequest)
var requestPath = try self.getPath(from: requestURL)
if let headerFileName = self.getFileName(fromContentDisposition: dataResponse.response?.allHeaderFields["Content-Disposition"] as? String) {
requestPath = requestPath.appending("/\(headerFileName)")
}
let filePath = documentsDirectory.appendingPathComponent(requestPath)
let directoryPath = filePath.deletingLastPathComponent().path
try fileManager.createDirectory(atPath: directoryPath, withIntermediateDirectories: true, attributes: nil)
try data.write(to: filePath, options: .atomic)
completion(
Response(
response: dataResponse.response!,
body: (filePath as! T)
),
nil
)
} catch let requestParserError as DownloadException {
completion(nil, ErrorResponse.Error(400, dataResponse.data, requestParserError))
} catch let error {
completion(nil, ErrorResponse.Error(400, dataResponse.data, error))
}
return
})
case is Void.Type: case is Void.Type:
validatedRequest.responseData(completionHandler: { (voidResponse) in validatedRequest.responseData(completionHandler: { (voidResponse) in
cleanupRequest() cleanupRequest()
@ -191,6 +241,66 @@ open class AlamofireRequestBuilder<T>: RequestBuilder<T> {
} }
return httpHeaders return httpHeaders
} }
fileprivate func getFileName(fromContentDisposition contentDisposition : String?) -> String? {
guard let contentDisposition = contentDisposition else {
return nil
}
let items = contentDisposition.components(separatedBy: ";")
var filename : String? = nil
for contentItem in items {
let filenameKey = "filename="
guard let range = contentItem.range(of: filenameKey) else {
break
}
filename = contentItem
return filename?
.replacingCharacters(in: range, with:"")
.replacingOccurrences(of: "\"", with: "")
.trimmingCharacters(in: .whitespacesAndNewlines)
}
return filename
}
fileprivate func getPath(from url : URL) throws -> String {
guard var path = NSURLComponents(url: url, resolvingAgainstBaseURL: true)?.path else {
throw DownloadException.requestMissingPath
}
if path.hasPrefix("/") {
path.remove(at: path.startIndex)
}
return path
}
fileprivate func getURL(from urlRequest : URLRequest) throws -> URL {
guard let url = urlRequest.url else {
throw DownloadException.requestMissingURL
}
return url
}
}
fileprivate enum DownloadException : Error {
case responseDataMissing
case responseFailed
case requestMissing
case requestMissingPath
case requestMissingURL
} }
public enum AlamofireDecodableRequestBuilderError: Error { public enum AlamofireDecodableRequestBuilderError: Error {

View File

@ -16,7 +16,7 @@ open class CodableHelper {
var returnedError: Error? = nil var returnedError: Error? = nil
let decoder = JSONDecoder() let decoder = JSONDecoder()
decoder.dataDecodingStrategy = .base64Decode decoder.dataDecodingStrategy = .base64
if #available(iOS 10.0, *) { if #available(iOS 10.0, *) {
decoder.dateDecodingStrategy = .iso8601 decoder.dateDecodingStrategy = .iso8601
} }
@ -38,7 +38,7 @@ open class CodableHelper {
if prettyPrint { if prettyPrint {
encoder.outputFormatting = .prettyPrinted encoder.outputFormatting = .prettyPrinted
} }
encoder.dataEncodingStrategy = .base64Encode encoder.dataEncodingStrategy = .base64
if #available(iOS 10.0, *) { if #available(iOS 10.0, *) {
encoder.dateEncodingStrategy = .iso8601 encoder.dateEncodingStrategy = .iso8601
} }

View File

@ -142,6 +142,56 @@ open class AlamofireRequestBuilder<T>: RequestBuilder<T> {
nil nil
) )
}) })
case is URL.Type:
validatedRequest.responseData(completionHandler: { (dataResponse) in
cleanupRequest()
do {
guard !dataResponse.result.isFailure else {
throw DownloadException.responseFailed
}
guard let data = dataResponse.data else {
throw DownloadException.responseDataMissing
}
guard let request = request.request else {
throw DownloadException.requestMissing
}
let fileManager = FileManager.default
let urlRequest = try request.asURLRequest()
let documentsDirectory = fileManager.urls(for: .documentDirectory, in: .userDomainMask)[0]
let requestURL = try self.getURL(from: urlRequest)
var requestPath = try self.getPath(from: requestURL)
if let headerFileName = self.getFileName(fromContentDisposition: dataResponse.response?.allHeaderFields["Content-Disposition"] as? String) {
requestPath = requestPath.appending("/\(headerFileName)")
}
let filePath = documentsDirectory.appendingPathComponent(requestPath)
let directoryPath = filePath.deletingLastPathComponent().path
try fileManager.createDirectory(atPath: directoryPath, withIntermediateDirectories: true, attributes: nil)
try data.write(to: filePath, options: .atomic)
completion(
Response(
response: dataResponse.response!,
body: (filePath as! T)
),
nil
)
} catch let requestParserError as DownloadException {
completion(nil, ErrorResponse.Error(400, dataResponse.data, requestParserError))
} catch let error {
completion(nil, ErrorResponse.Error(400, dataResponse.data, error))
}
return
})
case is Void.Type: case is Void.Type:
validatedRequest.responseData(completionHandler: { (voidResponse) in validatedRequest.responseData(completionHandler: { (voidResponse) in
cleanupRequest() cleanupRequest()
@ -191,6 +241,66 @@ open class AlamofireRequestBuilder<T>: RequestBuilder<T> {
} }
return httpHeaders return httpHeaders
} }
fileprivate func getFileName(fromContentDisposition contentDisposition : String?) -> String? {
guard let contentDisposition = contentDisposition else {
return nil
}
let items = contentDisposition.components(separatedBy: ";")
var filename : String? = nil
for contentItem in items {
let filenameKey = "filename="
guard let range = contentItem.range(of: filenameKey) else {
break
}
filename = contentItem
return filename?
.replacingCharacters(in: range, with:"")
.replacingOccurrences(of: "\"", with: "")
.trimmingCharacters(in: .whitespacesAndNewlines)
}
return filename
}
fileprivate func getPath(from url : URL) throws -> String {
guard var path = NSURLComponents(url: url, resolvingAgainstBaseURL: true)?.path else {
throw DownloadException.requestMissingPath
}
if path.hasPrefix("/") {
path.remove(at: path.startIndex)
}
return path
}
fileprivate func getURL(from urlRequest : URLRequest) throws -> URL {
guard let url = urlRequest.url else {
throw DownloadException.requestMissingURL
}
return url
}
}
fileprivate enum DownloadException : Error {
case responseDataMissing
case responseFailed
case requestMissing
case requestMissingPath
case requestMissingURL
} }
public enum AlamofireDecodableRequestBuilderError: Error { public enum AlamofireDecodableRequestBuilderError: Error {

View File

@ -16,7 +16,7 @@ open class CodableHelper {
var returnedError: Error? = nil var returnedError: Error? = nil
let decoder = JSONDecoder() let decoder = JSONDecoder()
decoder.dataDecodingStrategy = .base64Decode decoder.dataDecodingStrategy = .base64
if #available(iOS 10.0, *) { if #available(iOS 10.0, *) {
decoder.dateDecodingStrategy = .iso8601 decoder.dateDecodingStrategy = .iso8601
} }
@ -38,7 +38,7 @@ open class CodableHelper {
if prettyPrint { if prettyPrint {
encoder.outputFormatting = .prettyPrinted encoder.outputFormatting = .prettyPrinted
} }
encoder.dataEncodingStrategy = .base64Encode encoder.dataEncodingStrategy = .base64
if #available(iOS 10.0, *) { if #available(iOS 10.0, *) {
encoder.dateEncodingStrategy = .iso8601 encoder.dateEncodingStrategy = .iso8601
} }