admin管理员组

文章数量:1291106

I am trying to use a proxy with auth in Swift. I finally got it working using NWConnection. And I can see from my proxy server that it's actually getting the request from my iOS app when I call this function. However I get the error response below. I am assuming something about my request to httpbin is wrong but I have not been able to figure it out. The proxy in the array is working and feel free to use it if you want to test.

Connected to proxy: resi.wealthproxies
Response from proxy resi.wealthproxies: HTTP/1.1 400 Bad Request

Server: awselb/2.0

Date: Thu, 13 Feb 2025 21:31:28 GMT

Content-Type: text/html

Content-Length: 122

Connection: close

<html>

<head><title>400 Bad Request</title></head>

<body>

<center><h1>400 Bad Request</h1></center>

</body>

</html>
func averageProxyGroupSpeed(proxies: [String], completion: @escaping (Int, String) -> Void) {
    let numProxies = proxies.count
    if numProxies == 0 {
        completion(0, "No proxies")
        return
    }

    var totalTime: Int64 = 0
    var successCount = 0
    let group = DispatchGroup()
    let queue = DispatchQueue(label: "proxyQueue", attributes: .concurrent)
    let lock = NSLock()

    let shuffledProxies = proxies.shuffled()
    let selectedProxies = ["resi.wealthproxies:8000:akzaidan:x0if46jo-country-US-session-niwtz2y7-duration-60"]

    for proxy in selectedProxies {
        group.enter()
        queue.async {
            let proxyDetails = proxy.split(separator: ":").map(String.init)
            guard proxyDetails.count == 4,
                  let port = UInt16(proxyDetails[1]) else {
                completion(0, "Invalid proxy format")
                group.leave()
                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.tcp
            let privacyContext = NWParameters.PrivacyContext(description: "ProxyConfig")
            privacyContext.proxyConfigurations = [proxyConfig]
            parameters.setPrivacyContext(privacyContext)

            let connection = NWConnection(to: .hostPort(host: "httpbin", port: 80), using: parameters)

            let start = Date()
            
            connection.stateUpdateHandler = { state in
                switch state {
                case .ready:
                    print("Connected to proxy: \(proxyDetails[0])")
                                        
                    let httpRequest = """
                    GET  HTTP/1.1\r\n
                    Host: httpbin\r\n
                    Connection: close\r\n
                    Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8\r\n
                    Accept-Encoding: gzip, deflate\r\n
                    Accept-Language: en-US,en;q=0.9\r\n
                    Upgrade-Insecure-Requests: 1\r\n
                    User-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\n
                    \r\n
                    """
                    
                    connection.send(content: httpRequest.data(using: .utf8), completion: .contentProcessed({ error in
                        if let error = error {
                            print("Failed to send request: \(error)")
                            group.leave()
                        } else {
                            // Receive the response
                            connection.receive(minimumIncompleteLength: 1, maximumLength: 4096) { data, _, isComplete, error in
                                defer { group.leave() }
                                
                                if let error = error {
                                    print("Failed to receive response: \(error)")
                                } else if isComplete {
                                    print("complete")
                                    
                                    if let data {
                                        let responseString = String(data: data, encoding: .utf8) ?? ""
                                        print("Response from proxy \(proxyDetails[0]): \(responseString)")
                                    } else {
                                        print("data len is \(data?.count ?? -6)")
                                    }
                                    
                                    let duration = Date().timeIntervalSince(start) * 1000 // Convert to milliseconds
                                    
                                    lock.lock()
                                    totalTime += Int64(duration)
                                    successCount += 1
                                    lock.unlock()
                                } else if let data {
                                    let responseString = String(data: data, encoding: .utf8) ?? ""
                                    print("Response from proxy \(proxyDetails[0]): \(responseString)")
                                } else {
                                    print("Not complete")
                                }
                            }
                        }
                    }))
                case .failed(let error):
                    print("Connection failed for proxy \(proxyDetails[0]): \(error)")
                    group.leave()
                case .cancelled:
                    print("Connection cancelled for proxy \(proxyDetails[0])")
                    group.leave()
                case .waiting(let error):
                    print("Connection waiting for proxy \(proxyDetails[0]): \(error)")
                    group.leave()
                default:
                    break
                }
            }

            connection.start(queue: queue)
        }
    }

    group.notify(queue: DispatchQueue.main) {
        if successCount == 0 {
            completion(0, "Proxies Failed")
        } else {
            let averageTime = Int(Double(totalTime) / Double(successCount))
            completion(averageTime, "")
        }
    }
}

I am trying to use a proxy with auth in Swift. I finally got it working using NWConnection. And I can see from my proxy server that it's actually getting the request from my iOS app when I call this function. However I get the error response below. I am assuming something about my request to httpbin. is wrong but I have not been able to figure it out. The proxy in the array is working and feel free to use it if you want to test.

Connected to proxy: resi.wealthproxies
Response from proxy resi.wealthproxies: HTTP/1.1 400 Bad Request

Server: awselb/2.0

Date: Thu, 13 Feb 2025 21:31:28 GMT

Content-Type: text/html

Content-Length: 122

Connection: close

<html>

<head><title>400 Bad Request</title></head>

<body>

<center><h1>400 Bad Request</h1></center>

</body>

</html>
func averageProxyGroupSpeed(proxies: [String], completion: @escaping (Int, String) -> Void) {
    let numProxies = proxies.count
    if numProxies == 0 {
        completion(0, "No proxies")
        return
    }

    var totalTime: Int64 = 0
    var successCount = 0
    let group = DispatchGroup()
    let queue = DispatchQueue(label: "proxyQueue", attributes: .concurrent)
    let lock = NSLock()

    let shuffledProxies = proxies.shuffled()
    let selectedProxies = ["resi.wealthproxies:8000:akzaidan:x0if46jo-country-US-session-niwtz2y7-duration-60"]

    for proxy in selectedProxies {
        group.enter()
        queue.async {
            let proxyDetails = proxy.split(separator: ":").map(String.init)
            guard proxyDetails.count == 4,
                  let port = UInt16(proxyDetails[1]) else {
                completion(0, "Invalid proxy format")
                group.leave()
                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.tcp
            let privacyContext = NWParameters.PrivacyContext(description: "ProxyConfig")
            privacyContext.proxyConfigurations = [proxyConfig]
            parameters.setPrivacyContext(privacyContext)

            let connection = NWConnection(to: .hostPort(host: "httpbin.", port: 80), using: parameters)

            let start = Date()
            
            connection.stateUpdateHandler = { state in
                switch state {
                case .ready:
                    print("Connected to proxy: \(proxyDetails[0])")
                                        
                    let httpRequest = """
                    GET http://httpbin./get HTTP/1.1\r\n
                    Host: httpbin.\r\n
                    Connection: close\r\n
                    Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8\r\n
                    Accept-Encoding: gzip, deflate\r\n
                    Accept-Language: en-US,en;q=0.9\r\n
                    Upgrade-Insecure-Requests: 1\r\n
                    User-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\n
                    \r\n
                    """
                    
                    connection.send(content: httpRequest.data(using: .utf8), completion: .contentProcessed({ error in
                        if let error = error {
                            print("Failed to send request: \(error)")
                            group.leave()
                        } else {
                            // Receive the response
                            connection.receive(minimumIncompleteLength: 1, maximumLength: 4096) { data, _, isComplete, error in
                                defer { group.leave() }
                                
                                if let error = error {
                                    print("Failed to receive response: \(error)")
                                } else if isComplete {
                                    print("complete")
                                    
                                    if let data {
                                        let responseString = String(data: data, encoding: .utf8) ?? ""
                                        print("Response from proxy \(proxyDetails[0]): \(responseString)")
                                    } else {
                                        print("data len is \(data?.count ?? -6)")
                                    }
                                    
                                    let duration = Date().timeIntervalSince(start) * 1000 // Convert to milliseconds
                                    
                                    lock.lock()
                                    totalTime += Int64(duration)
                                    successCount += 1
                                    lock.unlock()
                                } else if let data {
                                    let responseString = String(data: data, encoding: .utf8) ?? ""
                                    print("Response from proxy \(proxyDetails[0]): \(responseString)")
                                } else {
                                    print("Not complete")
                                }
                            }
                        }
                    }))
                case .failed(let error):
                    print("Connection failed for proxy \(proxyDetails[0]): \(error)")
                    group.leave()
                case .cancelled:
                    print("Connection cancelled for proxy \(proxyDetails[0])")
                    group.leave()
                case .waiting(let error):
                    print("Connection waiting for proxy \(proxyDetails[0]): \(error)")
                    group.leave()
                default:
                    break
                }
            }

            connection.start(queue: queue)
        }
    }

    group.notify(queue: DispatchQueue.main) {
        if successCount == 0 {
            completion(0, "Proxies Failed")
        } else {
            let averageTime = Int(Double(totalTime) / Double(successCount))
            completion(averageTime, "")
        }
    }
}
Share Improve this question asked Feb 13 at 21:36 Ahmed ZaidanAhmed Zaidan 381 gold badge9 silver badges23 bronze badges 4
  • What type of proxies do you use? Regular HTTP, Socks5 or a reverse proxy? – Robert Commented Feb 13 at 21:44
  • Apple requires https, unless you have set the "NSAppTransportSecurity" in your Info.plist to allow http connection. – workingdog support Ukraine Commented Feb 13 at 22:54
  • @workingdogsupportUkraine yes I have already set the NSAppTransportSecurity -> NSAllowsArbitraryLoads -> YES entry in my info.plist – Ahmed Zaidan Commented Feb 13 at 23:11
  • regular HTTP proxies require to use the proxy protocol which encapsulates the HTTP protocol. This protocol starts with CONNECT <hostname or IP address]. You should better use a HTTP client library which already implements the HTTP and proxy protocol instead of faking your own HTTP requests. – Robert Commented Feb 14 at 7:56
Add a comment  | 

1 Answer 1

Reset to default 0

The issue was the formatting of the HTTP request within the string. The correct format is:

let httpRequest = "GET /get HTTP/1.1\r\nHost: httpbin.\r\nConnection: close\r\nAccept: */*\r\nUser-Agent: MySwiftApp/1.0\r\n\r\n"

This code enables requests in Swift to utilize a Proxy with Auth. The only way I found to Authenticate a proxy in swift was with NWConnection. All the other native methods didn't work.

import Foundation
import Network

func averageProxyGroupSpeed() {
    var successCount = 0
    let group = DispatchGroup()
    let queue = DispatchQueue(label: "proxyQueue", attributes: .concurrent)
    let lock = NSLock()

    let selectedProxies = ["107.180.132.32:3128:slgayamo:xxeeikxt"]

    for proxy in selectedProxies {
        group.enter()
        queue.async {
            let proxyDetails = proxy.split(separator: ":").map(String.init)
            guard proxyDetails.count == 4,
                  let port = UInt16(proxyDetails[1]) else {
                group.leave()
                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.tcp
            let privacyContext = NWParameters.PrivacyContext(description: "ProxyConfig")
            privacyContext.proxyConfigurations = [proxyConfig]
            parameters.setPrivacyContext(privacyContext)

            let connection = NWConnection(to: .hostPort(host: "httpbin.", port: 80), using: parameters)
            
            let start = Date()
            
            connection.stateUpdateHandler = { state in
                switch state {
                case .ready:
                    print("Connected to proxy: \(proxyDetails[0])")
                                        
                    let httpRequest = "GET /get HTTP/1.1\r\nHost: httpbin.\r\nConnection: close\r\nAccept: */*\r\nUser-Agent: MySwiftApp/1.0\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)")
                            group.leave()
                        } else {
                            connection.receive(minimumIncompleteLength: 1, maximumLength: 4096) { data, _, isComplete, error in
                                defer { group.leave() }
                                
                                if let error = error {
                                    print("Failed to receive response: \(error)")
                                } else if isComplete {
                                    print("complete")
                                    
                                    if let data {
                                        let responseString = String(data: data, encoding: .utf8) ?? ""
                                        print("Response from proxy \(proxyDetails[0]): \(responseString)")
                                    } else {
                                        print("data len is \(data?.count ?? -6)")
                                    }
                                    
                                    let duration = Date().timeIntervalSince(start) * 1000 // Convert to milliseconds
                                    
                                } else if let data {
                                    let responseString = String(data: data, encoding: .utf8) ?? ""
                                    print("Response from proxy \(proxyDetails[0]): \(responseString)")
                                } else {
                                    print("Not complete")
                                }
                            }
                        }
                    }))
                case .failed(let error):
                    print("Connection failed for proxy \(proxyDetails[0]): \(error)")
                    group.leave()
                case .cancelled:
                    print("Connection cancelled for proxy \(proxyDetails[0])")
                    group.leave()
                case .waiting(let error):
                    print("Connection waiting for proxy \(proxyDetails[0]): \(error)")
                    group.leave()
                default:
                    break
                }
            }

            connection.start(queue: queue)
        }
    }

    group.notify(queue: DispatchQueue.main) {
        // Handle completion if needed
    }
}

averageProxyGroupSpeed()

本文标签: Bad HTTP request when using SwiftStack Overflow