Making network request is a common task in iOS app development. If your company has its own backend team, it's likely that there's different environments you have to set up for your network code: usually Staging & Production environment. There might be some differences between those:
- Staging might use HTTP while Production always use HTTPS
- You might need to launch a
localhostserver - Your staging domain and production domain is different
- Your Staging domain needs a special proxy config.
Here's how to handle those differences using iOS's built-in URLSession:
Understanding URLComponents
URLComponents is a type-safe tool to parse URL information to scheme (HTTPS), host (domain), URL path and query items; and helping you constructing a URL from those elements, with percent encoding included.
Intitialize URLComponents with this convenient extension:
extension URLComponents {
init(scheme: String, host: String, path: String, queryItems: [URLQueryItem]) {
self.init()
self.scheme = scheme
self.host = host
self.path = path
self.queryItems = queryItems
}
}
Let's create an enum for the scheme we will handle
enum URLScheme : String {
case HTTPS = "https"
case HTTP = "http"
}
Configure environments
Staging domain
It's obvious from the URLComponents type that property .scheme will take HTTP or HTTPS and property .host will take your special domain for staging
Local host
For a local host server, you also need to configure the port, where URLComponents.port come in:
self.host = "localhost"
self.scheme = URLScheme.HTTP.rawValue // "HTTP"
self.port = 8080
Special proxy
If your company requires a special proxy in a special Wifi for testing Staging server or internal stuffs, you probably had to deal with iPhone's Wifi settings:
However, this kind of config also make the phone unable to connect to the Internet. Fortunately, you can always add an embedded proxy to any URLSessionConfiguration by taking advantage of property .connectionProxyDictionary.
public func getProxyConfig() -> URLSessionConfiguration {
let proxyConfiguration = URLSessionConfiguration.default
proxyConfiguration.requestCachePolicy = URLRequest.CachePolicy.reloadIgnoringLocalCacheData
proxyConfiguration.connectionProxyDictionary = [AnyHashable: Any]()
proxyConfiguration.connectionProxyDictionary?[kCFNetworkProxiesHTTPEnable as String] = 1
proxyConfiguration.connectionProxyDictionary?[kCFNetworkProxiesHTTPProxy as String] = "your.company.internal.domain"
proxyConfiguration.connectionProxyDictionary?[kCFNetworkProxiesHTTPPort as String] = 9502
proxyConfiguration.connectionProxyDictionary?[kCFStreamPropertyHTTPSProxyHost as String] = "your.company.internal.domain"
proxyConfiguration.connectionProxyDictionary?[kCFStreamPropertyHTTPSProxyPort as String] = 9502
proxyConfiguration.timeoutIntervalForRequest = 30.0
proxyConfiguration.timeoutIntervalForResource = 60.0
return proxyConfiguration
}
kCFStreamPropertyHTTPSProxyHost, kCFNetworkProxiesHTTPProxy is for HTTP Proxy Server. kCFNetworkProxiesHTTPPort and kCFStreamPropertyHTTPSProxyPort is for HTTP Proxy Port.
Finally, with newly created URLSessionConfiguration instance, using +[NSURLSession sessionWithConfiguration:] or URLSession.init(configuration: URLSessionConfiguration) to create your own URLSession. Use this new URLSession for your own network calls, and the rest, including web views, system services stay connecting to the Internet normally.
Enjoy your testable networking code!!!

Top comments (2)
Great article — love how you handle staging, proxy, and localhost configs in iOS using URLSession. I’ve been using ServBay in my local setups too, and it really helps me switch between environments cleanly (dev/staging/prod) without messing with configs
Good Article taking a similar approach but I can't get it to work, do you know if this approach is still valid on iOS 13.5 ? URLSession goes via proxy as expected when running from playground but the same code stop to work when on the simulator.