Как сделать запрос API в Swift похожим на рабочий запрос Python, который я сейчас использую? - PullRequest
0 голосов
/ 03 марта 2020

Я хочу преобразовать этот Python запрос в скрипт Swift.

Вот мой рабочий python скрипт, который возвращает accessToken!

#!/usr/bin/python

import requests
import json

#MAKE THE REQUEST
URL = "http://this/is/the/url"
headers = {
'Accept': "application/json",
"Accept-Language": "en_US"
}
data = {
    "grant_type": "password",
    "username" : "GROUP\SITE\USERNAME",
    "password" : "somepassword"
}
r = requests.get(url = URL, params = headers, data = data)
data = r.json()



accessToken = data['access_token']
print(accessToken)

Когда я запускаю Swift Playground для кода ниже ничего не возвращается! Кажется, что скрипт выходит из-под контроля, пусть data = data else {return}

Как я могу получить те же результаты, что и скрипт Python выше. Я пытался реализовать компоненты URLC с помощью этого руководства ...

import UIKit

var url = "http://just/the/url"
extension Dictionary {
    func percentEncoded() -> Data? {
        return map { key, value in
            let escapedKey = "\(key)"
            let escapedValue = "\(value)"
            print(escapedKey + "=" + escapedValue)
            return escapedKey + "=" + escapedValue
        }
        .joined(separator: "&")
        .data(using: .utf8)

    }
}

extension CharacterSet {
    static let urlQueryValueAllowed: CharacterSet = {
        let generalDelimitersToEncode = ":#[]@" // does not include "?" or "/" due to RFC 3986 - Section 3.4
        let subDelimitersToEncode = "$&'()*+,;="

        var allowed = CharacterSet.urlQueryAllowed
        allowed.remove(charactersIn: "\(generalDelimitersToEncode)\(subDelimitersToEncode)")
        return allowed
    }()
}

var request = URLRequest(url: URL(string:url)!)
   request.httpMethod = "GET"
let parameters: [String: String] = [
    "grant_type":"password",
    "username":"GROUP\\SITE\\USER",
    "password":"somePassword"
]
   request.httpBody = parameters.percentEncoded()
   request.setValue("application/x-www-form-urlencoded", forHTTPHeaderField: "Content-Type")
   request.setValue("application/XML", forHTTPHeaderField: "Accept")

let config = URLSessionConfiguration.default
    URLSession(configuration: config).dataTask(with: request) { (data, response, err) in

       guard let data = data else { return }
        print(data)
       guard let dataAsString = String(data: data, encoding: .utf8)else {return}
     print(dataAsString)

       guard let httpResponse = response as? HTTPURLResponse,
             (200...299).contains(httpResponse.statusCode) else {
           print("Bad Credentials")
           return
       }

       //HTTP Status Code!
        print("HTTP RESPONSE:"+"\(httpResponse.statusCode)")
//
           }.resume()

Ответы [ 2 ]

1 голос
/ 04 марта 2020

Если я правильно помню, начиная с iOS 13, у вас не может быть httpBody для вызова GET, поэтому вам нужно либо переключиться на POST / PUT, либо добавить параметры в строку URL (см. Ниже). также были разные Accept заголовки в вашем python против swift. Один был xml другой был json.

var urlComponents = URLComponents(string: "http://this/is/the/url")
urlComponents?.queryItems = [
    URLQueryItem(name: "grant_type", value: "password"),
    URLQueryItem(name: "username", value: "username"),
    URLQueryItem(name: "password", value: "somepassword")
]

guard let url = urlComponents?.url else { return } // You can print url here to see how it looks
var request = URLRequest(url: url)
request.httpMethod = "GET"
request.setValue("application/json", forHTTPHeaderField: "Accept")
request.setValue("en_US", forHTTPHeaderField: "Accept-Language")

let task = URLSession.shared.dataTask(with: request) { data, response, error in
        guard let data = data,
            let response = response as? HTTPURLResponse,
            error == nil else {
            print("error", error ?? "Unknown error")
            return
        }
        print(response)
        guard (200 ... 299) ~= response.statusCode else {
            print("response = \(response)")
            return
        }

        let responseString = String(data: data, encoding: .utf8)
        print(responseString)
    }
    task.resume()
0 голосов
/ 04 марта 2020

Проблема была в следующем ...

 request.httpMethod = "GET"

Мне пришлось изменить значение get на "POST", и теперь у меня есть токен !!!! Я был смущен, потому что скрипт python использовал GET. У меня был скрипт bash, который использовал curl для получения токена, отображавшего запись в журнале.

Короче говоря, моя вышеупомянутая Swift Playground теперь работает, изменяя request.httpMethod на "POST". СПАСИБО ЗА ВСЕ ПОМОЩЬ

...