0
votes

I am a .net developer but very new to iOS and swift development, just need help with consuming Web API using Swift2

The Asp.net Web API has been built with OAuth2 authentication, published to my Azure VM server with SSL certificate installed. The API site itself works properly, tested through Postman

However I got stuck when started writing first few lines of code in Swift trying to get Authentication token. After reading some online tutorials I decided to engage Alamofire, and produced below codes snippet:

func GetToken() {

    let params = [
        "grant_type" : "password",
        "username" : "[email protected]",
        "password" : "averygoodpassword"
    ]

    let headers = [
        "Content-Type" : "application/x-www-form-urlencoded"
    ]

    request(.POST, "https://api.example.com/token",
        parameters: params,
        headers: headers,
        encoding: .JSON)
        .responseJSON { request, response, result in

            print (request)
            print (response?.description)
            print (result)

            switch result {
            case .Success(let JSON):
                print("Success with JSON: \(JSON)")

            case .Failure(let data, let error):
                print("Request failed with error: \(error)")

                if let data = data {
                    print("Response data: \(NSString(data: data, encoding: NSUTF8StringEncoding)!)")
                }
            }

    }

}

It ends up with below output in Xcode which didn't seem to be OK. The error = unsupported_grant_type told me that the request were sent to server but the parameters were not sent with request properly. I really cannot figure out the reason and solution, had been digging on Internet for a few days but still feeling desperate with it. Can anyone help please? Even if someone can provide a pure swift solution without any 3rd party library will be greatly helpful. Thanks!

Xcode output:

Optional( { URL: https://api.example.com/token }) Optional(" { URL: https://api.example.com/token } { status code: 400, headers {\n \"Access-Control-Allow-Headers\" = \"Content-Type\";\n \"Access-Control-Allow-Methods\" = \"GET, POST, PUT, DELETE, OPTIONS\";\n \"Access-Control-Allow-Origin\" = \"*\";\n \"Cache-Control\" = \"no-cache\";\n \"Content-Length\" = 34;\n \"Content-Type\" = \"application/json;charset=UTF-8\";\n Date = \"Fri, 30 Sep 2016 10:30:31 GMT\";\n Expires = \"-1\";\n Pragma = \"no-cache\";\n Server = \"Microsoft-IIS/8.5\";\n \"X-Powered-By\" = \"ASP.NET\";\n} }") SUCCESS Success with JSON: { error = "unsupported_grant_type"; }

1

1 Answers

-1
votes

I had a similar problem trying to POST to MailGun for some automated emails I was implementing in an app.

I was able to get this working properly with a large HTTP response. I put the full path into Keys.plist so that I can upload my code to github and broke out some of the arguments into variables so I can have them programmatically set later down the road.

// Email the FBO with desired information
// Parse our Keys.plist so we can use our path
var keys: NSDictionary?

if let path = NSBundle.mainBundle().pathForResource("Keys", ofType: "plist") {
    keys = NSDictionary(contentsOfFile: path)
}

if let dict = keys {
    // variablize our https path with API key, recipient and message text
    let mailgunAPIPath = dict["mailgunAPIPath"] as? String
    let emailRecipient = "[email protected]"
    let emailMessage = "Testing%20email%20sender%20variables"

    // Create a session and fill it with our request
    let session = NSURLSession.sharedSession()
    let request = NSMutableURLRequest(URL: NSURL(string: mailgunAPIPath! + "from=FBOGo%20Reservation%20%3Cscheduler@<my domain>.com%3E&to=reservations@<my domain>.com&to=\(emailRecipient)&subject=A%20New%20Reservation%21&text=\(emailMessage)")!)

    // POST and report back with any errors and response codes
    request.HTTPMethod = "POST"
    let task = session.dataTaskWithRequest(request, completionHandler: {(data, response, error) in
        if let error = error {
            print(error)
        }

        if let response = response {
            print("url = \(response.URL!)")
            print("response = \(response)")
            let httpResponse = response as! NSHTTPURLResponse
            print("response code = \(httpResponse.statusCode)")
        }
    })
    task.resume()
}

The Mailgun Path is in Keys.plist as a string called mailgunAPIPath with the value:

https://API:key-<my key>@api.mailgun.net/v3/<my domain>.com/messages?

I'm slightly opposed to using 3rd party libraries, especially for small things like a http POST and this seems like a much more maintainable solution to me. Anyways, hope this helps, let me know if you have any questions!