Flutter App on LAN Cannot Receive Response from Node.js API on WiFi (Ping Reaches API, No Response Back)

Problem: I have a Flutter app running on a device connected to a LAN network, and a Node.js API running on a server connected to the same router via WiFi. There is no firewall enabled, and both devices can ping each other bi-directionally with no latency.

However, when trying to make a ping request from my Flutter app to the Node.js API, the ping request reaches the API, but the response does not come back to the Flutter app.

Network Setup:

  • Flutter Device: Connected to LAN.
  • Server (Node.js API): Connected to WiFi.
  • Both devices are on the same router and can communicate with each other.
  • No firewall is enabled on either device.
  • Ping works both ways with no latency.

Steps to Reproduce:

In Postman (from Flutter device): The ping request reaches the Node.js API successfully. The response is not received back from the API.

In Flutter App: I am using Dio to send a GET request to the /ping endpoint of the API.


Flutter code

Future<bool> testConnectivity() async {
  Logger.log('DIO TEST CONNECTION.', level: LogLevel.debug);
  try {
    final response = await _dio.get('/ping');
    if (response.statusCode == 200) {
      Logger.log('DIO TEST SUCCESSFUL.', level: LogLevel.debug);
      return true;
    }
    Logger.log('DIO TEST FAILURE WITH STATUS CODE ${response.statusCode}.',
        level: LogLevel.error);
    return false;
  } catch (e) {
    Logger.log('GENERAL EXCEPTION: ${e.toString().toUpperCase()}.',
        level: LogLevel.error);
    return false;
  }
}

Node JS Code

router.get("/ping", (req, res) => {
    console.log(`Ping endpoint hit at ${new Date().toISOString()}`);
    res.status(200).json({ status: "success", message: "pong" });
});

Dio Logs

DIO TEST CONNECTION.
Dio Log: *** Request ***
Dio Log: uri: http://192.168.10.15:3000/ping
Dio Log: method: GET
Dio Log: responseType: ResponseType.json
Dio Log: connectTimeout: 0:00:15.000000
Dio Log: sendTimeout: 0:00:15.000000
Dio Log: receiveTimeout: 0:00:30.000000
Dio Log: data: null
Dio Log: *** DioException ***
Dio Log: uri: http://192.168.10.15:3000/ping
Dio Log: DioException [connection timeout]: The request connection took longer than 0:00:15.000000 and it was aborted. 



Ping endpoint hit at 2024-11-22T04:47:06.179Z
Response sent at 2024-11-22T04:47:06.190Z
CLIENT CONNECTED: IP ADDRESS: 192.168.10.24 | HOSTNAME: 192.168.10.24

The issue you’re experiencing seems related to a timeout happening when the Flutter app tries to reach the Node.js API, even though the ping works and the request reaches the server. Based on the provided logs, here’s a structured way to diagnose and solve the issue:

1. Understanding the Symptoms

  • Ping from the Flutter device: You mentioned that the ping reaches the server (Node.js API) and is successfully responded to.
  • Request from Flutter app: The request from the Flutter app to http://192.168.10.15:3000/ping reaches the API, but the Flutter app doesn’t receive the response. The Dio log shows a DioException [connection timeout], indicating the request times out before the response is received.

The fact that the request gets to the Node.js server but the response isn’t coming back could be due to several factors. Let’s investigate each possible cause:

2. Possible Causes

a. Dio Timeout Settings

Your Dio client has a receiveTimeout of 30 seconds (receiveTimeout: 0:00:30.000000), which seems reasonable. However, the error log suggests the request times out after 15 seconds (connectTimeout: 0:00:15.000000). If the Node.js server is taking longer to respond than this timeout period allows, the request will be aborted.

Solution:

Increase the connectTimeout to give the connection more time to establish:

final dio = Dio(BaseOptions(
  connectTimeout: 30000,  // 30 seconds
  receiveTimeout: 30000,  // 30 seconds
));

Also, ensure that the receiveTimeout is high enough to accommodate the network conditions.

b. Server Response Time

While the request reaches the server (Ping endpoint hit), it’s possible the server’s response is delayed or there are network-related issues when sending the response back. It may also be a case where the server responds but the response is not being sent properly.

Solution:
  • Check Server Logs: Ensure the server is not encountering any issues when sending the response back. Check the server logs for any errors or delays after the request is received.

c. Cross-Network Communication (LAN/WiFi)

Since the Flutter device is connected to the LAN and the server is on WiFi, there may be some routing or networking issues even though both devices are on the same router.

Solution:
  • Check Network Routes: Ensure that the router is properly routing traffic between the LAN and WiFi subnets. Some routers may have separate IP subnets for LAN and WiFi, which could cause issues with returning responses.
  • Test with Direct IP: Try connecting directly to the local IP address instead of the local network address (http://192.168.10.15:3000/ping), and check if there are any issues with DNS resolution or routing.

d. CORS Issue (Client-Side)

If your Node.js API is set up to serve data over HTTP, make sure there are no CORS (Cross-Origin Resource Sharing) restrictions on the server. Sometimes, if the server expects the request to be from a specific origin (e.g., a web app), it might block the response.

Solution:

Ensure that the Node.js API allows requests from all origins (for testing purposes) or from the specific origin of your Flutter app.

const cors = require('cors');
app.use(cors()); // Allow requests from any origin for testing

e. Network Configuration and Routing

The fact that both devices can ping each other suggests the basic network connectivity is working, but sometimes certain types of network traffic (such as HTTP responses) can behave differently due to routing configurations.

Solution:
  • Use netstat or lsof on the Node.js server to confirm the server is listening on port 3000 correctly.
  • Try a different port: Temporarily change the Node.js server to listen on another port (e.g., 3001) and check if the Flutter app can reach it.
  • Test with CURL or Postman from the same device: Try sending a request to http://192.168.10.15:3000/ping from a browser, CURL, or Postman on the Flutter device itself. This can help identify if the issue is specific to Dio or if it’s a broader network issue.

3. Debugging the Issue

a. Test with Curl/Postman from the Same Device

Try sending a request directly from your Flutter device (or a laptop/PC on the same LAN) to the Node.js API:

curl -v http://192.168.10.15:3000/ping

This can help you verify if the issue is with the Flutter app (Dio) or the network configuration.

b. Add Detailed Logging on the Server

Add more logging in the Node.js API to track the entire request lifecycle. For example:

router.get("/ping", (req, res) => {
  console.log('Received ping request from:', req.ip);
  res.status(200).json({ status: "success", message: "pong" });
  console.log('Response sent');
});

This will allow you to see if the request is getting fully processed and the response is being sent back properly.

c. Test Response from Another Device

Test the same API from a different device (e.g., a laptop or mobile device on the same Wi-Fi network) to ensure the issue is not specific to the Flutter device.

4. Recap and Actions

  • Increase the Dio connectTimeout and receiveTimeout.
  • Double-check server-side logs for any issues related to response sending.
  • Ensure CORS is properly configured if your Flutter app is running in a browser or has other cross-origin considerations.
  • Test network routes between LAN and WiFi to ensure there are no issues with routing.
  • Confirm Node.js is listening properly on the server and that the router doesn’t block or isolate devices on LAN/WiFi.

By following these steps, you should be able to identify the root cause of the connectivity issue.