Skip to content

Latest commit

Β 

History

History
434 lines (340 loc) Β· 9.82 KB

File metadata and controls

434 lines (340 loc) Β· 9.82 KB

πŸ”§ Flutter API Debugging Guide

Issues Fixed βœ…

1. Authorization Policy Fixed

Problem: ConversationPolicy was blocking all API requests (returned false for everything)

Solution: Updated app/Policies/ConversationPolicy.php to:

  • Allow users to view conversations they're part of
  • Allow users to create conversations
  • Check participant membership before allowing actions

2. User Avatar URL Added

Problem: Avatar URLs weren't included in API responses

Solution: Added $appends = ['avatar_url'] to User model so it's automatically included in JSON

3. Added Logging

Problem: No visibility into API failures

Solution: Added logging to:

  • Contact search
  • Message fetching
  • Message sending

Testing Steps

Step 1: Clear Cache

cd D:\project\chat-app
php artisan config:clear
php artisan cache:clear
php artisan route:cache

Step 2: Test Contact Search

Via Browser/Postman:

GET http://localhost:8000/api/contacts/search?q=admin
Headers:
  Authorization: Bearer YOUR_TOKEN
  Accept: application/json

Expected Response:

[
  {
    "id": 1,
    "name": "Admin User",
    "email": "admin@example.com",
    "avatar_path": null,
    "created_at": "2024-01-01T00:00:00.000000Z",
    "avatar_url": "https://www.gravatar.com/avatar/..."
  }
]

Step 3: Test Get Conversations

Request:

GET http://localhost:8000/api/conversations
Headers:
  Authorization: Bearer YOUR_TOKEN
  Accept: application/json

Expected Response:

[
  {
    "id": 1,
    "name": null,
    "is_group": false,
    "created_by": 1,
    "created_at": "...",
    "participants": [
      {
        "id": 1,
        "name": "User 1",
        "avatar_url": "..."
      },
      {
        "id": 2,
        "name": "User 2",
        "avatar_url": "..."
      }
    ],
    "latest_message": {...}
  }
]

Step 4: Test Get Messages

Request:

GET http://localhost:8000/api/conversations/1/messages?page=1
Headers:
  Authorization: Bearer YOUR_TOKEN
  Accept: application/json

Expected Response:

{
  "current_page": 1,
  "data": [
    {
      "id": 1,
      "conversation_id": 1,
      "user_id": 1,
      "body": "Hello!",
      "type": "text",
      "created_at": "...",
      "sender": {
        "id": 1,
        "name": "User 1",
        "avatar_url": "..."
      },
      "media": []
    }
  ],
  "total": 10,
  "per_page": 50
}

Step 5: Test Send Message

Text Message:

POST http://localhost:8000/api/conversations/1/messages
Headers:
  Authorization: Bearer YOUR_TOKEN
  Content-Type: application/json
  Accept: application/json
Body:
{
  "type": "text",
  "body": "Test message from API"
}

Image Message (multipart/form-data):

POST http://localhost:8000/api/conversations/1/messages
Headers:
  Authorization: Bearer YOUR_TOKEN
  Accept: application/json
Form Data:
  type: image
  body: Optional caption
  image: [image file]

Flutter App Debug Steps

1. Check API Connection

Update lib/config/app_config.dart:

class AppConfig {
  // For Android Emulator (10.0.2.2 = host machine)
  static const String baseUrl = 'http://10.0.2.2:8000';
  
  // For iOS Simulator
  // static const String baseUrl = 'http://localhost:8000';
  
  // For Physical Device (use your computer's IP)
  // static const String baseUrl = 'http://192.168.1.XXX:8000';
  
  static const String apiUrl = '$baseUrl/api';
  static const String storageUrl = '$baseUrl/storage';
  
  // WebSocket Configuration
  static const String pusherAppKey = 'dzipltzgyda8iewsqt4o';
  static const String pusherHost = '10.0.2.2'; // Match baseUrl host
  static const int pusherPort = 8080;
  static const String pusherScheme = 'http';
  static const String pusherCluster = 'mt1';
  
  static const bool enableLogging = true;
}

2. Test API from Flutter

Add this test function to your app (temporarily):

Future<void> testAPI() async {
  final api = ApiService();
  
  print('πŸ§ͺ Testing API...');
  
  // Test 1: Get User
  try {
    final response = await api.get('/user');
    print('βœ… Get User: ${response.statusCode}');
    print('   Response: ${response.body}');
  } catch (e) {
    print('❌ Get User failed: $e');
  }
  
  // Test 2: Search Contacts
  try {
    final response = await api.get('/contacts/search?q=test');
    print('βœ… Search Contacts: ${response.statusCode}');
    print('   Response: ${response.body}');
  } catch (e) {
    print('❌ Search failed: $e');
  }
  
  // Test 3: Get Conversations
  try {
    final response = await api.get('/conversations');
    print('βœ… Get Conversations: ${response.statusCode}');
    print('   Response: ${response.body}');
  } catch (e) {
    print('❌ Get Conversations failed: $e');
  }
}

Call this from your conversations screen's initState() temporarily.

3. Check Laravel Logs

Monitor in real-time:

