Making HTTP Requests
1. Using http Package
| Property | Description | Example |
|---|---|---|
| get() | Method to send GET request | http.get(Uri.parse('https://api.example.com/data')) |
| post() | Method to send POST request | http.post(Uri.parse('https://api.example.com/data'), body: {'key': 'value'}) |
| put() | Method to send PUT request | http.put(Uri.parse('https://api.example.com/data/1'), body: {'key': 'updatedValue'}) |
| delete() | Method to send DELETE request | http.delete(Uri.parse('https://api.example.com/data/1')) |
Example: Making a GET Request
import 'package:http/http.dart' as http;
import 'dart:convert';
Future<void> fetchData() async {
final response = await http.get(
Uri.parse('https://jsonplaceholder.typicode.com/posts/1'),
);
if (response.statusCode == 200) {
final data = json.decode(response.body);
print(data['title']);
} else {
print('Failed to load data');
}
}
Example: Making a POST Request
import 'package:http/http.dart' as http;
import 'dart:convert';
Future<void> postData() async {
final response = await http.post(
Uri.parse('https://jsonplaceholder.typicode.com/posts'),
headers: {'Content-Type': 'application/json'},
body: jsonEncode({
'title': 'My New Post',
'body': 'This is the content of my new post.',
'userId': 1,
}),
);
if (response.statusCode == 201) {
print('Post created successfully');
} else {
print('Failed to create post');
}
}
Note: The
http package requires internet permission in AndroidManifest.xml and Info.plist for iOS.
Warning: Always handle potential network errors and timeouts in production apps.
2. Sending GET Requests
| Property | Description | Example |
|---|---|---|
| http.get() | Method to send a GET request | http.get(Uri.parse('https://api.example.com/data')); |
| HttpClient | Class for making HTTP requests | final client = HttpClient(); |
| HttpClientRequest | Represents an outgoing HTTP request | final request = await client.getUrl(url); |
| HttpClientResponse | Represents an incoming HTTP response | final response = await request.close(); |
Example: Fetching Data with http.get()
import 'dart:convert';
import 'package:http/http.dart' as http;
Future<void> fetchData() async {
final response = await http.get(
Uri.parse('https://jsonplaceholder.typicode.com/posts/1'),
);
if (response.statusCode == 200) {
print(response.body);
} else {
print('Failed to load data');
}
}
Example: Parsing JSON Response
import 'dart:convert';
import 'package:http/http.dart' as http;
Future<Map<String, dynamic>> fetchPost() async {
final response = await http.get(
Uri.parse('https://jsonplaceholder.typicode.com/posts/1'),
);
if (response.statusCode == 200) {
return jsonDecode(response.body);
} else {
throw Exception('Failed to load post');
}
}
Note: The
http package is a popular choice for making HTTP requests in Flutter. It provides a simple API for sending GET, POST, PUT, and DELETE requests.
3. Sending POST Requests
| Property | Description | Example |
|---|---|---|
| url | The endpoint to send the POST request to | https://api.example.com/users |
| headers | Optional headers to include in the request | {'Content-Type': 'application/json', 'Authorization': 'Bearer token'} |
| body | The data payload to send in the request body | {'name': 'John', 'email': 'john@example.com'} |
Example: Sending a POST Request with http Package
import 'package:http/http.dart' as http;
import 'dart:convert';
Future<http.Response> sendPostRequest() async {
final url = 'https://api.example.com/users';
final headers = {'Content-Type': 'application/json'};
final body = jsonEncode({'name': 'John', 'email': 'john@example.com'});
return await http.post(
Uri.parse(url),
headers: headers,
body: body,
);
}
Note: Ensure that the
Content-Type header is set to application/json when sending JSON data.
Warning: Always handle potential errors when making HTTP requests. Use
try-catch blocks to manage exceptions.
4. Sending PUT and DELETE Requests
| Method | Description | Usage |
|---|---|---|
| PUT | Updates a resource or creates it if it doesn't exist. | |
| DELETE | Deletes a resource from the server. | |
Example: PUT Request with Headers
final response = await http.put(
Uri.parse('https://api.example.com/users/123'),
headers: {
'Content-Type': 'application/json',
'Authorization': 'Bearer your_token_here',
},
body: jsonEncode({
'name': 'Updated Name',
'email': 'updated@example.com',
}),
);
Example: DELETE Request with Error Handling
try {
final response = await http.delete(
Uri.parse('https://api.example.com/users/123'),
);
if (response.statusCode == 200) {
print('User deleted successfully');
} else {
print('Failed to delete user: ${response.statusCode}');
}
} catch (e) {
print('Error deleting user: $e');
}
Note: PUT and DELETE requests are typically used in REST APIs to update or remove resources. Ensure proper authentication headers are included when required.
5. Setting Request Headers
| Header | Value Type | Description | Example |
|---|---|---|---|
| Authorization | string |
Used for authentication with the server | Bearer <token> |
| Content-Type | string |
Indicates the media type of the resource | application/json |
| Accept | string |
Specifies the media types that are acceptable for the response | application/json |
| User-Agent | string |
Identifies the client making the request | Flutter App/1.0 |
Example: Setting Custom Headers in a GET Request
import 'package:http/http.dart' as http;
Future<void> fetchWithHeaders() async {
final url = 'https://api.example.com/data';
final headers = {
'Authorization': 'Bearer <token>',
'Content-Type': 'application/json',
};
final response = await http.get(
Uri.parse(url),
headers: headers,
);
print(response.body);
}
Example: Setting Headers in a POST Request
import 'package:http/http.dart' as http;
Future<void> postWithHeaders() async {
final url = 'https://api.example.com/data';
final headers = {
'Authorization': 'Bearer <token>',
'Content-Type': 'application/json',
'Accept': 'application/json',
};
final body = {
'name': 'John Doe',
'email': 'john@example.com',
};
final response = await http.post(
Uri.parse(url),
headers: headers,
body: jsonEncode(body),
);
print(response.body);
}
6. Handling HTTP Responses
| Property | Description | Example |
|---|---|---|
| statusCode | Status code of the HTTP response | 200, 404 |
| headers | Map of response headers | {'content-type': 'application/json'} |
| body | Response body as string or parsed JSON | '{"name": "Flutter"}' |
Example: Parsing JSON Response
final response = await http.get(Uri.parse('https://api.example.com/data'));
if (response.statusCode == 200) {
final data = json.decode(response.body);
print(data['name']);
} else {
print('Failed to load data');
}
Note: Always check
statusCode before parsing the response body to avoid runtime errors.
Response Handling Best Practices
- Always validate
statusCodebefore accessing response data - Use
json.decode()to parse JSON responses - Handle errors gracefully with try-catch blocks
7. Parsing Response Bodies
| Property | Description | Example |
|---|---|---|
| jsonDecode() | Decodes a JSON string into a Dart object | final Map<String, dynamic> data = jsonDecode(response.body); |
| response.body | Raw string content of the response | String body = await response.body; // Raw text |
| response.json() | Directly parses JSON from response (if supported) | final Map<String, dynamic> json = await response.json(); |
Example: Parsing JSON Response
import 'dart:convert';
void parseResponse(String responseBody) {
final Map<String, dynamic> parsed = jsonDecode(responseBody);
print(parsed['name']); // Accessing nested data
}
Note: Always handle potential
FormatException when parsing JSON.
Example: Handling Nested JSON
final Map<String, dynamic> user = {
'id': 1,
'name': 'John Doe',
'address': {
'street': '123 Main St',
'city': 'Anytown'
}
};
final String street = user['address']['street']; // Accessing nested field
8. Implementing Request Timeouts
| Property | Description | Default Value | Notes |
|---|---|---|---|
| timeout | Specifies the maximum time to wait for a response | Duration(seconds: 30) |
Can be adjusted based on network conditions |
Example: Setting a Custom Timeout
import 'dart:io';
import 'package:http/http.dart' as http;
Future<http.Response> fetchWithTimeout() async {
final url = Uri.parse('https://api.example.com/data');
try {
final response = await http.get(url, timeout: Duration(seconds: 10));
return response;
} catch (e) {
if (e is TimeoutException) {
print('Request timed out');
}
rethrow;
}
}
Note: The
timeout parameter in http.get and similar methods controls how long the client waits for a response before throwing a TimeoutException.
Warning: Setting a timeout too low might cause premature failures in slow networks or servers.
9. Using MultipartRequest
The MultipartRequest class in Flutter is used to send HTTP requests with multipart content, typically for file uploads. It allows you to include both form fields and binary data (like images or documents) in a single request.
| Property | Description | Values |
|---|---|---|
| method | The HTTP method to use (e.g., POST) | 'POST' |
| url | The endpoint URL to send the request to | Uri.parse('https://example.com/upload') |
| fields | Map of string key-value pairs to include as form fields | {'name': 'John', 'email': 'john@example.com'} |
| files | List of MultipartFile objects to upload |
[MultipartFile.fromPath('file', 'path/to/file.jpg')] |
Example: Uploading a File with MultipartRequest
import 'dart:io';
import 'package:http/io_client.dart';
final request = MultipartRequest(
'POST',
Uri.parse('https://example.com/upload'),
);
request.fields['name'] = 'John Doe';
request.fields['email'] = 'john@example.com';
final file = await MultipartFile.fromPath(
'file',
'/path/to/image.jpg',
contentType: MediaType('image', 'jpeg'),
);
request.files.add(file);
final response = await request.send();
Note: Ensure that the file path is valid and accessible on the device when using
MultipartFile.fromPath.
Warning: Large file uploads can lead to memory issues or timeouts. Consider using
Stream or chunked uploads for large files.
10. Using Dio Package
| Property | Description | Example |
|---|---|---|
| Base URL | Root URL for all requests | https://api.example.com |
| Headers | HTTP headers to send with each request | {'Authorization': 'Bearer token'} |
| Timeout | Request timeout in milliseconds | 5000 |
Example: Basic GET Request
import 'package:dio/dio.dart';
final dio = Dio();
Response response = await dio.get('https://api.example.com/users');
print(response.data);
Example: POST Request with Data
import 'package:dio/dio.dart';
final dio = Dio();
Map<String, dynamic> data = {
'name': 'John Doe',
'email': 'john@example.com'
};
Response response = await dio.post(
'https://api.example.com/users',
data: data
);
print(response.data);
Example: Handling Errors
import 'package:dio/dio.dart';
final dio = Dio();
try {
Response response = await dio.get('https://api.example.com/users');
print(response.data);
} catch (e) {
if (e is DioException) {
print('Error: ${e.message}');
}
}
Note: Dio provides built-in support for interceptors, which can be used to modify requests or responses before they are handled.