unified_http_client 0.0.7
unified_http_client: ^0.0.7 copied to clipboard
A Flutter Package to provide smooth Api call with All Error and Exception handeled.
unified_http_client #
unified_http_client is a Flutter/Dart package that gives you a single, simple API surface for making REST calls using either http or dio under the hood.
- Unified API: call
UnifiedHttpClient.get/post/delete/multipartand switch betweenhttpanddiowith a single flag. - Centralized headers: configure common headers once in
init(); they are automatically applied to all requests for bothhttpanddio, with per-call overrides still possible. - Unified error model: instead of throwing, requests return a
Result<Success, Failure>with a richUnifiedHttpClientEnumerror type and messages. - Network checking & snackbar: optional internet availability check with a built-in "no internet" snackbar helper.
- Interceptors: plug in
UnifiedInterceptors once and have them applied consistently for bothhttpanddio.
Installation #
Add this to your pubspec.yaml:
dependencies:
unified_http_client: ^latest
Then run:
flutter pub get
Android configuration #
On Android, for correct working in release mode, you must add INTERNET and ACCESS_NETWORK_STATE permissions to AndroidManifest.xml:
<manifest xmlns:android="http://schemas.android.com/apk/res/android">
<!-- Permissions for internet_connection_checker -->
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<application
android:name="..."
... >
</application>
</manifest>
You can use the built-in internet checker and snackbar like this:
if (!await InternetConnectionChecker().hasConnection) {
CustomSnackbar().showNoInternetSnackbar();
}
Initialize the snackbar after MaterialApp is built:
@override
Widget build(BuildContext context) {
// Needed to show the "no internet" snackbar.
CustomSnackbar().init(context);
return MaterialApp(
home: Scaffold(
appBar: AppBar(title: const Text('Unified HTTP Client')),
body: const MyHomePage(),
),
);
}
Initialization (headers + client selection) #
Call UnifiedHttpClient().init() once, early in your app (e.g. in main()), to configure:
- whether to use
httpordio - base URL and timeouts (for
dio) - global headers (used by both
httpanddio) - interceptors and logging
void main() async {
WidgetsFlutterBinding.ensureInitialized();
UnifiedHttpClient().init(
usehttp: false, // false => use dio, true => use http (default is true)
baseUrl: 'https://66c45adfb026f3cc6ceefd10.mockapi.io',
showLogs: true,
// headers configured here are applied to ALL requests by default
headers: {
'Authorization': 'Bearer <token>',
'X-App-Version': '1.0.0',
},
interceptors: [
ApiInterceptor(
// Example: override headers or log extra info
onRequestOverride: (req) {
req.headers['X-Demo-Header'] = 'demo';
return req;
},
),
],
);
runApp(const MyApp());
}
Note: You no longer need to call
PackageDio.setBaseOptions/setUpDio()orPackageHttp.setup()directly in your app. Theinit()method wires everything up for you.
Making API calls #
Use the static helpers from UnifiedHttpClient anywhere in your code.
All methods return a Result<String> which will be either Success or Failure.
GET #
final result = await UnifiedHttpClient.get(
'/data/postdata',
// optional per-call headers (merged with init headers, override by key)
headers: {
'X-Request-Id': '123',
},
queryPara: {
'page': 1,
},
);
result.fold(
(failure) {
debugPrint('GET failed: ${failure.unifiedHttpClientEnum} - ${failure.message}');
},
(body) {
debugPrint('GET body: $body');
},
);
POST #
final result = await UnifiedHttpClient.post(
'/data/postdata',
body: {
'name': 'John',
'age': 30,
},
headers: {
// overrides/extends init headers for this call only
'X-Request-Id': '456',
},
);
result.fold(
(failure) {
// handle error
},
(body) {
// handle success
},
);
DELETE #
final result = await UnifiedHttpClient.delete(
'/data/postdata/1',
);
Multipart (file upload) #
final result = await UnifiedHttpClient.multipart(
'/upload',
files: {
'image': {
'path': '/path/to/image.jpg',
'filename': 'image.jpg',
},
},
fields: {
'title': 'My Image',
'description': 'Image description',
},
);
Header behavior (important) #
-
Init-level headers (
init(headers: ...)):- Stored once and automatically applied to every request (for both
httpanddio). - Example: global
Authorizationtoken,Accept-Language, app version, etc.
- Stored once and automatically applied to every request (for both
-
Per-call headers (e.g.
get(..., headers: {...})):- Optional and still supported.
- These are merged with init headers; when a key exists in both, the per-call value wins.
- This works consistently for
get,post,delete, andmultipart.
This lets you configure your main headers once, while still having the flexibility to tweak/override them for individual calls.
You can also update global headers later at runtime from anywhere in your app:
// e.g. after a successful login
final loginResult = await UnifiedHttpClient.post('/auth/login', body: {...});
loginResult.fold(
(failure) {
// handle login error
},
(body) {
final token = extractTokenFrom(body);
UnifiedHttpClient.setDefaultHeader('Authorization', 'Bearer $token');
},
);
// or replace/merge multiple defaults at once
UnifiedHttpClient.setDefaultHeaders({
'Authorization': 'Bearer $token',
'X-Session-Id': sessionId,
});
You can also update global headers later at runtime from anywhere in your app:
// e.g. after a successful login
result.fold(
(failure) {
// handle login error
},
(body) {
final token = extractTokenFrom(body);
UnifiedHttpClient.setDefaultHeader('Authorization', 'Bearer $token');
},
);
// or replace/merge multiple defaults at once
UnifiedHttpClient.setDefaultHeaders({
'Authorization': 'Bearer $token',
'X-Session-Id': sessionId,
});
Error handling #
All helpers (get/post/delete/multipart) return a Result<String>:
- Success: wraps the response body as a
String. - Failure: wraps:
- a
UnifiedHttpClientEnumdescribing the error category (e.g.badRequestError,internalServerError,noInternetError, etc.), - a default message,
- and (where applicable) the raw response body from the server.
- a
You can pattern-match on the enum to customize your UI and flows:
result.fold(
(failure) {
switch (failure.unifiedHttpClientEnum) {
case UnifiedHttpClientEnum.badRequestError:
// 400
break;
case UnifiedHttpClientEnum.notFoundError:
// 404
break;
default:
// generic handling
}
},
(body) {
// handle success
},
);
Network log viewer screen #
This package also includes a ready‑made network inspector screen, powered by a unified interceptor that records all http and dio traffic.
- Logs are stored in-memory inside the package (via
NetworkLogStorage). - The widget is exposed as
NetworkLogScreenand can be used in any Flutter app.
Usage in your Flutter project #
- Import the package (and screen)
import 'package:flutter/material.dart';
import 'package:unified_http_client/unified_http_client.dart'; // exports NetworkLogScreen
- Navigate to the screen from anywhere
IconButton(
icon: const Icon(Icons.network_check),
onPressed: () {
Navigator.of(context).push(
MaterialPageRoute(
builder: (_) => const NetworkLogScreen(),
),
);
},
);
- Or use it as a standalone page
class DebugNetworkPage extends StatelessWidget {
const DebugNetworkPage({super.key});
@override
Widget build(BuildContext context) {
return const NetworkLogScreen();
}
}
As long as your app is using UnifiedHttpClient (and calling UnifiedHttpClient().init(...)), all requests made through the package (both http and dio) will be recorded and displayed in this screen—no extra setup or external state management required.
Example app #
See the example folder (and its README.md) for a minimal working Flutter app that demonstrates:
- initializing the client once in
main.dart - switching between
httpanddio - configuring headers globally and per-call
- using interceptors and logging
- handling
Success/Failureresults in the UI