Refresh your memory:

It may happen, that we will have to include in our project the code, which doesn’t comply with the architecture we are presenting in this series. Reasons might be various: we might have legacy code, badly separated by concerns, perhaps we have React Native bridging with a lot of already written Javascript code, for which we have no possibility to change interfacing to the Native side, etc.

This chapter will show, how we shall use URLProtocol and iOS’s simple URL Loading system to turn our modules into classic HTTP API thus making our modules open and compatible with any code in the same way as we would do it for deep links outside the app.

A simple Network Service

We have created a simple NetworkService class, which provides us with two exposed functions get and post . Besides that, we have two private functions. First, the request is pretty much obvious. The only thing that seems a bit fishy is the scheme parameter. It’s handled pretty much simply: if no scheme is passed as a parameter, then it’s set the default to ‘http’. We are happy with this for now.

Then we have the service function since we are reusing this code it in both HTTP methods, get and post . But there is one line of code, which makes all this very interesting: configuration.protocolClasses?.append(URLRouter.self) . This method of URLSessionConfiguration gives the possibility to register our own class URLRouter which inherits from URLProtocol abstract class. Let’ see why is this needed.

URLRouter

This is our implementation of 2 protocols: URLSessionDataDelegate , URLSessionTaskDelegate and above all, subclassing the abstract class URLProtocol (which doesn’t have the best name, perhaps). For all of you, who have ever used old mocking framework for testing URL connections, URLProtocol was usually used for it. Many of us used it directly ourselves, to create our own network stubbing infrastructure. I won’t go too much into details, because there’s quite a lot written about it already, but let me just explain the role of this protocol in our example.

So, what we do with the URLRouter is very simple:

check in override class func canInit(with task: URLSessionTask) -> Bool if URLRequest from the task has the schema , which matches our internal schema, which we defined in previous chapter

if from the task has the , which matches our internal schema, which we defined in previous chapter then we check if URL contains host and path that have a match in our ApplicationRouter

and that have a match in our if the check is positive, then URL Loading system calls our override func startLoading() function, where we simply call an appropriate module through are ApplicationRouter and job done!

Well, not completely, we haven’t created the returning response boilerplate here, but that is not the most important right now. So, what is the next step? Well, the ‘naughty’ module, I guess!

Non-conforming Module

We have created a very simple class, called NonConformingModule , which doesn’t implement any of the architecture, we were talking about in this series from the first chapter onwards. The only thing it does is the login to get bearerToken and this is where the login function in LoginModuleRouter is used, which we mentioned before.

The only thing we need to do is to instantiate this module and call login function and the following will happen:

NonConformingModule calls directly NetworkService as a normal HTTP request, but it passes ‘ tandem ’ as schema and parameters for /login method of LoginModule

calls directly as a normal HTTP request, but it passes ‘ ’ as and parameters for method of NetworkService calls to iOS’s URL loading system in the same way as it would for any other HTTP request.

calls to iOS’s URL loading system in the same way as it would for any other HTTP request. Registered URLRouter class intercepts the URLSessionTask , sees the scheme from URL matches an internal one, confirms interception and creates the instance of itself

class intercepts the , sees the from URL matches an internal one, confirms interception and creates the instance of itself URLRouter calls ApplicationRouter with URL, which opens LoginModule the latter calls LogineModuleRouter and the rest you already know…

This is a showcase, how the URL as a universal access object can be used directly through URL Loading system to access our Module Architecture infrastructure.

Demo Project

Checkout the demo project on the tag 1.0 and look at the code we have talked about up to now in the first 4 chapters.

The story will continue with how we removed the need for explicit Router class and implement the routing implicitly. Read about it in Part 5.