http - Manage Cookies on Swift NWConnection - Stack Overflow

Until now I have found no way to use a higher level Swift native method (URlSession for example) to mak

Until now I have found no way to use a higher level Swift native method (URlSession for example) to make a basic GET/POST request using a HTTP proxy that requires AUTH. I have this Stack OverFlow Question dedicated for that, but have had no luck solving it. The only way that works that I have found is shown below using a NWConnection and it's not very clean. A URLSession auto manages cookies so that Set Cookies from a previous request are present in future requests. I am trying to replicate this behavior with NWConnection, but have had no luck.

The response data from an NWConnection includes the response headers at the top. Do I have to manually parse the string and try and extract cookies then add them into the httpRequest string. Is there an easier way?

Also if anyone knows an answer to the question linked above then there is no need to solve this question.

func updateOrderStatusProxy(proxy: String, completion: @escaping (Bool) -> Void) {
    let orderLink = ";

    guard let url = URL(string: orderLink) else {
        completion(true)
        return
    }
    
    let proxyDetails = proxy.split(separator: ":").map(String.init)
    guard proxyDetails.count == 4, let port = UInt16(proxyDetails[1]) else {
        completion(false)
        print("Invalid proxy format")
        return
    }

    let proxyEndpoint = NWEndpoint.hostPort(host: .init(proxyDetails[0]),
                                            port: NWEndpoint.Port(integerLiteral: port))
    let proxyConfig = ProxyConfiguration(httpCONNECTProxy: proxyEndpoint, tlsOptions: nil)
    proxyConfig.applyCredential(username: proxyDetails[2], password: proxyDetails[3])

    let parameters = NWParameters.tls
    let privacyContext = NWParameters.PrivacyContext(description: "ProxyConfig")
    privacyContext.proxyConfigurations = [proxyConfig]
    parameters.setPrivacyContext(privacyContext)

    let host = url.host ?? ""
    let path = url.path.isEmpty ? "/" : url.path
    let query = url.query ?? ""
    let fullPath = query.isEmpty ? path : "\(path)?\(query)"

    let connection = NWConnection(
        to: .hostPort(
            host: .init(host),
            port: .init(integerLiteral: UInt16(url.port ?? 443))
        ),
        using: parameters
    )

    connection.stateUpdateHandler = { state in
        switch state {
        case .ready:

            let httpRequest = "GET \(fullPath) HTTP/1.1\r\nHost: \(host)\r\nConnection: close\r\nAccept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8\r\nUser-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.0.1 Safari/605.1.15\r\nAccept-Language: en-US,en;q=0.9\r\nSec-Fetch-Dest: document\r\nSec-Fetch-Mode: navigate\r\nSec-Fetch-Site: none\r\nPriority: u=0, i\r\n\r\n"
            
            connection.send(content: httpRequest.data(using: .utf8), completion: .contentProcessed({ error in
                if let error = error {
                    print("Failed to send request: \(error)")
                    completion(false)
                    return
                }
                
                readAllData(connection: connection) { finalData, readError in
                    if let readError = readError {
                        print("Failed to receive response: \(readError)")
                        completion(false)
                        return
                    }

                    guard let data = finalData else {
                        print("No data received or unable to read data.")
                        completion(false)
                        return
                    }

                    if let body = String(data: data, encoding: .utf8) {
                        completion(true)

                    } else {
                        print("Unable to decode response body.")
                        completion(false)
                    }
                }
            }))

        case .failed(let error):
            print("Connection failed for proxy \(proxyDetails[0]): \(error)")
            completion(false)

        default:
            break
        }
    }

    connection.start(queue: .global())
}
func readAllData(connection: NWConnection,
                         accumulatedData: Data = Data(),
                         completion: @escaping (Data?, Error?) -> Void) {
    
    connection.receive(minimumIncompleteLength: 1, maximumLength: 65536) { data, context, isComplete, error in
        
        if let error = error {
            completion(nil, error)
            return
        }
        
        let newAccumulatedData = accumulatedData + (data ?? Data())

        if isComplete {
            completion(newAccumulatedData, nil)
        } else {
            readAllData(connection: connection,
                             accumulatedData: newAccumulatedData,
                             completion: completion)
        }
    }
}

Until now I have found no way to use a higher level Swift native method (URlSession for example) to make a basic GET/POST request using a HTTP proxy that requires AUTH. I have this Stack OverFlow Question dedicated for that, but have had no luck solving it. The only way that works that I have found is shown below using a NWConnection and it's not very clean. A URLSession auto manages cookies so that Set Cookies from a previous request are present in future requests. I am trying to replicate this behavior with NWConnection, but have had no luck.

