HTTP Network Request Logging with HTTP Library in Flutter

HTTP Network Request Logging with HTTP Library in Flutter

Logging Network Request and Response made easier.

Table of contents

No heading

No headings in the article.

While working with APIS, on any app, it is important to log network calls, both incoming and outgoing. In dart and Flutter, there are 2 libraries most commonly used to perform network requests. They are HTTP and DIO. If you are using dio package, then there is a cool library called dio_pretty_logger and it makes it extremely easy to log the request and response to the flutter console. You can check the library docs by clicking the above link. But if you have ever used the package HTTP package, then you know how difficult it becomes to log network requests. And that’s what we are trying to solve today.

Sample App. Let’s create a sample flutter project to demonstrate the hardship we have to go through to log network requests and responses in the flutter app. I assume you have some experience with Flutter. Now, for this demo, let’s erase all the pre-generated code and replace it with the following. But before that, let’s add HTTP to our pubspec.yaml like this:

http: ^0.13.4

Now let's erase everything from the main.dart and replace it with the following.

import 'package:flutter/material.dart';
import 'api.dart';

void main() {
  runApp(MyApp());
}

class MyApp extends StatefulWidget {
  @override
  _MyAppState createState() => _MyAppState();
}

class _MyAppState extends State<MyApp> {
  final api = Api();
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      theme: ThemeData(primarySwatch: Colors.blue),
      home: Scaffold(
        appBar: AppBar(
          title: Text('Flutter Http Logger Demo'),
        ),
        body: Center(
          child: Column(
            mainAxisAlignment: MainAxisAlignment.center,
            children: <Widget>[
              Container(
                margin: EdgeInsets.all(16),
                width: double.infinity,
                child: ElevatedButton(
                  onPressed: api.mockGet,
                  child: Text('GET'),
                  style: ElevatedButton.styleFrom(
                    primary: Theme.of(context).primaryColor,
                    padding: EdgeInsets.all(16),
                  ),
                ),
              ),
              Container(
                margin: EdgeInsets.all(16),
                width: double.infinity,
                child: ElevatedButton(
                  onPressed: api.mockPost,
                  child: Text('POST'),
                  style: ElevatedButton.styleFrom(
                    primary: Theme.of(context).errorColor,
                    padding: EdgeInsets.all(16),
                  ),
                ),
              ),
            ],
          ),
        ),
      ),
    );
  }
}

Here we have two buttons, laid vertically. One button references a method defined in api.dart. Let’s create a new file api.dart in the same lib directory and paste the following code.

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

class Api {
  final _client = Client();

  Future<void> mockGet() async {
    final url = Uri.parse("https://jsonplaceholder.typicode.com/posts/1");
    try {
      final response = await _client.get(url);
      final body = jsonDecode(response.body);
      print("Request url: ${response.request?.url}");
      print("Request headers: ${response.request?.headers}");
      print("Response header: ${response.headers}");
      print("Response body: ${response.body}");
      return body;
    } catch (e) {
      print("Response exception: $e");
      throw Exception("$e".replaceAll("Exception:", ""));
    }
  }

  Future<void> mockPost() async {
    final url = Uri.parse("https://jsonplaceholder.typicode.com/posts/");
    try {
      final response =
          await _client.post(url, body: jsonEncode({"username": "123"}));
      final body = jsonDecode(response.body);
      print("Request url: ${response.request?.url}");
      print("Request headers: ${response.request?.headers}");
      print("Response header: ${response.headers}");
      print("Response body: ${response.body}");
      return body;
    } catch (e) {
      print("Response exception: $e");
      throw Exception("$e".replaceAll("Exception:", ""));
    }
  }
}]

In api.dart we are making two network requests, one get request and one post request. As you see in the code, this is probably most developers would log out the request and the response to the console. It is painful, time-consuming, and repetitive. As we would have to repeat those print statements in every method we write that performs network requests. This is what it would look like in the console. Sometimes when the network response is big, flutter would clip out some part of the response. It makes logging extremely difficult.

1__S78cukgE5qreAw7P98YLg.png

Logging network requests in the flutter app. Inspired by pretty_dio_logger I created a similar package for HTTP. I could not find any other package that would do the same thing pretty_dio_logger does. Therefore I took two whole projects: http_logger and http_middleware and fused them into this one library — pretty_http_logger.

Using this library is extremely easy. Just add this to your pubspec.yaml after HTTP like this:

pretty_http_logger: ^0.2.1

And in api.dart let’s replace our client with a class provided by pretty_http_logger like this:


HttpClientWithMiddleware _client = HttpClientWithMiddleware.build(middlewares: [
  HttpLogger(logLevel: LogLevel.BODY),
]);

Don’t forget to import the package:

importpackage:pretty_http_logger/pretty_http_logger.dart’;

Now we are all set to go. We can use the _client as we would normally do. The package will console out the request headers, request body if any, response headers, and response body and if any exception occurs, it will console out that too. Now our console will look like this.

second.png

The text looks very small on the image. You can try zooming into it. Basically, it separately consoles out URLs, headed, and body of request and response.

You can pass timeout, and log level to determine what to console out to them HttpClientWithMiddleware as well. You can read more about it on the package home page http_pretty_logger. I hope you find this useful.

> I am Mithun Adhikari, I am a software engineer, Flutter enthusiast, instructor, and entrepreneur. You can write me back in case of any queries. I will try to communicate back as soon as I can. You can find my contact details and more about me on my portfolio here. If you have any suggestions or anything feel free to write to me. Happy Coding.