Kotlin Training Program

DOWNLOAD APP

FEEDBACK

Connecting to the Internet

Overview

We generally use internet for browsing websites via a Web browser. Several applications also use internet for connecting with server and exchanging data. For example, Uber app needs a server to store vehicles data. When the app is launched, it connects to the server and fetches data about nearby vehicles. When a ride is requested, server is informed about ride details to notify the drivers.

How does this data exchange work on internet? Through well defined protocols / rules. Each protocol has its own connection mechanism and request response formats. One such widely used protocol is HTTP (Hypertext Transfer Protocol). All web browsers use HTTP to request webpages. Applications & Server also use HTTP APIs for communication. URLs are used to locate a resource on the server. For example,

HTTP Request Methods

HTTP supports multiple request methods.

GET request

The most basic HTTP request method is GET. GET request is used to simply fetch the data located by a URL. Web browsers send a HTTP GET request when a webpage is requested. Examples :

  • HTML response :

     GET HTTP/1.1
    Host : google.com
    
    200 OK
    
    <!DOCTYPE html>
    <html>
    ...
    </html>
     
  • JSON response :

     GET /vehicles?location=23.4,74.5 HTTP/1.1
    Host : my-uber.com
    
    200 OK
    
    {
    		"status": "success",
    		"data": {
    				"vehicles": [
    						{...}, {...}, {...}
    				]
    		}
    }
     

POST request

Another widely used HTTP method is POST. In contrast to GET, POST is used to submit a data payload along with requesting data. It is commonly used for log in purpose to send username and password to the server. Example :

  • Login

     POST /login HTTP/1.1
    Host : thestreamliners.in
    Content-Type: application/json
    
    // Payload :
    {
    		"username": "alpha123"
    		"password": "FJF5@454%KDJF"
    }
    
    // Response :
    200 OK
    
    <!DOCTYPE html>
    <html>
    ...
    </html>
     
  • Uber ride request

     POST /ride HTTP/1.1
    Host : my-uber.com
    Content-Type: application/json
    
    // Payload :
    {
    		"service": "Sedan"
    		"destination": {...}
    }
    
    // Response :
    200 OK
    
    {
    		"status": "success"
    }
     

There are more HTTP request methods but we shall work with GET and POST methods only. You can learn more about HTTP request methods here.

HTTP Status Codes

Along with response, servers send HTTP Status code also. It is a numeric value used to know the response status. Following are the most commonly used HTTP Status Codes :

  • 200 - OK : Successful request
  • 404 - Not Found : Resource not found
  • 500 - Internal Server Error

You can learn more about HTTP response status codes here.

Let us now learn how to send HTTP requests to Web APIs programmatically.

Sending GET request

In Kotlin, we can send HTTP GET request with just single line of code :

 val response = URL(/* url */).readText()
 

Example :

 fun main() {
    val response = URL("http://numbersapi.com/7/math").readText()
    println("response = $response")
}
 

NumbersAPI is a free Web API that provides facts about numbers. The above example requests a mathematical fact about the number 7.

Behind the scenes

Let’s dig a bit deeper and understand how the above code functions internally. Following are the basic steps required to perform a HTTP GET request :

  1. Create a URL object for required resource url

     val url = URL(/* url */)
     
  2. Establish a connection using URL#openConnection() function

     val connection = url.openConnection() as HttpURLConnection
     
  3. Create an InputStream instance for reading response

     val inputStream = connection.inputStream
     
  4. Read the response as ByteArray using InputStream#readBytes() function and convert it to a string

     val response = String(inputStream.readBytes())
     
  5. Check the response status

     // If not 'OK', throw error
    if (connection.responseCode != HttpURLConnection.HTTP_OK) {
        error("${connection.responseCode} : ${connection.responseMessage} : $response")
    }
     

Example :

 fun main() {
    val url = URL("http://numbersapi.com/7/math")
    val connection = url.openConnection() as HttpURLConnection
    val response: String = String(connection.inputStream.readBytes())
		if (connection.responseCode != HttpURLConnection.HTTP_OK) {
		    error("${connection.responseCode} : ${connection.responseMessage} : $response")
		}
    println("response = $response")
}
 

We can define a generic function for HTTP GET as :

 fun httpGet(urlString: String): String {
    val url = URL(urlString)
    val connection = url.openConnection() as HttpURLConnection
    val response = String(connection.inputStream.readBytes())
    if (connection.responseCode != HttpURLConnection.HTTP_OK) {
        error("${connection.responseCode} : ${connection.responseMessage} : $response")
    }
    return response
}

// Usage :
fun main() {
    val response = httpGet("http://numbersapi.com/7/math")
    println("response = $response")
}
 

Sending POST request

Steps

Following steps need to be followed to send a HTTP POST request :

  1. Create a URL object for required resource url

     val url = URL(/* url */)
     
  2. Establish a connection using URL#openConnection() function

     val connection = url.openConnection()as HttpURLConnection
     
  3. Create an OutputStream instance for sending payload

     val outputStream = connection.outputStream
     
  4. Send payload as ByteArray using OutputStream#write() function and flush the stream at end

     outputStream.write(/* bytes */)
    outputStream.flush()
     
  5. Create an InputStream instance for reading response

     val inputStream = connection.inputStream
     
  6. Read the response as ByteArray using InputStream#readBytes() function and convert it to a string

     val response = String(inputStream.readBytes())
     
  7. Check the response status

     // If not 'OK', throw error
    if (connection.responseCode != HttpURLConnection.HTTP_OK) {
        error("${connection.responseCode} : ${connection.responseMessage} : $response")
    }
     

Example : PasteBin

PasteBin is a Plain text storage website. We can paste any text that we want to share and get a unique URL against it. PasteBin also allows creating new Paste using their API. Following is an example how to do so :

 fun createNewPaste(
    text: String,
    apiKey: String = "PASTE_YOUR_API_KEY_HERE"
): String {
    
    // Connect
    val url = "https://pastebin.com/api/api_post.php"
    val connection = URL(url).openConnection() as HttpURLConnection

    // Specify POST request
    connection.doOutput = true

    // Send Payload
    connection.setRequestProperty("Content-Type", "application/x-www-form-urlencoded")
    val payload = "api_dev_key=$apiKey&api_paste_code=$text&api_option=paste"
    connection.outputStream.run {
        write(payload.toByteArray())
        flush()
    }

    // Get response
    val inputStream = connection.inputStream
    val response = String(inputStream.readBytes())

    // Check status code
    if (connection.responseCode != HttpURLConnection.HTTP_OK) {
        error("${connection.responseCode} : ${connection.responseMessage} : $response")
    }

    // Return PasteBin URL response
    return response
}

// Usage :
fun main() {
    val pasteUrl = createNewPaste("This is secret code!")
    println("Paste created @ $pasteUrl")
}

/* Output :

Paste created @ https://pastebin.com/YYZbJ1B1
 */
 

Easier way

The above code to send HTTP POST request might seem long. We can simplify and make the code more concise using HTTP Client libraries like OkHttp, Ktor etc. We will learn more about the Ktor library in Coroutines module.