Skip to content

Networking Architecture Documentation

This document explains how the networking layer works in the E2IP Mobile App, specifically focusing on the DioService and the various DataSource classes.

Table of Contents

  1. Overview
  2. DioService
  3. DataSource Classes
  4. Authentication Flow
  5. Error Handling
  6. Usage Examples

Overview

The networking architecture follows a clean architecture pattern with clear separation of concerns:

  • DioService: Core HTTP client wrapper that handles authentication, token refresh, and common HTTP operations
  • DataSource Classes: Domain-specific classes that use DioService to interact with specific API endpoints
  • Secure Storage: Manages token storage and retrieval securely
┌─────────────────┐    ┌─────────────────┐    ┌─────────────────┐
│   Presentation  │───▶│   DataSource    │───▶│   DioService    │
│     Layer       │    │    Classes      │    │                 │
└─────────────────┘    └─────────────────┘    └─────────────────┘
                                                       │
                                               ┌─────────────────┐
                                               │  Secure Storage │
                                               │    Service      │
                                               └─────────────────┘

DioService

Purpose

DioService is a wrapper around the Dio HTTP client that provides: - Automatic authentication token management - Token refresh mechanism - Standardized error handling - Request/response interceptors - DigiKey API token management

Key Features

1. Automatic Authentication

// Automatically adds Bearer token to requests
options.headers['Authorization'] = 'Bearer $token';

2. Token Refresh Mechanism

  • Detects 401 Unauthorized responses
  • Automatically attempts to refresh expired tokens
  • Retries original request with new token
  • Prevents multiple simultaneous refresh attempts

3. DigiKey Token Management

  • Captures DigiKey tokens from response headers
  • Stores them securely for future API calls
  • Handles both access and refresh tokens

4. HTTP Methods

  • get(endpoint, queryParameters) - GET requests with automatic error handling
  • getRaw(endpoint, queryParameters, options) - GET requests returning full Response
  • post(endpoint, data, queryParameters, options) - POST requests with form data support
  • postRaw(endpoint, data, queryParameters, options) - POST requests returning full Response
  • put(endpoint, data) - PUT requests for updates

5. Error Handling

Converts Dio exceptions into meaningful error messages: - Connection timeouts - Server errors with status codes - Network connectivity issues - Certificate problems

Configuration

DioService({
  String? baseUrl,           // API base URL (from .env file)
  Map<String, dynamic>? headers  // Custom headers
})

Default configuration: - Base URL from environment variable BASE_URL - Content-Type: application/json - ngrok-skip-browser-warning: true (for development) - Connect timeout: 35 seconds - Receive timeout: 35 seconds

DataSource Classes

AuthDataSource

Purpose: Handles user authentication and session management

Key Methods: - signIn(usernameOrEmail, password) - User login - logout() - Clear stored tokens and user data - isAuthenticated() - Check authentication status

Token Management: - Stores access_token, refresh_token, user_id, and admin status - Returns tuple with (isAuthenticated, isAdmin, userId)

ComponentDataSource

Purpose: Manages electronic component data and inventory operations

Key Methods: - getComponents() - Fetch all components from local database - searchComponents(keywords) - Search DigiKey API for components - saveComponent(component, quantityLocalStock, minStock) - Add component to local inventory - updateLocalStock(component, localStock, minLocalStock) - Update inventory levels - checkoutComponent(component, quantity) - Remove components from inventory

Special Features: - DigiKey Integration: Handles both access and refresh tokens for DigiKey API - Fallback Token Strategy: Tries access token first, falls back to refresh token - Response Normalization: Handles different API response formats - Data Transformation: Converts between API formats and internal models

UserDataSource

Purpose: Manages user profile and settings

Key Methods: - getUser(userId) - Fetch user profile - updateUserProfile(userId, firstName, lastName, email) - Update profile information - updateUserSettings(userId, notificationsEnabled, lowStockAlerts) - Update user preferences

Authentication Flow

Initial Login

1. User enters credentials
2. AuthDataSource.signIn() called
3. DioService.post() sends credentials to /api/auth/login
4. Server returns access_token, refresh_token, and user info
5. Tokens stored in SecureStorage
6. User roles and ID extracted and stored

Authenticated Requests

1. DataSource method called
2. DioService adds Authorization header automatically
3. Request sent to API
4. If 401 received, token refresh triggered
5. New tokens obtained and stored
6. Original request retried with new token

Token Refresh Process

1. 401 Unauthorized detected
2. Check if not already refreshing (prevent race conditions)
3. Extract refresh_token from SecureStorage
4. Send refresh request to /api/auth/refresh
5. Store new tokens
6. Retry original request
7. If refresh fails, clear all tokens

Error Handling

DioService Error Types

  • Connection Timeout: Network connectivity issues
  • Bad Response: Server errors (4xx, 5xx status codes)
  • Request Cancelled: User cancelled request
  • Bad Certificate: SSL/TLS certificate issues
  • Connection Error: Network infrastructure problems
  • Unknown Error: Unexpected errors including SocketException

DataSource Error Handling

Each DataSource wraps DioService calls in try-catch blocks and provides meaningful error messages:

try {
  final response = await _dioService.get(endpoint);
  return processResponse(response);
} catch (e) {
  throw Exception('Failed to fetch data: $e');
}

Usage Examples

final componentDataSource = ComponentDataSource();
try {
  final components = await componentDataSource.searchComponents('resistor 10k');
  // Process components
} catch (e) {
  // Handle error
  print('Search failed: $e');
}

User Authentication

final authDataSource = AuthDataSource();
final (success, isAdmin, userId) = await authDataSource.signIn('user@example.com', 'password');

if (success) {
  print('Login successful. Admin: $isAdmin, ID: $userId');
} else {
  print('Login failed: $userId'); // userId contains error message on failure
}

Component Inventory Management

final componentDataSource = ComponentDataSource();

// Add component to inventory
await componentDataSource.saveComponent(component, 100, 10);

// Update stock levels
final updatedComponent = await componentDataSource.updateLocalStock(component, 50, 5);

// Checkout components
final afterCheckout = await componentDataSource.checkoutComponent(component, 5);

Security Considerations

  1. Secure Token Storage: All tokens stored using SecureStorageService
  2. Automatic Token Refresh: Prevents manual token handling in UI
  3. Request Validation: Server-side validation of all requests
  4. HTTPS Only: All API communication over secure connections
  5. Token Expiration: Automatic handling of expired tokens

Configuration Requirements

Environment Variables (.env file)

BASE_URL=https://your-api-server.com/api

Dependencies (pubspec.yaml)

dependencies:
  dio: ^5.0.0
  flutter_dotenv: ^5.0.0
  # Add other networking dependencies

Troubleshooting

Common Issues

  1. 401 Unauthorized Errors
  2. Check if tokens are properly stored
  3. Verify token refresh mechanism is working
  4. Ensure API endpoints are correct

  5. Connection Timeouts

  6. Check network connectivity
  7. Verify API server is running
  8. Consider increasing timeout values

  9. DigiKey API Issues

  10. Verify DigiKey tokens are being captured from headers
  11. Check token storage keys match expected format
  12. Ensure fallback refresh token strategy is working

Debug Logging

The DioService includes debug logging for troubleshooting: - Request URLs and methods - Form data contents - Response status codes - Error details and types

Enable debug mode to see detailed networking logs in the console.