Apple Networking Feedback

Recently Quinn, an engineer on the Developer Technical Support team at Apple, posted a request for feedback on Apple’s networking APIs. Here are his questions and my answers:

  1. If your product is still using the deprecated NSURLConnection or NSURLDownload APIs, is that because:

    • (A) You just haven’t got around to adopting NSURLSession
    • (B) NSURLSession is missing some feature that you need
    • (C) Other

    For B and C, please provide some details.

    Answer: There are times I’ve longed for the NSURLConnection API. In many respects, I find its execution model to be simpler, where a single connection has a single corresponding delegate. That’s really simple to follow and is the main thing I miss about the NSURLConnection API. However, I do not miss its reliance on a runloop; I’ve had situations where I’ve had to manually spin up a background thread and pump its runloop in order to keep NSURLConnection off the main thread.

  2. If your product is still using the deprecated CFHTTPStream API, is that because:

    • (A) You just haven’t got around to adopting NSURLSession
    • (B) NSURLSession is missing some feature that you need
    • (C) Other

    For B and C, please provide some details.

    Answer: Not applicable.

  3. If your product is still using the FTP protocol, is that because:

    • (A) It’s a legacy feature you haven’t got around to removing
    • (B) Your product interacts with hardware that only supports FTP
    • (C) FTP is an absolute requirement of the folks who pay the bills
    • (D) Other

    For B, C and D, please provide some details.

    Answer: Not applicable. Was it ever applicable to anyone?

  4. If your product is still using the FTP protocol, do you use:

    • (A) NSURLSession
    • (B) NSURLConnection / NSURLDownload
    • (C) CFFTPStream directly
    • (D) A third-party library that uses CFFTPStream
    • (E) A third-party library with its own core FTP code
    • (F) Other

    For D, E or F, please provide some details.

    Answer: Not applicable.

  5. If your product uses a third-party library layered on top of NSURLSession, did you choose that library because:

    • (A) It provides specific functionality you need
    • (B) It has a nicer programming interface
    • (C) Other

    In all cases, please let us know which library you’re using. In case C, please provide some details.

    Answer: (A) and (B).

    Taking AlamoFire as an example, it meets (A) because NSURLSession and friends don’t provide anything in the way of multi-part encoding. You occasionally come across the need for building up a form submission, and having to manually do that all yourself is extremely annoying, especially if that form submission involves streaming files off disk. AlamoFire’s form encoding isn’t perfect (since you can’t really compose NSInputStreams, it essentially just re-builds the entire form submission as a file on disk and then provides a single stream to that), but it’s infinitely better than a non-existent API from NSURLSession and having to roll your own encoder.

    If also meets (B) because AlamoFire generally has a shorter API than NSURLSession provides. And, as I’ll mention at the end, it uses Result<T>, which is amazing.

  6. If your product uses a third-party HTTP[S] library that is not layered on top of NSURLSession (one that uses its own core HTTP code) is that because:

    • (A) It helps with cross-platform compatibility
    • (B) It’s intrinsic to your development environment
    • (C) NSURLSession is missing some feature that you need
    • (D) The third-party library performs better than NSURLSession
    • (E) The third-party library is more reliable than NSURLSession
    • (F) Other

    For C, D, E and F, please provide some details.

    Answer: In the past I’ve used non-NSURLSession HTTP libraries mainly because of (A); when working for a company that offers their product on multiple platforms, it’s pretty common to have a bunch of the core product logic built in cross-platform frameworks (mainly C++).

    Otherwise, I rarely come across a situation where I need to “re-invent” the networking wheel.

  7. If your product uses the HTTP[S] protocol but does not use HTTP/2, is that because:

    • (A) You use HTTP, not HTTPS
    • (B) Your product talks to a variety of HTTP servers, some of which support HTTP/2 and some of which don’t
    • (C) Your product talks to a specific HTTPS server that’s outside of your control
    • (D) Your product talks to a specific HTTPS server that you control but you haven’t yet updated to use HTTP/2
    • (E) Other

    For E, please provide some details.

    Answer: (E): I’ve never had to care about HTTP 1.1 vs HTTP 2

  8. For NSURLSession [*], what are the enhancement requests or bugs that you’d most like to see addressed? Please list up to five in order from most to least desired. Ideally we’d like a list of bug numbers, with all the details in the corresponding bug report.

    [*] This includes the core NSURLSession API and all its related technologies, including:

    • Async API structure (delegates, blocked-based convenience APIs, and so on)
    • Swift integration
    • Requests and responses
    • Caching
    • Cookies
    • Authentication (including credentials and their storage)
    • Background sessions
    • Core HTTP and HTTP/2 protocol implementations
    • Debugging tools
    • Security (HTTPS)
    • Performance
    • Task metrics
    • Task prioritisation
    • Stream tasks

    Answer: I generally don’t have many complaints about the networking stack. Mainly I just want it to be simpler, but if I had to pick some…

    1. Swift integration (mainly better type-safety)
    2. Debugging tools (see answer to #16)
  9. If your app uses the reachability API (SCNetworkReachability, either directly or via a wrapper like the Reachability sample code), is that because:

    • (A) Someone said you needed reachability and you’re not entirely sure why
    • (B) You just haven’t got around to adopting the new waitsForConnectivity support in NSURLSession
    • (C) You want to preflight network requests, that is, you don’t make a request until reachability indicates that it might work
    • (D) You want to know when it’s a good time to retry a failed request
    • (E) You’re using SCNetworkReachabilityCreateWithAddressPair to monitor the state of a specific connection
    • (F) You want to know what type of networking is available, for example, WWAN or Wi-Fi
    • (G) You’re using it solely to update your app’s user interface
    • (H) Other

    For C, we’d really like some details on why you’re preflighting network requests.

    For F, G and H, please provide some general details.

    Answer: (B), (D), (F), and (G).

    I like control. By manually using SCNetworkReachability, I get the control to manually retry requests, update my app user-interface, proactively disable app functionality (why should I keep a sync engine turned on if I “know” the network is off?), and tune certain kinds of requests to the networking interfaces I feel are more appropriate for the app’s functionality (ex: when on WWAN, restrict communication to app-critical things; save WiFi for proactively downloading caches, etc).

    However, the reachability API is archaic. It desperately needs some Swifty love.

  10. If your product works directly on top of the TCP protocol, what API do you use:

    • (A) BSD Sockets
    • (B) CFSocket
    • (C) NSStream
    • (D) NSURLSessionTask
    • (E) NWTCPConnection
    • (F) A third-party library
    • (G) Other

    For F, please let us know which library you’re using. For G, please provide some details.

    Answer: Not applicable.

  11. If you answered the previous question, please provide information about your TLS (aka SSL) use:

    • (A) You don’t need TLS
    • (B) You use the TLS implementation provided by the API you’re using (for example, in NSURLSessionTask you can enable TLS by calling -startSecureConnection)
    • (C) You use Secure Transport to implement TLS
    • (D) You use OpenSSL to implement TLS
    • (E) You use some other third-party TLS library

    For D, please explain why you use OpenSSL. For E, please provide some details.

    Answer: Not applicable, although there are totally valid reasons for bundling OpenSSL in your app because the iOS Security APIs don’t provide enough functionality.

  12. If your product uses BSD Sockets for networking, is that because:

    • (A) It helps with cross-platform compatibility
    • (B) You have existing code that you don’t want to rewrite
    • (C) You’re using UDP, not TCP
    • (D) You’re using one of the more obscure features of BSD Sockets (raw IP, routing sockets, and so on) for which there is no equivalent higher-level API
    • (E) The equivalent higher-level API would otherwise be appropriate but is missing some small feature that you need
    • (F) Your code performs better than the equivalent high-level API
    • (G) Your code is more reliable than the equivalent high-level API
    • (H) Other

    For D through H, please provide some details.

    Answer: Not applicable

  13. Are you interested in adopting the QUIC protocol?

    Answer: I don’t know what QUIC is.

  14. Are there any other existing or future networking protocols that would be useful to your product? Remember that the focus here is on commonly-used user-space networking APIs, so please restrict yourself to protocols that make sense in that context.

    Answer: Web sockets. If you’re connecting to a realtime web service, it’s pretty common to have that implemented via websockets. In the past I’ve poked around at SocketRocket and Starscream. It’d be very nice if that were built-in.

  15. When debugging problems with the networking features of your product, which tools do you typically use?

    • (A) Wireshark
    • (B) Some other packet trace tool
    • (C) A debugging HTTP proxy
    • (D) CFNetwork diagnostic logging
    • (E) sysdiagnose logs
    • (F) Other

    For B, C and F, please provide details.


    (C): Charles Proxy

    (D): I put this in here because I explicitly don’t use it. There’s no obvious way to configure the verbosity of its logging, and it seems like every other release of iOS plagues your console with random spew from the networking layers that is difficult to disable. It’d be nice if this were useful in any degree, but honestly right now it’s an utter waste of console space and just obfuscates my logs.

    (F): Paw ← this is like the best thing ever.

  16. In the context of debugging problems with the networking features of your product, is there a specific tool that you’d like Apple to provide?

    Answer: I want an Instruments template that does HTTP inspection. There are templates for doing the byte-level traffic analysis, but usually I don’t care that much about it. I want a tool that shows me the actual HTTP requests and responses, like what I get in Charles. I want to see the hosts I’m connecting to, the raw HTTP request, various views of the bodies (raw, formatted, interpreted as JSON, interpreted as form encoding, etc), the headers, the latency, etc. And I want to see all this information for the response.

    Ideally, there would be a debug gauge in Xcode that shows a high-level view of this information, and then if I needed deeper analysis I would pop open Instruments to get it.

Other Thoughts: (These don’t particularly fit in to the questions above, so I’m putting them here at the bottom)

There are a couple things that I find annoying about working with NSURLSession in Swift:

  1. It’s a URL session, and not an HTTP session. This means I have to do lots of silly as? casting to make sure things are HTTPURLResponses before proceeding. I would really love to see a specialization of the API that is focused on only the HTTP use-case. I don’t think I’ve ever really needed anything except an HTTP session, and having to dig around the API to figure out what’s HTTP-specific and not and do the type-safe guarding is annoying.

  2. The Swift API desperately needs a Result<T> type. Getting a callback that is a (URLResponse?, Data?, Error?) is supremely annoying to deal with. I’d much rather have a Result<(HTTPURLResponse, Data?)>. That would be way easier to work with.

  3. It would be nice (but not required) to have some sort of protocol-defined serialization/deserialization support for bodies in requests and responses. If I know that I’m going to get back XML or JSON or an Image, it’d be great if I could have a generic way to simply say “execute this request and give me back the image that comes back in the body”.

Related️️ Posts️

The Laws of Core Data
A Better MVC, Part 5: An Evolution
If iPads were meant for kids
Swift Protocols Wishlist
Simplifying Swift framework development
Reading your own entitlements
A Better MVC, Part 4: Future Directions
A Better MVC, Part 3: Fixing Massive View Controller
A Better MVC, Part 2: Fixing Encapsulation
A Better MVC, Part 1: The Problems
Keynote's awesome Outline Mode
iOS Feature Wish: Contact Provider Extensions
Every beginning has an end
Incrementing Build Numbers in Xcode