Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Is XML Based Response Supported #54

Closed
tonespy opened this issue Oct 6, 2017 · 8 comments
Closed

Is XML Based Response Supported #54

tonespy opened this issue Oct 6, 2017 · 8 comments
Labels

Comments

@tonespy
Copy link

tonespy commented Oct 6, 2017

I've been trying to utilize TRON for an API that gives response in XML and my response has been empty always. This is how I've been making my requests:

let tron = MoviepathService.create()
    
    func getSubscriptions(params: [String : Any]) -> Observable<[SubscriptionObject]> {
        let request: APIRequest<String, MoviePathError> = tron.request("".getSubscriptions())
        request.method = .post
        request.headers = ["Content-Type":"application/x-www-form-urlencoded"]
        request.parameters = params
        return request.rxResult().flatMap({ (element) -> Observable<[SubscriptionObject]> in
            print("SubscriptionFetch: ", element)
            return Observable.just([SubscriptionObject]())
        })
    }

Am I doing anything wrong? Thanks.

@DenTelezhkin
Copy link
Member

You need to use custom response serializer for that, by default TRON assumes you are using JSON or key-value based payloads. For examples on how to implement that you can take a look at Response serializers doc.

@tonespy
Copy link
Author

tonespy commented Oct 6, 2017

What if I want the response to just be in strings. Do, I still have to write a serializer? Because, I've tried something like this and still no response

let request: APIRequest<String, MoviePathError> = 
tron.request("".getSubscriptions(), responseSerializer: DataRequest.stringResponseSerializer(encoding: nil))

@DenTelezhkin
Copy link
Member

Yes, because by default SwiftyJSON is used and it will try to initialize JSON object from your String.

@tonespy
Copy link
Author

tonespy commented Oct 6, 2017

Okay. So, I did this:

struct CustomResponseSerializer<T, ErrorModel: JSONDecodable> : ErrorHandlingDataResponseSerializerProtocol {
    
    typealias SerializedError = ErrorModel
    typealias SerializedObject = T
    
    var serializeResponse: (URLRequest?, HTTPURLResponse?, Data?, Error?) -> Result<T> {
        return { request, response, data, error in
            if let error = error {
                return Result.failure(error)
            }
            
            let mainResponse = String(data: data!, encoding: String.Encoding.utf8) ?? "Data could not be printed"
            return Result.success(mainResponse) as! Result<T>
        }
    }
}

Utilizing the Serializer below:

func getSubscriptions(params: [String : Any]) -> Observable<[SubscriptionObject]> {
        let request: APIRequest<String, MoviePathError> = tron.request("".getSubscriptions(), responseSerializer: CustomResponseSerializer()) //tron.request("".getSubscriptions())
        request.method = .post
        request.headers = ["Content-Type":"application/x-www-form-urlencoded"]
        request.parameters = params
        return request.rxResult().flatMap({ (element) -> Observable<[SubscriptionObject]> in
            print("SubscriptionFetch: ", element)
            //self.alamoTry(params: params)
            return Observable.just([SubscriptionObject]())
        })
    }

But, data is empty always. Am I still doing anything wrong?

@DenTelezhkin
Copy link
Member

Looks fine, apart from bunch of force unwraps. It probably should work, can you post your code for using this response serializer?

@tonespy
Copy link
Author

tonespy commented Oct 6, 2017

Updated @DenHeadless

@DenTelezhkin
Copy link
Member

I don't understand what following part does:

request("".getSubscriptions()

But other than that looks fine. You can also try this request using cURL and see if it works correctly. You can get curl for final request by doing something like this:

let sentRequest = request.perform(withSuccess: { _ in }, error: { _ in})
debugPrint(sentRequest) // This line will get you resulting cURL.

@tonespy
Copy link
Author

tonespy commented Oct 6, 2017

Everything is working fine. For anyone looking at implementing XML this is the full workaround:
The Serializer:

import Foundation
import Alamofire

struct CustomResponseSerializer<T, ErrorModel: JSONDecodable> : ErrorHandlingDataResponseSerializerProtocol {
    
    typealias SerializedError = ErrorModel
    typealias SerializedObject = T
    
    var serializeResponse: (URLRequest?, HTTPURLResponse?, Data?, Error?) -> Result<T> {
        return { request, response, data, error in
            if let error = error {
                return Result.failure(error)
            }
            
            if let data = data {
                let mainResponse = String(data: data, encoding: String.Encoding.utf8)
                return Result.success(mainResponse) as! Result<T>
            }
            return Result.success("") as! Result<T>
        }
    }
}

And, in your request, remember to add the "Accept" header to accept "text/xml" or and "application/xml"

request.headers = ["Content-Type":"application/x-www-form-urlencoded", "Accept": "text/xml,application/xml,application/json"]

@tonespy tonespy closed this as completed Oct 6, 2017
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

2 participants