Skip to content

Conversation

@Aarushsr12
Copy link
Contributor

@Aarushsr12 Aarushsr12 commented Jan 29, 2026

URL Port was required for customLookup, hence used Interceptors of axios API
check doc for reference https://axios-http.com/docs/interceptors

For non-localhost requests, axios default dns resolution will internally it, we do not custom lookup for them

How to test

  1. test it on localhost:3000
  2. run on the local endpoints of the emulator run
  3. any dev server
  4. hosted api endpoints

Summary by CodeRabbit

  • Bug Fixes
    • Improved IPv6 localhost connectivity with automatic IPv4 fallback support
    • Enhanced dynamic hostname resolution for local network requests
    • Optimized local connection handling to improve request routing efficiency

✏️ Tip: You can customize this high-level summary in your review settings.

@linear
Copy link

linear bot commented Jan 29, 2026

@coderabbitai
Copy link

coderabbitai bot commented Jan 29, 2026

Walkthrough

Adds IPv6/IPv4 probing and dynamic localhost resolution for requests targeting localhost. Introduces helpers checkConnection and createLocalhostLookup and constants for localhost addresses. The createAxiosInstance signature is changed to accept enableRQProxy?: boolean (default false) and optional addStoredCookies. When enableRQProxy is false, Axios instances are created without a proxy and a request interceptor rewrites localhost requests to use a custom Agent with dynamic localhost lookup (preferring IPv6 when reachable, falling back to IPv4). When enableRQProxy is true, the existing proxy-based path with HttpsProxyAgent and CA handling is preserved. createOrUpdateAxiosInstance calls updated to pass enableRQProxy false and enable stored cookies for session-cookie usage.

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~45 minutes

Possibly related PRs

Suggested reviewers

  • wrongsahil
  • nsrCodes
