19
Dec 14

Protocols to Closures in Swift

After releasing Socivy in a very short time, it required some refactoring in the API level. Since MVC pattern is in the foundation of the iOS development, without touching UI components, I can directly refactor only API part of the project.

Well, I highly used protocols in my implementation. For instance, if user makes a request to get available routes in the system, it uses already constructed SocivyAvailableRouteAPI to make fetch routes from the API. It handles the requests asynchronously and returns the response by calling delegate function like routeRequestDidFinish(), this is enormously helpful for me to separate controllers and models however, after increases in our API methods, unfortunately it increased protocols and unnecessary repetitions.

Not only this, increased a spaghetti code, it also affected the compile time. A big advantage was that everything was explicit, and implementation was pretty fast, it helped  our tight development schedule.

I will be adding a chatting feature for Socivy for the end of the semester for CS392 course. Before starting the feature, I thought it would be better to refactor the code and use closures and Factory and a kind of Facade pattern to reduce redundancy and decrease number of classes.

Because of the architecture of SocivyAPI security, it requires re-logins sometimes. Whenever an API request fails due to expired session, it should automatically restore and continue the calling the action and trigger the callback to update the user interface. I subclassed NSURLConnection, added completionHandler and errorHandler:

  • completionHandler: (response:NSMutableData->())?
  • errorHandler: (error:NSError->())?

Basically if request returns successfully or with an error, it will be handled by these handlers. Another problem was the data validation, NSMutableData must be a convertible to a valid JSON object. For that, I implemented a Model layer that gets exactly same handlers but this time completionHandler gets JSON as parameter. In that layer, I also handled session expires, it automatically re-logins after the validation, so no need for extra care for all methods that require authentication.

However, delegates must be removed after these, since the protocols are removed. For instance:

It is currently on ViewController side:

With closures, I think it is much cleaner than delegates, you can handle different cases, much better than delegates. On the other hand, you should never do this:

This is not very expressive, and would eventually lead to a callback hell.


21
Nov 13

Dilixiri, Securing an REST API and OzU-EMS

Screen Shot 2013-11-21 at 11.00.14 PM

In 2010, I was working on moving web app of Dilixiri to a iPhone app. (Dilixiri is a Turkish-English and English-Turkish sentence translation app.) The problem was of that time, our small team does not know anything about handling data between different softwares. I knew some stuff about TCP/UDP because of my PyQt book‘s example. I first thought about making a TCP server on the server side and then since Dilixiri’s page is a Django based HTML page that simply uses a HTML POST to translate a sentence, I tried to do the same thing as web browser does.

For two major versions of Dilixiri (1.0-2.0), it worked pretty well. I was simulating what web browser does by using actually same headers that what a browser does while making a request. Another problem was parsing response(HTML file). I used some simple “split( )” functions to find the text that I am looking for. (Now I feel embarrassed about it, especially after learning about the side effects and regex.)

However in 2012, instead of making another big mistake, I made something right without knowing that it is the best practice for Dilixiri(partially).  In 3.0, I changed how the app handles the translation by using JSON in the middle. But I was afraid of third party users who could easily use it on their software. I got to think about a solution to handle it.

My first attempt was, implementing using GET parameters based API. So in this case:
http://dilixiri.com/api/?translate=hello&from=eng
But if somebody discovers this url pattern, it can be used without permission. Despite my first attempt that is in engineering may referred as a very bad implementation, this time I thought about giving an API key like some of the famous web services do. But if I request a translation:
http://dilixiri.com/api/?translate=hello&from=eng&key=123123123123
It is the same thing. This request can be listened in the network and be repeated again. (like Man-in-middle-attack) At the end, I implemented something like:
http://dilixiri.com/api/?translate=hello&from=eng&md5=ef800e8….9ff878e50a886d2

I hashed request and API key same time that for every request, I use a different hash number. By implementing this, still relay attacks can be done but a fully working API that makes translations as same as Dilixiri became impossible without knowing API key.

A big drawback is you can only use just a one API key. Another is relay attacks. For an API like Dilixiri, it is not a big deal but when you think about other services. It should be handled, both immunity from relay attacks and being able to serve more than one clients.

How to achieve this ? Nowadays, in Computer Club, we are working on OZU-EMS(Özyeğin University Event Management System) that allows clubs to send their club events to this system and system will share it on its mobile app, web page and etc. Also it also saves time in the university side. (A professor that is responsible for the club, and the social coordinator in the university accept or reject this event request by the club easily in a painless way.) We were looking for a way to make an API to serve these events for different clients that are outside of the server. Such as an Android app or a Kinect based Windows app(CreativeOzu(another club) is working for that.). After a small research, I found that my Dilixiri 3.0 approach was the correct one, but lot’s of clients and different API keys, there should be a public key and private key. I personally wanted to share these links for detailed explanation about implementing this solution:

There should be other methods such as implementing HTTPS based service or something else. But I think such kind of custom solutions are better, if you wanted to handle and understand by yourself.