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
localhost
server - 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 (1)
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.