🚥 Pre-merge checks | ✅ 2 | ❌ 1
❌ Failed checks (1 warning)
Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (2 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title accurately reflects the main changes: removing proxy functionality and implementing localhost resolution with custom DNS lookup for API requests.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing touches
  • 📝 Generate docstrings
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch ENGG-5085

Tip

🧪 Unit Test Generation v2 is now available!

We have significantly improved our unit test generation capabilities.

To enable: Add this to your .coderabbit.yaml configuration:

reviews:
  finishing_touches:
    unit_tests:
      enabled: true

Try it out by using the @coderabbitai generate unit tests command on your code files or under ✨ Finishing Touches on the walkthrough!

Have feedback? Share your thoughts on our Discord thread!


Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

const lookup = await createLocalhostLookup(port);

requestConfig.httpAgent = new http.Agent({ lookup });
requestConfig.httpsAgent = new https.Agent({ lookup });
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

why add it to https agent? is it needed there as well?

Copy link
Contributor Author

@Aarushsr12 Aarushsr12 Jan 29, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not needed though, do local setups use https://localhost ?

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

you are right, no harm in keeping it

@Aarushsr12
Copy link
Contributor Author

@CodeRabbitReview

@coderabbitai
Copy link

coderabbitai bot commented Jan 29, 2026

@Aarushsr12, I'll review the changes in this pull request now.

✅ Actions performed

Review triggered.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🤖 Fix all issues with AI agents
In `@src/main/actions/getProxiedAxios.ts`:
- Around line 97-115: The request interceptor crashes on relative URLs because
new URL(requestUrl) throws; update instance.interceptors.request.use to guard
URL parsing by using requestConfig.baseURL as the fallback (i.e., try new
URL(requestUrl, requestConfig.baseURL)) and wrap construction in a try/catch
that returns requestConfig on parse failure; only proceed to check hostname/port
and call createLocalhostLookup when URL construction succeeds, and keep setting
requestConfig.httpAgent/httpsAgent as before.

Comment on lines +97 to +115
instance.interceptors.request.use(async (requestConfig) => {
const { url: requestUrl } = requestConfig;

if (!requestUrl) {
return requestConfig;
}

const url = new URL(requestUrl);
const { hostname, port: urlPort, protocol } = url;

if (hostname === "localhost" || hostname === LOCAL_IPV6 || hostname === LOCAL_IPV4) {
// convert string port to integer
const port = urlPort ? parseInt(urlPort, 10) : protocol === "https:" ? 443 : 80;

const lookup = await createLocalhostLookup(port);

requestConfig.httpAgent = new http.Agent({ lookup });
requestConfig.httpsAgent = new https.Agent({ lookup });
}
Copy link

@coderabbitai coderabbitai bot Jan 30, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

🧩 Analysis chain

🏁 Script executed:

# Read the file to see the context and current implementation
cat -n src/main/actions/getProxiedAxios.ts | head -130 | tail -50

Repository: requestly/requestly-desktop-app

Length of output: 1847


🏁 Script executed:

node <<'EOF'
// Test URL constructor with relative paths
console.log("Test 1: Absolute URL");
try {
  const url1 = new URL("https://example.com/path");
  console.log("✓ Success:", url1.href);
} catch (e) {
  console.log("✗ Error:", e.message);
}

console.log("\nTest 2: Relative URL without base");
try {
  const url2 = new URL("/path");
  console.log("✓ Success:", url2.href);
} catch (e) {
  console.log("✗ Error:", e.message);
}

console.log("\nTest 3: Relative URL with base parameter");
try {
  const url3 = new URL("/path", "https://example.com");
  console.log("✓ Success:", url3.href);
} catch (e) {
  console.log("✗ Error:", e.message);
}

console.log("\nTest 4: Simple relative path");
try {
  const url4 = new URL("api/endpoint");
  console.log("✓ Success:", url4.href);
} catch (e) {
  console.log("✗ Error:", e.message);
}

console.log("\nTest 5: Simple relative path with base");
try {
  const url5 = new URL("api/endpoint", "https://example.com");
  console.log("✓ Success:", url5.href);
} catch (e) {
  console.log("✗ Error:", e.message);
}
EOF

Repository: requestly/requestly-desktop-app

Length of output: 400


🏁 Script executed:

# Search for axios creation with baseURL
rg "axios\.create|baseURL" --type ts --type js -A 3 -B 1

Repository: requestly/requestly-desktop-app

Length of output: 703


🏁 Script executed:

# Search for usage of getProxiedAxios
rg "getProxiedAxios|createOrUpdateAxiosInstance" --type ts --type js -B 2 -A 5

Repository: requestly/requestly-desktop-app

Length of output: 3612


🏁 Script executed:

# Read makeApiClientRequest to see how axios is used
cat -n src/main/actions/makeApiClientRequest.js | head -120 | tail -80

Repository: requestly/requestly-desktop-app

Length of output: 2929


🏁 Script executed:

# Read the start of makeApiClientRequest to see the function signature and URL source
cat -n src/main/actions/makeApiClientRequest.js | head -40

Repository: requestly/requestly-desktop-app

Length of output: 1599


Guard URL parsing against relative url values.

new URL(requestUrl) throws for relative paths, which will crash the interceptor and prevent requests from being sent. This is particularly important for applications using axios with baseURL or for handling edge cases with relative URLs. Extract baseURL from requestConfig and use it as a fallback parameter to the URL constructor, returning early if parsing fails.

🛠️ Proposed fix
-    instance.interceptors.request.use(async (requestConfig) => {
-      const { url: requestUrl } = requestConfig;
+    instance.interceptors.request.use(async (requestConfig) => {
+      const { url: requestUrl, baseURL } = requestConfig;
 
       if (!requestUrl) {
         return requestConfig;
       }
 
-      const url = new URL(requestUrl);
+      let url: URL;
+      try {
+        url = baseURL ? new URL(requestUrl, baseURL) : new URL(requestUrl);
+      } catch {
+        return requestConfig;
+      }
       const { hostname, port: urlPort, protocol } = url;
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
instance.interceptors.request.use(async (requestConfig) => {
const { url: requestUrl } = requestConfig;
if (!requestUrl) {
return requestConfig;
}
const url = new URL(requestUrl);
const { hostname, port: urlPort, protocol } = url;
if (hostname === "localhost" || hostname === LOCAL_IPV6 || hostname === LOCAL_IPV4) {
// convert string port to integer
const port = urlPort ? parseInt(urlPort, 10) : protocol === "https:" ? 443 : 80;
const lookup = await createLocalhostLookup(port);
requestConfig.httpAgent = new http.Agent({ lookup });
requestConfig.httpsAgent = new https.Agent({ lookup });
}
instance.interceptors.request.use(async (requestConfig) => {
const { url: requestUrl, baseURL } = requestConfig;
if (!requestUrl) {
return requestConfig;
}
let url: URL;
try {
url = baseURL ? new URL(requestUrl, baseURL) : new URL(requestUrl);
} catch {
return requestConfig;
}
const { hostname, port: urlPort, protocol } = url;
if (hostname === "localhost" || hostname === LOCAL_IPV6 || hostname === LOCAL_IPV4) {
// convert string port to integer
const port = urlPort ? parseInt(urlPort, 10) : protocol === "https:" ? 443 : 80;
const lookup = await createLocalhostLookup(port);
requestConfig.httpAgent = new http.Agent({ lookup });
requestConfig.httpsAgent = new https.Agent({ lookup });
}
🤖 Prompt for AI Agents
In `@src/main/actions/getProxiedAxios.ts` around lines 97 - 115, The request
interceptor crashes on relative URLs because new URL(requestUrl) throws; update
instance.interceptors.request.use to guard URL parsing by using
requestConfig.baseURL as the fallback (i.e., try new URL(requestUrl,
requestConfig.baseURL)) and wrap construction in a try/catch that returns
requestConfig on parse failure; only proceed to check hostname/port and call
createLocalhostLookup when URL construction succeeds, and keep setting
requestConfig.httpAgent/httpsAgent as before.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

can you explain this by some examples ?

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@Aarushsr12, sure! Let me explain with concrete examples:

The Problem

The new URL() constructor requires an absolute URL (with protocol). If you pass a relative URL, it throws an error:

// ✅ Works - absolute URL
new URL('https://api.example.com/users')
// Result: { hostname: 'api.example.com', ... }

// ❌ Crashes - relative URL
new URL('/api/users')
// Throws: TypeError: Invalid URL

// ❌ Crashes - relative path
new URL('api/users')
// Throws: TypeError: Invalid URL

Why This Matters for Axios

When using axios, you can configure requests in different ways:

// Scenario 1: Absolute URL - works fine
axios.get('https://api.example.com/users')

// Scenario 2: Using baseURL with relative path - CRASHES with current code
const client = axios.create({ baseURL: 'https://api.example.com' })
client.get('/users')  // requestUrl = '/users' → new URL('/users') throws!

// Scenario 3: Just a path - CRASHES with current code
axios.get('/api/users')

The Fix

By using baseURL as the second parameter to the URL constructor, we can safely parse relative URLs:

// Before (crashes):
const url = new URL('/users')  // ❌ Throws

// After (works):
const url = new URL('/users', 'https://api.example.com')  // ✅ Returns full URL

// The try-catch ensures any parsing errors don't break the request:
try {
  url = baseURL ? new URL(requestUrl, baseURL) : new URL(requestUrl);
} catch {
  return requestConfig;  // Skip localhost handling, let axios handle it normally
}

Practical Impact

Without the fix, if your API client code uses:

const apiClient = getProxiedAxios();
apiClient.defaults.baseURL = 'https://api.requestly.io';
apiClient.get('/users');  // This would crash the interceptor

With the fix, the interceptor gracefully handles it by constructing the full URL and checking if it's localhost before applying the custom DNS lookup.

Does this clarify the issue?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants