代码之家  ›  专栏  ›  技术社区  ›  Paul Peelen

Vapor HTTPClient跟踪重定向

  •  2
  • Paul Peelen  · 技术社区  · 6 年前

    我不知道如何跟踪来自外部URL的重定向。我访问的网址是因为某种原因给了我301,即使我没有收到它的邮差。我想知道怎样才能让httpclient跟踪这个重定向,或者我是否做了什么错误来获得301。

    我确实读过 this PR 但我认为这已经不相关了。也不 HTTPClient documentation 封面重定向。 在下面的示例中,我将用户代理设置为与邮递员相同,以便尽可能模拟邮递员的请求。

    我的代码到目前为止:

    import Vapor
    import HTTP
    
    protocol DataFetching {
      func getFromURL(_ url: URL, on worker: Worker) throws -> Future<HTTPResponse>
    }
    
    class DataFetcher: DataFetching {
    
      enum Error: Swift.Error {
        case unknown
      }
    
      func getFromURL(_ url: URL, on worker: Worker) throws -> Future<HTTPResponse> {
    
        guard let host = url.host else { throw Error.unknown }
    
        var headers = HTTPHeaders()
        headers.replaceOrAdd(name: .userAgent, value: "PostmanRuntime/7.4.0")
        headers.replaceOrAdd(name: .accept, value: "*/*")
        headers.replaceOrAdd(name: .cacheControl, value: "no-cache")
        headers.replaceOrAdd(name: .applyToRedirectRef, value: "true")
        headers.replaceOrAdd(name: .acceptEncoding, value: "gzip, deflate")
    
        let httpRequest = HTTPRequest(method: .GET, url: url, version: HTTPVersion(major: 1, minor: 1), headers: headers)
    
        return HTTPClient.connect(hostname: host, on: worker).flatMap { client in
          return client.send(httpRequest)
        }
      }
    }
    

    我错过了什么?

    1 回复  |  直到 6 年前
        1
  •  3
  •   Paul Peelen    6 年前

    我最终使用了urlsession。这是我的最终结果,对我来说很好:

    enum DataFetcherErrors: Error {
      case didNotRecieveData
      case unknown
    }
    
    protocol DataFetching {
      func getFromURL(_ url: URL, on worker: Worker) throws -> Future<Data>
    }
    
    class DataFetcher: DataFetching {
    
      let urlSession: URLSession
      private var headers = [
        "Accept": "*/*",
        "User-Agent": "DataFetcher",
        "Cache-Control": "no-cache",
        "Accept-Encoding": "gzip, deflate"
      ]
    
      init(urlSession: URLSession = .shared) {
        self.urlSession = urlSession
      }
    
      func getFromURL(_ url: URL, on worker: Worker) throws -> Future<Data> {
        let promise = worker.eventLoop.newPromise(Data.self)
    
        request(url: url) { (data, response, error) in
          if let error = error {
            promise.fail(error: error)
          }
    
          guard let data = data else {
            promise.fail(error: DataFetcherErrors.didNotRecieveData)
            return
          }
    
          promise.succeed(result: data)
        }
    
        return promise.futureResult
      }
    }
    
    private extension DataFetcher {
    
      func request(url: URL, completionHandler: @escaping ((Data?, URLResponse?, Error?) -> Void)) {
        var request = URLRequest(url: url)
        request.httpMethod = "GET"
    
        headers.forEach { fieldName, value in
          request.setValue(value, forHTTPHeaderField: fieldName)
        }
    
        let task = urlSession.dataTask(with: request, completionHandler: completionHandler)
        task.resume()
      }
    }