api_hawk 1.0.3 copy "api_hawk: ^1.0.3" to clipboard
api_hawk: ^1.0.3 copied to clipboard

A lightweight HTTP inspector for Flutter. Built-in support for Dio, http, and Chopper. Granular copy options, collapsible JSON viewer, and quick cURL export.

API Hawk #

A lightweight HTTP inspector for Flutter with built-in support for Dio, http, and Chopper.

Capture, search, and inspect network calls with a clean dark UI. Copy exactly what you need — a URL, just the response body, headers, or a ready-to-paste cURL command.

License: MIT

Why? #

Most inspector packages are either unmaintained (flutter_alice), too heavy on dependencies (chucker_flutter), or lock you into a single HTTP client.

API Hawk works with the three most popular Flutter HTTP clients out of the box, stays in memory (no database, no disk writes), and lets you copy individual parts of a request instead of dumping everything at once.

Installation #

dependencies:
  api_hawk:
    git:
      url: https://github.com/awais-jamil/ApiHawk.git

Setup #

Create one instance and share it across your app.

import 'package:api_hawk/api_hawk.dart';

final hawk = HawkInspector();

Dio #

Add the interceptor to your Dio instance. Every request made through that instance gets captured automatically.

import 'package:api_hawk/api_hawk.dart';
import 'package:dio/dio.dart';

final hawk = HawkInspector();
final dio = Dio(BaseOptions(baseUrl: 'https://api.example.com'))
  ..interceptors.add(hawk.dioInterceptor);

Making requests — nothing changes in your existing code:

// GET
final users = await dio.get('/users');

// GET with query parameters
final filtered = await dio.get('/users', queryParameters: {'role': 'admin', 'page': '1'});

// POST with JSON body
final created = await dio.post('/users', data: {
  'name': 'John Doe',
  'email': 'john@example.com',
});

// PUT
await dio.put('/users/42', data: {'name': 'Jane Doe'});

// DELETE
await dio.delete('/users/42');

// Multipart upload
final formData = FormData.fromMap({
  'avatar': await MultipartFile.fromFile('/path/to/image.jpg'),
  'name': 'profile_pic',
});
await dio.post('/upload', data: formData);

Errors are captured too — if a request returns 4xx/5xx or the connection fails, it shows up in the inspector with the error details and stack trace.


http package #

Wrap your http.Client with hawk.httpClient(). The returned client has the exact same API — just swap it in.

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

final hawk = HawkInspector();
final client = hawk.httpClient(http.Client());

Use it like you normally would:

// GET
final response = await client.get(
  Uri.parse('https://api.example.com/users'),
  headers: {'Authorization': 'Bearer $token'},
);

// POST with JSON
final created = await client.post(
  Uri.parse('https://api.example.com/users'),
  headers: {'Content-Type': 'application/json'},
  body: jsonEncode({'name': 'John', 'email': 'john@example.com'}),
);

// Multipart
final request = http.MultipartRequest('POST', Uri.parse('https://api.example.com/upload'));
request.files.add(await http.MultipartFile.fromPath('file', '/path/to/image.jpg'));
request.fields['description'] = 'Profile photo';
final streamedResponse = await client.send(request);

The response body is automatically parsed as JSON when possible, so it shows up in the tree viewer.


Chopper #

Pass the interceptor to your ChopperClient. Works with Chopper 8.x and the modern Interceptor interface.

import 'package:api_hawk/api_hawk.dart';
import 'package:chopper/chopper.dart';

final hawk = HawkInspector();

final chopperClient = ChopperClient(
  baseUrl: Uri.parse('https://api.example.com'),
  services: [
    UserService.create(),
    PostService.create(),
  ],
  interceptors: [
    hawk.chopperInterceptor,
    // your other interceptors still work
    HttpLoggingInterceptor(),
  ],
  converter: JsonConverter(),
);

All requests made through any Chopper service attached to this client will be captured.

final userService = chopperClient.getService<UserService>();
final response = await userService.getUser(id: 42);
final allUsers = await userService.getUsers(page: 1);

Retrofit #

Retrofit generates code on top of Dio, so the Dio interceptor covers it. No extra setup needed.

import 'package:api_hawk/api_hawk.dart';
import 'package:dio/dio.dart';