The response data from an NWConnection includes the response headers at the top. Do I have to manually parse the string and try and extract cookies then add them into the httpRequest string. Is there an easier way?

Also if anyone knows an answer to the question linked above then there is no need to solve this question.

func updateOrderStatusProxy(proxy: String, completion: @escaping (Bool) -> Void) {
    let orderLink = "https://us.supreme/checkouts/c/79393a1d2d6098cb2477a49dfd7699bd/thank_you"

    guard let url = URL(string: orderLink) else {
        completion(true)
        return
    }
    
    let proxyDetails = proxy.split(separator: ":").map(String.init)
    guard proxyDetails.count == 4, let port = UInt16(proxyDetails[1]) else {
        completion(false)
        print("Invalid proxy format")
        return
    }

    let proxyEndpoint = NWEndpoint.hostPort(host: .init(proxyDetails[0]),
                                            port: NWEndpoint.Port(integerLiteral: port))
    let proxyConfig = ProxyConfiguration(httpCONNECTProxy: proxyEndpoint, tlsOptions: nil)
    proxyConfig.applyCredential(username: proxyDetails[2], password: proxyDetails[3])

    let parameters = NWParameters.tls
    let privacyContext = NWParameters.PrivacyContext(description: "ProxyConfig")
    privacyContext.proxyConfigurations = [proxyConfig]
    parameters.setPrivacyContext(privacyContext)

    let host = url.host ?? ""
    let path = url.path.isEmpty ? "/" : url.path
    let query = url.query ?? ""
    let fullPath = query.isEmpty ? path : "\(path)?\(query)"

    let connection = NWConnection(
        to: .hostPort(
            host: .init(host),
            port: .init(integerLiteral: UInt16(url.port ?? 443))
        ),
        using: parameters
    )

    connection.stateUpdateHandler = { state in
        switch state {
        case .ready:

            let httpRequest = "GET \(fullPath) HTTP/1.1\r\nHost: \(host)\r\nConnection: close\r\nAccept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8\r\nUser-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.0.1 Safari/605.1.15\r\nAccept-Language: en-US,en;q=0.9\r\nSec-Fetch-Dest: document\r\nSec-Fetch-Mode: navigate\r\nSec-Fetch-Site: none\r\nPriority: u=0, i\r\n\r\n"
            
            connection.send(content: httpRequest.data(using: .utf8), completion: .contentProcessed({ error in
                if let error = error {
                    print("Failed to send request: \(error)")
                    completion(false)
                    return
                }
                
                readAllData(connection: connection) { finalData, readError in
                    if let readError = readError {
                        print("Failed to receive response: \(readError)")
                        completion(false)
                        return
                    }

                    guard let data = finalData else {
                        print("No data received or unable to read data.")
                        completion(false)
                        return
                    }

                    if let body = String(data: data, encoding: .utf8) {
                        completion(true)

                    } else {
                        print("Unable to decode response body.")
                        completion(false)
                    }
                }
            }))

        case .failed(let error):
            print("Connection failed for proxy \(proxyDetails[0]): \(error)")
            completion(false)

        default:
            break
        }
    }

    connection.start(queue: .global())
}
func readAllData(connection: NWConnection,
                         accumulatedData: Data = Data(),
                         completion: @escaping (Data?, Error?) -> Void) {
    
    connection.receive(minimumIncompleteLength: 1, maximumLength: 65536) { data, context, isComplete, error in
        
        if let error = error {
            completion(nil, error)
            return
        }
        
        let newAccumulatedData = accumulatedData + (data ?? Data())

        if isComplete {
            completion(newAccumulatedData, nil)
        } else {
            readAllData(connection: connection,
                             accumulatedData: newAccumulatedData,
                             completion: completion)
        }
    }
}
Share asked Mar 3 at 21:27 Ahmed ZaidanAhmed Zaidan 711 gold badge9 silver badges24 bronze badges
Add a comment  | 

1 Answer 1

Reset to default 0

Made a Swift TLS Client. Please start of GitHub. Literally the only swift tls client on GitHub.

https://github/ak3zaidan/Swift-TLS-Client

发布者:admin,转转请注明出处:http://www.yc00.com/questions/1745071055a4609548.html

相关推荐

  • http - Manage Cookies on Swift NWConnection - Stack Overflow

    Until now I have found no way to use a higher level Swift native method (URlSession for example) to mak

    15小时前
    40

发表回复

评论列表(0条)

  • 暂无评论

联系我们

400-800-8888

在线咨询: QQ交谈

邮件:admin@example.com

工作时间:周一至周五,9:30-18:30,节假日休息

关注微信