Developers

Bolina SDK (Beta)

Integration Overview



Bolina is deployed via two components: Bolina Client (integrated into the mobile application) and Bolina Server.

The process of integrating our Bolina SDK with your application requires three main steps:

  1. Register at Codavel’s and set up your private area
  2. Integrate Bolina Client with your mobile application
  3. Deploy Bolina Server on your server (or cloud infrastructure)

Here you can find a basic integration scheme.



10,000 Foot View over Bolina

Just before we kick-off this process, here are some deeper insights on Bolina, so you can understand how both SDK pieces work together.

Bolina Client captures the app’s HTTP/HTTPS requests and sends those requests to a Bolina Server using a fast and efficient Bolina link.

Bolina Server receives the Bolina traffic and forwards the content of that traffic by establishing a regular HTTP/HTTPS connection with the original Content Server.

Finally, the latter sends the response back to the mobile application in reverse order.

Bolina protocol establishes a fast and secure end-to-end connection between its peers, based on TLS 1.3. It fully supports HTTP or HTTPS requests, as well as HTTP/2.



Requirements



Server

Minimum requirements:

  • CPU: 2.4GHZ Dual core
  • RAM: 1GB

Recommended requirements:

  • Ubuntu 18.04
  • CPU: 2.4GHZ Quad core
  • RAM: 8GB

Bolina server requires an Internet connection for license validation

 

Mobile

Android

  • Minimum SDK version: 16

iOS

  • Minimum SDK version: 9.0 or higher


Step 1. Registering and setting up



To start the integration process, you need to register and validate your account at Codavel’s. If you haven’t registered yet, you can do it here (don’t forget to validate your account!). If you’re already registered, just log in.

Setting up basically consists of creating a deployment, which allows Codavel to identify and map all entities of your service. Each deployment is associated with a package, which defines the deployment usage, pricing plan, and level of support.

Your deployment will be uniquely identified by a deployment ID (that maps clients with servers and validate licenses) and secret (that authenticates the server and clients). You can fetch both values from your private area, by creating a new deployment.



Creating a new deployment

    1. Go to the Home page of your private area and select New Deployment
      1. Choose a deployment name
      2. Set the application identifiers:
        1. Insert com.codavel.bolina.demo as the Android Package Name
        2. Insert com.codavel.bolina.demo as the iOS Bundle Identifier (available soon)
      3. Select the Free Tier package
      4. Select Create Deployment
    2. Fetch the deployment ID and secret from the created deployment
      1. Select the created deployment, or select the info icon of the created deployment
      2. Copy the deployment ID and secret

Note: Save the deployment ID and secret, they will be necessary to configure the Bolina Server and the mobile application.



Step 2. Integrating Bolina Client



Given that HTTP and HTTPS traffic must be captured on the app, Bolina Client is provided in an SDK that integrates with the most popular HTTP libraries used. It is now available for Android and iOS:

If your app does not use any of the previous HTTP libraries, Bolina Client SDK can also be used as a regular HTTP proxy, on both platforms, please contact us.



Android

On Android, Bolina Client SDK can be integrated directly into the following HTTP libraries:

On all approaches, you need to include the Bolina Client SDK repository to the app’s build.gradle, by adding the following lines:

allprojects {
        repositories {
            maven { url "https://artifact.codavel.com:8081/artifactory/android" }
        }
    }


OKHTTP v2.7+

If you’re integrating Bolina Client SDK in an app that uses OKHTTP v2.7+, just import the library (after importing the repository, don’t forget!), by adding it to the build.gradle file:

 ...
   implementation 'com.codavel.bolina:interceptor_okhttp2:0.9.21'

 

Then, enable Bolina SDK on the app after creating the OKHTTP client:

