Dart Lesson 38 – HTTP Package | Dataplexa

Using the HTTP Package in Dart

In the previous lesson, you learned how to work with APIs in Dart. Now, we will go deeper into the http package and understand how to use headers, query parameters, timeouts, and advanced request handling.

These concepts are critical for building real-world Dart applications such as dashboards, mobile apps, backend services, and CLI tools.


Why the HTTP Package Is Important

The http package allows Dart programs to:

  • Send GET, POST, PUT, DELETE requests
  • Attach headers like authentication tokens
  • Send query parameters
  • Handle API errors and timeouts

Basic HTTP Client

The simplest way to make a request is using http.get(), but for large applications, using http.Client is recommended.

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

void main() async {
  final client = http.Client();

  final response = await client.get(
    Uri.parse('https://jsonplaceholder.typicode.com/posts'),
  );

  print(response.statusCode);
  print(response.body);

  client.close();
}

Adding Headers to Requests

Headers are used for authentication, content type, and custom metadata.

Example: Sending a token with the request.

final response = await http.get(
  Uri.parse('https://jsonplaceholder.typicode.com/posts'),
  headers: {
    'Authorization': 'Bearer my_api_token',
    'Content-Type': 'application/json',
  },
);

Headers are commonly used for:

  • JWT authentication
  • API keys
  • Content negotiation

Using Query Parameters

Query parameters help filter or paginate API responses.

Example: Fetch posts for a specific user.

final uri = Uri.https(
  'jsonplaceholder.typicode.com',
  '/posts',
  {'userId': '1'},
);

final response = await http.get(uri);

print(response.body);

This generates:

https://jsonplaceholder.typicode.com/posts?userId=1


POST Requests with JSON Data

When sending data to APIs, we usually send JSON.

final response = await http.post(
  Uri.parse('https://jsonplaceholder.typicode.com/posts'),
  headers: {
    'Content-Type': 'application/json',
  },
  body: jsonEncode({
    'title': 'New Dart Post',
    'body': 'Learning HTTP in Dart',
    'userId': 10,
  }),
);

print(response.statusCode);
print(response.body);

PUT and DELETE Requests

PUT updates existing resources.

await http.put(
  Uri.parse('https://jsonplaceholder.typicode.com/posts/1'),
  headers: {'Content-Type': 'application/json'},
  body: jsonEncode({
    'title': 'Updated Title',
    'body': 'Updated content',
  }),
);

DELETE removes a resource.

await http.delete(
  Uri.parse('https://jsonplaceholder.typicode.com/posts/1'),
);

Handling Timeouts

Network calls can fail or hang. Timeouts prevent your app from freezing.

try {
  final response = await http
      .get(Uri.parse('https://jsonplaceholder.typicode.com/posts'))
      .timeout(Duration(seconds: 5));

  print(response.body);
} catch (e) {
  print('Request timed out or failed');
}

Handling Status Codes Properly

Always check HTTP status codes.

  • 200–299 → Success
  • 400–499 → Client errors
  • 500+ → Server errors
if (response.statusCode == 200) {
  print('Success');
} else {
  print('Failed: ${response.statusCode}');
}

Reusable API Service Class

Large applications should separate API logic.

class ApiService {
  final String baseUrl =
      'https://jsonplaceholder.typicode.com';

  Future fetchPosts() async {
    final response =
        await http.get(Uri.parse('$baseUrl/posts'));

    if (response.statusCode == 200) {
      return response.body;
    } else {
      throw Exception('API error');
    }
  }
}

Real-World Applications

  • REST API integration
  • Mobile app backends
  • Authentication services
  • Data-driven dashboards

📝 Practice Exercises

Exercise 1

Fetch comments using query parameters.

Exercise 2

Create a POST request with user input.

Exercise 3

Add timeout handling to an API call.


What’s Next?

In the next lesson, you will build command-line tools using Dart that consume APIs and handle user input.