yonaskolb / SwagGen

OpenAPI/Swagger 3.0 Parser and Swift code generator
MIT License
626 stars 146 forks source link

Multipart request only supports limited number of body types #177

Open jrcmramos opened 5 years ago

jrcmramos commented 5 years ago

Description

A multipart request can only accept a limited number of formParameter types, as we can see in the following code from the generated APIClient.swift.

    private func makeNetworkRequest<T>(request: APIRequest<T>, urlRequest: URLRequest, cancellableRequest: CancellableRequest, requestBehaviour: RequestBehaviourGroup, completionQueue: DispatchQueue, complete: @escaping (APIResponse<T>) -> Void) {
        requestBehaviour.beforeSend()

        if request.service.isUpload {
            sessionManager.upload(
                multipartFormData: { multipartFormData in
                    for (name, value) in request.formParameters {
                        if let file = value as? UploadFile {
                            switch file.type {
                            case let .url(url):
                                if let fileName = file.fileName, let mimeType = file.mimeType {
                                    multipartFormData.append(url, withName: name, fileName: fileName, mimeType: mimeType)
                                } else {
                                    multipartFormData.append(url, withName: name)
                                }
                            case let .data(data):
                                if let fileName = file.fileName, let mimeType = file.mimeType {
                                    multipartFormData.append(data, withName: name, fileName: fileName, mimeType: mimeType)
                                } else {
                                    multipartFormData.append(data, withName: name)
                                }
                            }
                        } else if let url = value as? URL {
                            multipartFormData.append(url, withName: name)
                        } else if let data = value as? Data {
                            multipartFormData.append(data, withName: name)
                        } else if let data = value as? String {
                            multipartFormData.append(data.data(using: .utf8)!, withName: name)
                        }
                    }
                },

This means that if we have a multipart request with (for example) a string property, this won't be added to the request.

My suggestion would be to have a protocol (DataConvertible) with a method toData() that would convert types to Data and then append them to the multipart request.

Example

APIRequest.swift

protocol DataConvertible {
    func toData() -> Data
}

APIClient.swift

private func makeNetworkRequest<T>(request: APIRequest<T>, urlRequest: URLRequest, cancellableRequest: CancellableRequest, requestBehaviour: RequestBehaviourGroup, completionQueue: DispatchQueue, complete: @escaping (APIResponse<T>) -> Void) {
(...)
else if let data = value as? DataConvertible {
    multipartFormData.append(data.toData(), withName: name)
}