Starting with Flutter: http requests

It is a obligatory passage for all developers, no one can skip it. Getting to know http requests and interfacing with web services is an essential part of many apps. The great thing is that, in Flutter, it’s all very simple to do.

We’ll look at a package in this article called, simply, http, which is published by the official Dart development team. All you need to do some networking is there and it’s really easy to use (as long as you know how to use async functions in Flutter, if not, check out the official dart documentation here).

Preparation

Before starting we’ll need to add http as a dependency, so let’s edit our pubspec.yaml file and add http:

dependencies:
  flutter:
    sdk: flutter
  http: ^0.12.2 //This one

Then we’ll just need to do a good old flutter pub get and import it in our file. I will use as a test case an ideal API Wrapper in order to call a single function to do all the work for us:

import 'package:http/http.dart' as http;

//We'll use an enum to route our static function to a single HTTP method.
enum MyHttpMethod {
  get,
  post,
  delete,
  put,
}

class MyHttpWrapper{

   //This is a singleton class we can use in various places of a Flutter app
   MyHttpWrapper._privateConstructor();
   static final MyHttpWrapper_instance = MyHttpWrapper._privateConstructor();
   static MyHttpWrapperget instance {
      return _instance;
   }
}

We should also need to divide the URL endpoint from the eventual API in order to create the Uri we need to call:

//Our first url is https://dummy.restapiexample.com/api/v1/employees

const String endpoint = "dummy.restapiexample.com";
const String api = "api/v1/employees";

Let’s now start with the basics: GET requests!

GET requests

A GET request is absolutely easy to do, first we need to create the uri which contains the path and query:

var uri = Uri.https(endpoint, api);

then just use the http package to obtain a Future<Response> which represent the result of the operation with data like body and status code:

http.Response response = await http.get(uri);
print(response.statusCode);            //Response status code (200)
print(response.body);                  //Response body ("")

The end. Great, ain’t it??!

POST, DELETE and PUT

Those three methods work similarly to GET but we expect to add some body parameters. Fear not gentle developer! 

With the call we can add a String body with a jsonEncoded Map<String,String> which will be body parameters: then we only need to use http package with postdelete or put method:

http.Response response = await http.post(
            uri,
            body: jsonEncode(<String, String>{
               'param1': param1,
               'param2': param2
            })
);
//or http.delete or http.put

You can also jsonEncode objects as you wish, just remember to add the encoding type.

Map<String, String> parameters = Map<String, String>();
parameters['param1'] = 'param1';
parameters['param2'] = 'param2';
var encodedBody= json.encode(parameters);

http.Response response = await http.post(
            uri,
            body: encodedBody,
            encoding: Encoding.getByName("application/json")
);
//or http.delete or http.put

Now let’s start creating our API wrapper method, complete of switch-case for our enum methods:

Future<Response> callAPI(MyHttpMethod httpMethod, 
String endpoint, String apiName,{ Map<String, String> apiParameters}) async {
    var uri = Uri.https(endpoint, apiName, apiParameters);
    var encodedBody = json.encode(parameters);
    http.Response response;
    switch (httpMethod) {
      case MyHttpMethod.get:{
        response = await http.get(uri);
      }
      break;

      case MyHttpMethod.post:{
        response = await http.post(uri, body: encodedBody, encoding: Encoding.getByName("application/json"));
      }
      break;

      case MyHttpMethod.delete:{
        response = await http.delete(uri, body: encodedBody, encoding: Encoding.getByName("application/json"));
      }
      break;

      case MyHttpMethod.put:{
        response = await http.put(uri, body: encodedBody, encoding: Encoding.getByName("application/json"));
      }
      break;
    }

    return response;
  }

As final touch let’s add the possibility to add custom headers to our API calls.

Add custom headers

Adding custom headers is just another Map to add to http methods:

Map<String, String> myHeaders = Map<String, String>();
myHeaders ['header1'] = 'header1';

http.Response response = await http.post(uri, headers: myHeaders);

Wrapping up

Let’s now complete our API Wrapper adding headers to our callAPI function:

Future<Response> callAPI(MyHttpMethod httpMethod, 
String endpoint, String apiName,{ 
Map<String, String> apiParameters,
Map<String, String> customHeaders}) async {
    var uri = Uri.https(endpoint, apiName);
    var encodedBody = json.encode(parameters);
    http.Response response;
    switch (httpMethod) {
      case MyHttpMethod.get:{
        response = await http.get(uri, headers: customHeaders);
      }
      break;

      case MyHttpMethod.post:{
        response = await http.post(uri, headers: customHeaders, body: encodedBody, encoding: Encoding.getByName("application/json"));
      }
      break;

      case MyHttpMethod.delete:{
        response = await http.delete(uri, headers: customHeaders, body: encodedBody, encoding: Encoding.getByName("application/json"));
      }
      break;

      case MyHttpMethod.put:{
        response = await http.put(uri, headers: customHeaders, body: encodedBody, encoding: Encoding.getByName("application/json"));
      }
      break;
    }

    return response;
  }

Well guys, that was pretty easy, ain’t it? http has many other features like, json body encoding or multi-part request but it is a bit out of scope from this article. Remember that you should not reinvent hot water, Dart team already did.

2 Responses

Add a Comment

Your email address will not be published. Required fields are marked *