import com.codavel.bolina.interceptor.okhttp2.CvlOkHttp2Interceptor;
  ...
  OkHttpClient client = new OkHttpClient();
  client.interceptors().add(newCvlOkHttp2Interceptor();

 

Make sure that before performing HTTP requests you import and start the interceptor passing the application Context:

import com.codavel.bolina.interceptor.okhttp2.InterceptorSingleton;
  …
InterceptorSingleton.startInterceptor(getApplicationContext());

 

You should also stop the interceptor whenever you don’t need it, by running:

...
InterceptorSingleton.getInstance().stopInterceptor();
...


OKHTTP v3.0+

If you’re integrating Bolina Client SDK in an app that uses OKHTTP v3.0+, import the library (after importing the repository, don’t forget!), by adding it to the build.gradle file:

 android {
    defaultConfig {
        ...
        resValue "string", "BOLINA_DEPLOY_ID", ""
        resValue "string", "BOLINA_SECRET_ID", ""
    }
}
dependencies {
    ...
    implementation 'com.codavel.bolina:interceptor_okhttp3:0.9.30'
}


Then, enable Bolina SDK on the app when creating the OKHTTP client:

import com.codavel.bolina.interceptor.okhttp3.CvlOkHttp3Interceptor;
  ...
  OkHttpClient client = new OkHttpClient.Builder()
    .addInterceptor(new CvlOkHttp3Interceptor())
    .build();

 

Make sure that before performing HTTP requests you import and start the interceptor passing the application Context:

import com.codavel.bolina.interceptor.okhttp3.InterceptorSingleton;
 ...
InterceptorSingleton.startInterceptor(getApplicationContext());

 

You should also stop the interceptor whenever you don’t need it, by running:

...
 InterceptorSingleton.getInstance().stopInterceptor();
...


HTTPURLConnection

If you’re integrating Bolina Client SDK in an app that uses HTTPURLConnection, import the library (after importing the repository, don’t forget!), by adding it to the build.gradle file:

android {
    defaultConfig {
        ...
        resValue "string", "BOLINA_DEPLOY_ID", ""
        resValue "string", "BOLINA_SECRET_ID", ""
    }
}
dependencies {
    ...
    implementation 'com.codavel.bolina:interceptor_urlconn3:0.9.30'
}


Then, enable Bolina SDK on the app before performing an HTTP request:

  import com.codavel.bolina.interceptor.urlconn.InterceptorSingleton;
  ...
  InterceptorSingleton.startInterceptor(getApplicationContext());

 

You should also stop the interceptor whenever you don’t need it, by running:

...
InterceptorSingleton.getInstance().stopInterceptor();
...


Android HTTP Proxy

To use Bolina Client in proxy mode, the app must redirect all intended traffic to Bolina Client proxy, which is listening for HTTP requests on the localhost.

When Bolina Client works as an HTTP proxy, it does not accept HTTPS requests. Enabling it would require certificate pinning, making its setup more complex. However, security is provided natively by the Bolina fast link, given that it provides end-to-end encryption, based on TLS 1.3.

No changes are required on the original Content Server side, given that Bolina Server will send regular HTTPS requests to the original Content Server.

To integrate Bolina Client SDK as an HTTP proxy in an app, import the library (after importing the repository, don’t forget!) by adding it to the build.gradle file:

android {
    defaultConfig {
        ...
        resValue "string", "BOLINA_DEPLOY_ID", "<APP_ID>"
        resValue "string", "BOLINA_SECRET_ID", "<API_KEY>"
    }
}
dependencies {
    ...
    implementation 'com.codavel.bolina:proxy:0.9.3'
}

 

Then, enable Bolina Client proxy before any request by using the line:

ProxySingleton.startProxy(getApplicationContext());

 

To get the port where the Bolina Client proxy is listening for requests use the following line:

int port = ProxySingleton.getInstance().bolinaProxyPort

 

After enabling the Bolina Client proxy, all HTTP requests must be sent to the proxy that is listening for request on port on the localhost in the following format:

http://localhost:<port>/?url=<original_url>

 

All HTTP requests made to Bolina Client proxy must include a random token in an HTTP header with the name “Codavel-Token”. The token can be obtained after starting the service with the following line:

String token = ProxySingleton.getInstance().bolinaProxyToken


iOS

On iOS, Bolina Client SDK can be integrated directly into the following HTTP libraries:

On all approaches, Bolina Interceptor is distributed using CocoaPods, a dependency manager for Objective-c and Swift. To install CocoaPods run the following commands in Terminal.app:

sudo gem install cocoapods
pod setup

 

Then, you’ll need to create a file named ‘Podfile’ in the same directory as your Xcode project (.xcodeproj) file with the following content:

target "MyTargetName" do
     platform :ios, '9.0'
     use_frameworks!

     Pod 'BolinaInterceptor', 
:http=>'https://artifact.codavel.com:8081/artifactory/ios/BolinaInterceptor_0.9.27.zip'
end 

 

Now you can install the dependencies in your project using the command:

pod install

 

To build your app with the dependencies, you need to open the generated Xcode workspace (.xcworkspace) instead of the project file:

open <YourProjectName>.xcworkspace


NSURLSession

If you’re integrating Bolina Client SDK in an app that uses NSURLSession, enable the Bolina Client (after importing the repository, don’t forget!) before any request (a good place would be the :didFinishLaunchingWithOptions: method in your AppDelegate):

...

Objective-c

    #import <BolinaInterceptor/BolinaInterceptor.h>

[BolinaInterceptor startInterceptor:@"<APP_ID>" withSecret:@"<APP_SECRET>"];


Swift

    #import  BolinaInterceptor

BolinaInterceptor.start(<APP_ID>, withSecret: <APP_SECRET>)

 

Also, make sure you stop the interceptor whenever you don’t need it:

Objetive-c

    [BolinaInterceptor stopInterceptor];


Swift

    BolinaInterceptor.stop()


AFNetworking

If you’re integrating Bolina Client SDK in an app that uses AFNetworking, enable the Bolina Client (after importing the repository, don’t forget!) before any request (a good place would be the :didFinishLaunchingWithOptions: method in your AppDelegate):

 #import <BolinaInterceptor/BolinaInterceptor.h>
    ...
    NSURLSessionConfiguration *configuration = [NSURLSessionConfiguration defaultSessionConfiguration];
    NSArray *protocols = [NSArray arrayWithObjects:[CdvlURLProtocol class], nil];
[configuration setProtocolClasses:protocols];

    AFURLSessionManager *manager = [[AFURLSessionManager alloc] initWithSessionConfiguration:configuration];


Then, add the Bolina interceptor
as a configuration of AFURLSessionManager and use that session manager to perform the HTTP requests:

   #import <BolinaInterceptor/BolinaInterceptor.h>

    ...
    NSURLSessionConfiguration *configuration = [NSURLSessionConfiguration defaultSessionConfiguration];
    NSArray *protocols = [NSArray arrayWithObjects:[CdvlURLProtocol class], nil];
[configuration setProtocolClasses:protocols];

    AFURLSessionManager *manager = [[AFURLSessionManager alloc] initWithSessionConfiguration:configuration];

...

 

Also, make sure you stop the interceptor whenever you don’t need it:

 [BolinaInterceptor stopInterceptor];


Alamofire

If you’re integrating Bolina Client SDK in an app that uses Alamofire, enable the Bolina Client (after importing the repository, don’t forget!) before any request (a good place would be the :didFinishLaunchingWithOptions: method in your AppDelegate):

  #import BolinaInterceptor
    ...
     BolinaInterceptor.start(<APP_ID>, withSecret: <APP_SECRET>)


Then, add the Bolina interceptor
as a configuration of Alamofire.SessionManager and use that session manager to perform the HTTP requests:

 #import BolinaInterceptor

    ...
     let configuration = URLSessionConfiguration.default
        if configuration.protocolClasses != nil {
            configuration.protocolClasses!.insert(CdvlURLProtocol.self, at: 0)
        }

        manager = Alamofire.SessionManager(configuration: configuration)

...


Also, make sure you stop the interceptor whenever you don’t need it:

BolinaInterceptor.stop()


iOS HTTP Proxy

To use Bolina Client in proxy mode, the app must redirect all intended traffic to  Bolina Client proxy, which is listening for HTTP requests on the localhost.

When Bolina Client works as an HTTP proxy, it does not accept HTTPS requests. To enable it would require certificate pinning, making its setup more complex. However, security is provided natively by the Bolina fast link, given that it provides end-to-end encryption, based on TLS 1.3.

No changes are required on the original Content Server side, given that Bolina Server will send regular HTTPS requests to the original Content Server.

Bolina Proxy is distributed using CocoaPods, a dependency manager for Objective-c and Swift. To install CocoaPods run the following commands in Terminal.app:

sudo gem install cocoapods
pod setup


Then, you’ll need to create a file named ‘Podfile’ in the same directory as your Xcode project (.xcodeproj) file with the following content:

target "MyTargetName" do
     platform :ios, '9.0'
     use_frameworks!

     Pod 'BolinaInterceptor', :http=>'https://artifact.codavel.com:8081/artifactory/ios/BolinaProxy_0.9.7.zip'
end


Now you can install the dependencies in your project using the command:

pod install


To build your app with the dependencies, you need to open the generated Xcode workspace (.xcworkspace) instead of the project file:

 open <YourProjectName>.xcworkspace

 

To integrate Bolina Client SDK as an HTTP proxy in an app, after importing the repository, simply enable the Bolina Client proxy before any request (a good place would be the :didFinishLaunchingWithOptions: method in your AppDelegate):

Objective-c 

#import <BolinaProxy/BolinaProxy.h>
    ...
    int port = [BolinaProxy startProxy:@"<APP_ID>" withSecret:@"<APP_SECRET>"]

Swift

   import BolinaProxy

    let port = BolinaProxy.start(info.object(forKey: <APP_ID>) as? String, withSecret: info.object(forKey: <APP_SECRET>) as? String)


After enabling the Bolina Client proxy, all HTTP requests must be sent to the proxy that is listening for request on
port on the localhost in the following format:

http://localhost:<port>/?url=<original_url>

 

To ensure that the requests processed are only those sent by the entity that started the proxy, we required that all HTTP requests made to Bolina Client proxy include a random token in an HTTP header with the name “Codavel-Token”. The token can be obtained after starting the service with the following line:

Objective-c
NSString *token = [BolinaProxy getBolinaToken];


Swift
let token = BolinaProxy.getBolinaToken()


Step 3. Deploying Bolina Server



The Bolina Server consists of a Docker container and it behaves like a regular HTTP proxy. It receives a request from an app with Bolina Client and forwards these requests to the original Content Server, using a regular HTTP/HTTPS request. It does not require any changes or modifications to the original Content Servers.

No changes to the original content servers are required. 



Where to Install?

Bolina Server can be deployed in any region, between the client and the original content server. If your service makes use of multiple regions and you want to speed up HTTP traffic for every user, we recommend you to place them in the same regions of your Content Servers.



Is it scalable?

Given its container nature, Bolina Server is horizontally scalable and can be deployed in any cloud environment. We recommend the usage of auto-scaling groups of Bolina Server instance, each containing a single container. The instances on these auto scaling groups can be scaled using CPU, memory and throughput metrics.



Configuring the Discovery Mechanism: General

Bolina Servers employ a server discovery mechanism based on DNS querying. This mechanism relies on the capability of Bolina Server instances to register on a DNS zone when they become alive and to de-register when they are shut down.

This discovery mechanism can be easily configured in a cloud environment by following these steps:

  1. Create a new DNS Hosted Zone inside DNS Zone Manager
    • If you are creating a deployment for a service named serviced, we recommend you to create a domain like serviced.example.com.
    • In a multi-cluster Bolina Server setup, a Bolina Server cluster can be identified by their prefix.
      • A European Bolina Server cluster can be identified as eu.serviced.example.com
      • An American Bolina Server cluster can be identified as us.serviced.example.com
      • Identifying Bolina Server clusters this way allows Bolina Clients to make use of DNS latency or region routing.
  2. Allow scaling events, such as Bolina Server instance initiation and Bolina Server instance termination, to notify a lambda function to update the DNS Zone Manager
  3. Create a new lambda function to update the DNS Zone Manager with the Bolina Server auto-scaling group events.


Configuring the Discovery Mechanism: AWS

To configure the discovery mechanism in an AWS environment, you should:

  1. Create a new DNS Hosted Zone inside Route 53
  2. Create a new Simple Notification Service (SNS) topic
  3. Associate a newly created SNS topic to a Bolina Server auto-scaling group
  4. Create a new IAM role for the update Lambda function
  5. Create a Lambda function to update the Route 53 with the Bolina Server auto-scaling group events


Load Balancing

Load balancing between multiple Bolina Servers is achieved via the previously described DNS querying mechanism. The Bolina Client component is responsible to query for servers in a specific domain and manages the life-cycle of that connection. That way, if a Bolina Client wishes to communicate again with a server that it has previously communicated with, it can perform a true 0-RTT handshake.



Sample Project



We have built a Sample Project to get you into Bolina very quickly. It will only take 30 minutes to set it up and see Bolina’s performance in your own environment. That’s why we highly recommend you to start with this.

The Sample Project includes a content server, a network emulator tool and a demo app. To set it up, you just have to follow this guide.