final hawk = HawkInspector();
final dio = Dio(BaseOptions(baseUrl: 'https://api.example.com'))
  ..interceptors.add(hawk.dioInterceptor);

final apiClient = RestClient(dio);

// these are all captured
final user = await apiClient.getUser(42);
final posts = await apiClient.getPosts(page: 1, limit: 20);
await apiClient.createPost(title: 'Hello', body: 'World');

Other HTTP Clients #

For clients that don't have a built-in interceptor, use the generic logging API. You get a call ID when you log the request, then pass it back when the response (or error) arrives.

import 'package:api_hawk/api_hawk.dart';

final hawk = HawkInspector();

Future<MyResponse> fetchData() async {
  final callId = hawk.logRequest(
    method: 'GET',
    url: 'https://api.example.com/data',
    headers: {
      'Authorization': 'Bearer $token',
      'Accept': 'application/json',
    },
    queryParameters: {'page': '1', 'limit': '20'},
  );

  try {
    // make the request with whatever client you're using
    final response = await myCustomClient.get('/data');

    hawk.logResponse(
      callId: callId,
      statusCode: response.statusCode,
      headers: response.headers,
      body: response.parsedBody,
    );

    return response;
  } catch (e, stack) {
    hawk.logError(
      callId: callId,
      error: e,
      stackTrace: stack,
      statusCode: e is HttpException ? e.statusCode : null,
      responseBody: e is HttpException ? e.body : null,
    );
    rethrow;
  }
}

This works with GraphQL clients, gRPC, WebSocket wrappers, or anything that makes HTTP calls.


Opening the Inspector #

// push as a full-screen route
hawk.show(context);

// or get a Route for your own navigation setup
Navigator.of(context).push(hawk.route());

The inspector screen shows all captured calls in reverse chronological order. You can search by URL and filter by HTTP method using the chips at the top.

Tap any call to see the detail screen with four tabs: Overview, Request, Response, and Error.


Copying #

This is the main reason this package exists. Tap the menu button on any call detail screen and pick exactly what you want:

  • Copy URL — just the URL
  • Copy Request Headers — request headers as text
  • Copy Request Body — formatted JSON
  • Copy Response Headers — response headers as text
  • Copy Response Body — formatted JSON
  • Copy as cURL — a full cURL command you can paste into a terminal
  • Copy Full Call Log — everything in one block

You can also long-press any header row or any value in the JSON tree to copy just that piece.

There's a dedicated cURL button in the app bar for quick access — no need to open the menu for the most common action.


JSON Viewer #

Response and request bodies are displayed as a collapsible tree with syntax highlighting. Keys, strings, numbers, booleans, and nulls each have their own color. You can switch between tree view and raw JSON with a toggle.

Nodes deeper than level 2 are collapsed by default to keep things readable. Tap any node to expand or collapse it.


Configuration #

// keep more calls in memory (default is 200)
final hawk = HawkInspector(maxCalls: 1000);

// clear all captured calls
hawk.clear();

// listen to the call stream for custom logging or UI
hawk.store.callsStream.listen((calls) {
  debugPrint('${calls.length} calls captured');
});

// clean up when you're done
hawk.dispose();

Supported Clients #

Client Integration
Dio 5.x hawk.dioInterceptor
http 1.x hawk.httpClient(inner)
Chopper 8.x hawk.chopperInterceptor
Retrofit via Dio interceptor
GraphQL (dio-based) via Dio interceptor
Anything else logRequest / logResponse / logError

Contributing #

Pull requests are welcome. If you find a bug or want to add support for another HTTP client, feel free to open an issue or submit a PR.

  1. Fork the repository
  2. Create your branch (git checkout -b feature/my-feature)
  3. Commit your changes (git commit -m 'Add my feature')
  4. Push (git push origin feature/my-feature)
  5. Open a Pull Request

License #

MIT — see LICENSE for details.

2
likes
130
points
170
downloads

Documentation

API reference

Publisher

unverified uploader

Weekly Downloads

A lightweight HTTP inspector for Flutter. Built-in support for Dio, http, and Chopper. Granular copy options, collapsible JSON viewer, and quick cURL export.

Repository (GitHub)
View/report issues

Topics

#http #inspector #dio #networking #debugging

License

MIT (license)

Dependencies

chopper, dio, flutter, http

More

Packages that depend on api_hawk