# Windows PowerShell
Get-Content "D:\project\chat-app\storage\logs\laravel.log" -Wait -Tail 50

Look for:

[2024-01-01 12:00:00] local.INFO: Contact search request {"query":"test","user_id":1}
[2024-01-01 12:00:00] local.INFO: Contact search results {"count":2}
[2024-01-01 12:00:00] local.INFO: Fetching messages {"conversation_id":1,"user_id":1,"page":1}
[2024-01-01 12:00:00] local.INFO: Messages fetched {"count":5}

Common Errors & Solutions

Error: "Unauthenticated" (401)

Cause: Token not sent or expired

Solution:

  1. Check token is stored: await StorageService().getToken()
  2. Re-login to get fresh token
  3. Verify Authorization header is sent

Flutter Debug:

final token = await StorageService().getToken();
print('Token: $token');
if (token == null) {
  print('❌ No token found - need to login');
}

Error: "Forbidden" (403)

Cause: User not authorized (ConversationPolicy blocked)

Solution:

  1. Verify you're a participant in the conversation
  2. Check policy was updated correctly
  3. Clear Laravel cache

Error: "Connection refused" / "Connection timeout"

Cause: Can't reach Laravel server

Solution:

  1. Verify Laravel is running: http://localhost:8000 in browser
  2. Check IP address:
    • Android Emulator: Use 10.0.2.2 (not localhost)
    • iOS Simulator: Use localhost
    • Physical Device: Use your computer's IP
  3. Laravel must serve on all interfaces:
    php artisan serve --host=0.0.0.0
  4. Check firewall: Temporarily disable to test

Error: "The given data was invalid"

Cause: Validation failed

Solution:

  1. Check request body format
  2. View Laravel logs for validation errors
  3. Ensure Content-Type header is correct

Error: Messages list shows empty but conversations exist

Cause: Messages API failing silently

Solution:

  1. Check Laravel logs for errors
  2. Test API endpoint directly with Postman
  3. Verify conversation ID is correct
  4. Check user is participant

Verification Checklist

After fixes, verify:

  • Can login via Flutter app
  • Conversations list loads
  • Search for contacts works (shows results)
  • Can create new conversation
  • Messages load in chat screen
  • Can send text message
  • Can send image message
  • Messages appear in real-time (WebSocket)
  • Images display correctly

Quick Test Script

Save as test_api.sh (Mac/Linux) or test_api.ps1 (Windows):

Windows PowerShell:

$token = "YOUR_TOKEN_HERE"
$base = "http://localhost:8000/api"

Write-Host "Testing API..." -ForegroundColor Green

# Test User
Write-Host "`n1. Testing GET /user" -ForegroundColor Yellow
$response = Invoke-WebRequest -Uri "$base/user" -Headers @{"Authorization"="Bearer $token"; "Accept"="application/json"}
Write-Host "Status: $($response.StatusCode)" -ForegroundColor Cyan

# Test Search
Write-Host "`n2. Testing GET /contacts/search?q=admin" -ForegroundColor Yellow
$response = Invoke-WebRequest -Uri "$base/contacts/search?q=admin" -Headers @{"Authorization"="Bearer $token"; "Accept"="application/json"}
Write-Host "Status: $($response.StatusCode)" -ForegroundColor Cyan
Write-Host $response.Content

# Test Conversations
Write-Host "`n3. Testing GET /conversations" -ForegroundColor Yellow
$response = Invoke-WebRequest -Uri "$base/conversations" -Headers @{"Authorization"="Bearer $token"; "Accept"="application/json"}
Write-Host "Status: $($response.StatusCode)" -ForegroundColor Cyan

Write-Host "`nAll tests passed! βœ…" -ForegroundColor Green

Still Not Working?

1. Get Your Token

Login via Flutter, then add this debug code:

// After successful login in auth_provider.dart
final token = await _storage.getToken();
print('πŸ”‘ AUTH TOKEN: $token');
print('Copy this token for testing');

2. Test with Postman/Browser

Use the token to test each endpoint manually

3. Compare Logs

Laravel Log:

tail -f storage/logs/laravel.log

Flutter Console: Look for API request logs from ApiService

4. Check Database

-- Verify user has conversations
SELECT * FROM conversation_participants WHERE user_id = YOUR_USER_ID;

-- Verify messages exist
SELECT * FROM messages WHERE conversation_id = YOUR_CONVERSATION_ID;

-- Check if user is authenticated
SELECT * FROM personal_access_tokens WHERE tokenable_id = YOUR_USER_ID;

Success! πŸŽ‰

When everything works you should see:

Flutter Console:

GET: http://10.0.2.2:8000/api/conversations
Response: 200 - [{"id":1,"name":null,...}]
βœ… Subscribed to conversation.1
πŸ“¨ Message received on conversation 1

Laravel Log:

[INFO] Fetching messages {"conversation_id":1,"user_id":1}
[INFO] Messages fetched {"count":5}
[INFO] Storing message {"conversation_id":1,"type":"text"}
[INFO] Message stored and broadcast {"message_id":15}

App Behavior:

  • Conversations load instantly
  • Messages display properly
  • Search returns users
  • Messages send successfully
  • Real-time updates work