skip to Main Content

I’ve an app that should call this API:

http://109.168.113.11/Acucgi/G7TestWeb.sh?funzione=charge_pms&utente=WXWX&password=TESTWWW1&azienda=RISTORANTE&modo=Json&fl_ad=A&camera=5&data_del=20231004&codadd[0]=V10&qtaadd[0]=1&impadd[0]=7,80&desadd[0]=Cappuccinos

In my app I’ve developed a class who can call this API, but from iOS 17 I’ve several problem because Apple has updated to RFC 3986 the url encoding.
Here’s my code:

let urlString = "http://109.168.113.11/Acucgi/G7TestWeb.sh?funzione=charge_pms&utente=WXWX&password=TESTWWW1&azienda=RISTORANTE&modo=Json&fl_ad=A&camera=5&data_del=20231004&codadd[0]=V10&qtaadd[0]=1&impadd[0]=7,80&desadd[0]=Cappuccinos"
guard let url = URL(string: urlString) else {
    print("!! url !!")
    return
}
var request = URLRequest(url: sysDatUrl)
request.httpMethod = "GET"
let task = URLSession.shared.dataTask(with: request) { (data, response, error) in
      [MANAGE RESPONSE]
}

By using this code the server answer me an error because my app use the following url:

http://109.168.113.11/Acucgi/G7TestWeb.sh?funzione=charge_pms&utente=WXWX&password=TESTWWW1&azienda=RISTORANTE&modo=Json&fl_ad=A&camera=5&data_del=20231004&codadd%5B0%5D=V10&qtaadd%5B0%5D=1&impadd%5B0%5D=7,80&desadd%5B0%5D=Cappuccinos

As you can see in my url iOS changed the character [ with %5B and ] with %5D. To work with my server I must use the [ and ], if I use the %5B and %5D my integration will not work anymore. There’s a way to keep the character [ and ]?
Thank you

2

Answers


  1. The string that your server requires is not a valid URL, which means that your server implements a protocol that is similar to HTTP, but is not actually HTTP. Apple’s frameworks only support certain protocols, and do not support this non-standard protocol that your server implements. There is no way to express an invalid URL as an URL.

    The best solution is to correct your server so that it decodes HTTP messages properly. That includes handling percent-encoded URIs.

    If cannot or do not wish to modify your server, then you’ll need to implement this custom protocol by hand. Since this is very close to HTTP, that’s pretty easy.

    This is the kind of code you’d write. I haven’t tested it much, but it should hopefully get you one the right path:

    class Client {
        var connection: NWConnection?
    
        // You need to split the host, port, and query. You must encode this "path" exactly
        // as you need it to be sent. It won't be further encoded.
        let host = NWEndpoint.Host("109.168.113.11")
        let port = NWEndpoint.Port(80)
        let path = "/Acucgi/G7TestWeb.sh?funzione=charge_pms&utente=WXWX&password=TESTWWW1&azienda=RISTORANTE&modo=Json&fl_ad=A&camera=5&data_del=20231004&codadd[0]=V10&qtaadd[0]=1&impadd[0]=7,80&desadd[0]=Cappuccinos"
    
        // This is the important method, which constructs an HTTP request by hand.
        // This is where you need to make sure that you send whatever your server requires.
        func sendRequest() {
            let data = Data("""
            GET (path) HTTP/1.1r
            Host: (host)r
            r
            r
            """.utf8)
            connection?.send(content: data, isComplete: true, completion: .idempotent)
        }
    
        // This is where you handle what is returned
        func handle(data: Data) {
            print(String(decoding: data, as: UTF8.self))
        }
    
        // The rest is somewhat boilerplate code for handling NWConnection.
        // It's roughly based on Eskimo's work.
        // https://forums.swift.org/t/socket-api/19971/6
    
        func start() {
            // `.tcp` here is what you want for HTTP.
            // For HTTPS, you'd change the port to 443 and use `.tls` here.
            let connection = NWConnection(host: host, port: port, using: .tcp)
            connection.stateUpdateHandler = self.stateDidChange(to:)
            self.setupReceive(on: connection)
            self.connection = connection
            connection.start(queue: .main)
        }
    
        func stateDidChange(to state: NWConnection.State) {
            switch state {
            case .setup:
                break
            case .waiting(let error):
                self.connectionDidFail(error: error)
            case .preparing:
                break
            case .ready:
                sendRequest()
            case .failed(let error):
                self.connectionDidFail(error: error)
            case .cancelled:
                break
            @unknown default:
                fatalError()
            }
        }
    
        func setupReceive(on connection: NWConnection) {
            connection.receive(minimumIncompleteLength: 1, maximumLength: 65536) { (data, contentContext, isComplete, error) in
                if let data = data, !data.isEmpty {
                    self.handle(data: data)
                }
                if isComplete {
                    // … handle end of stream …
                    self.stop()
                } else if let error = error {
                    self.connectionDidFail(error: error)
                } else {
                    self.setupReceive(on: connection)
                }
    
            }
        }
        func connectionDidFail(error: Error) {
            print(error)
        }
    
        func stop() {
            // Handle shutting down
        }
    }
    
    
    let client = Client()
    client.start()
    
    Login or Signup to reply.
  2. Same issued, but it is working in iOS 16 and under. Any other solution?

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search