Skip to content

fix: respect HTTPJAIL_HTTP_BIND and HTTPJAIL_HTTPS_BIND in server mode - #80

Merged
ammario merged 7 commits into
mainfrom
fix-bind
Nov 3, 2025
Merged

fix: respect HTTPJAIL_HTTP_BIND and HTTPJAIL_HTTPS_BIND in server mode#80
ammario merged 7 commits into
mainfrom
fix-bind

Conversation

@ammar-agent

@ammar-agentammar-agent commented Nov 2, 2025

Copy link
Copy Markdown
Contributor

Fixes#79

Summary

The server mode was ignoring the IP addresses specified in the HTTPJAIL_HTTP_BIND and HTTPJAIL_HTTPS_BIND environment variables, always binding to localhost instead.

This PR refactors the proxy binding logic to use std::net::SocketAddr throughout, which provides a cleaner API that supports both IPv4 and IPv6 while combining IP and port into a single type.

Changes

  • Refactored ProxyServer struct to use Option<SocketAddr> for http_bind and https_bind instead of separate IP and port fields
  • Created unified bind_listener() function that handles both IPv4 and IPv6
  • Removed redundant bind_ipv4_listener() function
  • Simplified parse_bind_config() to return Option<SocketAddr> directly
  • Fixed strong jail mode to properly bind to computed jail IP with port 0 for auto-selection when no port is specified

Testing

✅ All tests passing:

  • 45/45 unit tests pass
  • 23/23 integration tests pass
  • Clippy passes with -D warnings
  • Code formatted with cargo fmt

✅ Functional verification:

  • Server mode correctly binds to 0.0.0.0 when configured
  • Server mode correctly binds to specific IPv4 addresses
  • Strong jail mode still works (binds to computed jail IP)
  • Port auto-selection works in all modes

Supported Bind Address Formats

  • "ip:port" (e.g., "0.0.0.0:8080", "127.0.0.1:8080")
  • "[ipv6]:port" (e.g., "[::1]:8080")
  • "port" (defaults to localhost)

Backward Compatibility

The fix maintains full backward compatibility while resolving the reported issue.

@ammar-agent
ammar-agentforce-pushed the fix-bind branch 2 times, most recently from 9e8690a to 1f3357bCompareNovember 3, 2025 15:03
@ammario
ammario marked this pull request as ready for review November 3, 2025 15:04

@chatgpt-codex-connectorchatgpt-codex-connectorBot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment threadsrc/main.rs
Comment on lines +503 to +505
// Try parsing as just a port number - bind to all interfaces (0.0.0.0)
if let Ok(port) = val.parse::<u16>() {
return Some(std::net::SocketAddr::from(([0, 0, 0, 0], port)));

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P1 Badge Port-only bind exposes server on all interfaces

When the bind environment variables contain only a port, the new parser builds a SocketAddr with 0.0.0.0, so HTTPJAIL_HTTP_BIND=8080 now listens on every interface. Previously such configuration bound to loopback, and the commit summary still claims that the port-only format defaults to localhost. This change silently broadens the listener’s exposure and can unintentionally publish the proxy to the whole network. It would be safer to keep the default IP at 127.0.0.1 and only bind to 0.0.0.0 when the user explicitly supplies an address.

Useful? React with 👍 / 👎.

Fixes#79
The server mode was ignoring the IP addresses specified in the
HTTPJAIL_HTTP_BIND and HTTPJAIL_HTTPS_BIND environment variables,
always binding to localhost instead.
This commit refactors the proxy binding logic to use std::net::SocketAddr
throughout, which provides a cleaner API that supports both IPv4 and IPv6
while combining IP and port into a single type.
Changes:
- Refactored ProxyServer struct to use Option<SocketAddr> for http_bind
and https_bind instead of separate IP and port fields
- Created unified bind_listener() function that handles both IPv4 and IPv6
- Removed redundant bind_ipv4_listener() function
- Simplified parse_bind_config() to return Option<SocketAddr> directly
- Fixed strong jail mode to properly bind to computed jail IP with port 0
for auto-selection when no port is specified
The fix maintains backward compatibility and passes all tests:
- 45/45 unit tests pass
- 23/23 integration tests pass
- Clippy passes with -D warnings
Supported formats for bind addresses:
- "ip:port" (e.g., "0.0.0.0:8080", "127.0.0.1:8080")
- "[ipv6]:port" (e.g., "[::1]:8080")
- "port" (defaults to localhost)
- Port-only config (e.g., '8080') now binds to 0.0.0.0 (all interfaces) following Go convention
- DRY up bind_str logic with closure instead of duplicating for HTTP/HTTPS
- DRY up bind resolution with resolve_bind_with_default() helper
- Simplify parse_ip_from_env() to one-liner
- Add #[serial] to all server bind tests to prevent port conflicts
- Respect explicit port 0 for OS auto-selection
- Clean verbosity logic: server mode defaults to INFO level
Fixes#79
Previously this test passed port-only (e.g., '19876') which now binds
to 0.0.0.0 (all interfaces) per Go convention. The test expects localhost
binding, so explicitly specify '127.0.0.1:PORT' format.
This commit adds support for the Go-style :port bind syntax (e.g., :80, :8080)
which binds to all interfaces (0.0.0.0) on the specified port.
Changes:
- Updated parse_bind_config() to handle :port format
- Added test_server_bind_colon_prefix_port test
- Updated start_server_with_bind() helper to parse :port format
Now supports all bind formats:
- "80" -> 0.0.0.0:80
- ":80" -> 0.0.0.0:80 (new)
- "127.0.0.1:80" -> 127.0.0.1:80
- "127.0.0.1" -> 127.0.0.1:8080 (server mode default)
@ammario
ammario merged commit 321d0e6 into mainNov 3, 2025
6 checks passed
@ammario
ammario deleted the fix-bind branch November 3, 2025 15:22
Sign up for freeto 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.

Server mode always binds on localhost

2 participants

@ammar-agent@ammario
, 'i'); if (__m === '*' || __re.test(location.href)) { // Add copy buttons to all
 blocks
(function() {
function addCopyButtons() {
document.querySelectorAll('pre code').forEach(function(codeBlock) {
if (codeBlock.parentElement.hasAttribute('data-copy-added')) return;
codeBlock.parentElement.setAttribute('data-copy-added', 'true');
var btn = document.createElement('button');
btn.textContent = 'Copy';
btn.style.cssText = 'position:absolute;top:4px;right:4px;padding:2px 8px;font-size:11px;background:#4ecdc4;border:none;border-radius:4px;color:#1a1a2e;cursor:pointer;opacity:0.7;transition:opacity 0.2s;';
btn.onmouseover = function() { this.style.opacity = '1'; };
btn.onmouseout = function() { this.style.opacity = '0.7'; };
btn.onclick = function() {
navigator.clipboard.writeText(codeBlock.textContent).then(function() {
btn.textContent = 'Copied!';
setTimeout(function() { btn.textContent = 'Copy'; }, 1500);
});
};
codeBlock.parentElement.style.position = 'relative';
codeBlock.parentElement.appendChild(btn);
});
}
addCopyButtons();
// Re-run on dynamic content
var observer = new MutationObserver(addCopyButtons);
observer.observe(document.body, { childList: true, subtree: true });
})();
}
} catch(__e) { console.warn('[Userscript:Add Copy Buttons to Code Blocks]', __e); }
})();
(function(){
try {
var __m = "github.com";
var __re = new RegExp('^' + "github\\.com" + '
fix: respect HTTPJAIL_HTTP_BIND and HTTPJAIL_HTTPS_BIND in server mode by ammar-agent · Pull Request #80 · coder/httpjail · GitHub
Skip to content

fix: respect HTTPJAIL_HTTP_BIND and HTTPJAIL_HTTPS_BIND in server mode - #80

Merged
ammario merged 7 commits into
mainfrom
fix-bind
Nov 3, 2025
Merged

fix: respect HTTPJAIL_HTTP_BIND and HTTPJAIL_HTTPS_BIND in server mode#80
ammario merged 7 commits into
mainfrom
fix-bind

Conversation

@ammar-agent

@ammar-agentammar-agent commented Nov 2, 2025

Copy link
Copy Markdown
Contributor

Fixes#79

Summary

The server mode was ignoring the IP addresses specified in the HTTPJAIL_HTTP_BIND and HTTPJAIL_HTTPS_BIND environment variables, always binding to localhost instead.

This PR refactors the proxy binding logic to use std::net::SocketAddr throughout, which provides a cleaner API that supports both IPv4 and IPv6 while combining IP and port into a single type.

Changes

  • Refactored ProxyServer struct to use Option<SocketAddr> for http_bind and https_bind instead of separate IP and port fields
  • Created unified bind_listener() function that handles both IPv4 and IPv6
  • Removed redundant bind_ipv4_listener() function
  • Simplified parse_bind_config() to return Option<SocketAddr> directly
  • Fixed strong jail mode to properly bind to computed jail IP with port 0 for auto-selection when no port is specified

Testing

✅ All tests passing:

  • 45/45 unit tests pass
  • 23/23 integration tests pass
  • Clippy passes with -D warnings
  • Code formatted with cargo fmt

✅ Functional verification:

  • Server mode correctly binds to 0.0.0.0 when configured
  • Server mode correctly binds to specific IPv4 addresses
  • Strong jail mode still works (binds to computed jail IP)
  • Port auto-selection works in all modes

Supported Bind Address Formats

  • "ip:port" (e.g., "0.0.0.0:8080", "127.0.0.1:8080")
  • "[ipv6]:port" (e.g., "[::1]:8080")
  • "port" (defaults to localhost)

Backward Compatibility

The fix maintains full backward compatibility while resolving the reported issue.

@ammar-agent
ammar-agentforce-pushed the fix-bind branch 2 times, most recently from 9e8690a to 1f3357bCompareNovember 3, 2025 15:03
@ammario
ammario marked this pull request as ready for review November 3, 2025 15:04

@chatgpt-codex-connectorchatgpt-codex-connectorBot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment threadsrc/main.rs
Comment on lines +503 to +505
// Try parsing as just a port number - bind to all interfaces (0.0.0.0)
if let Ok(port) = val.parse::<u16>() {
return Some(std::net::SocketAddr::from(([0, 0, 0, 0], port)));

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P1 Badge Port-only bind exposes server on all interfaces

When the bind environment variables contain only a port, the new parser builds a SocketAddr with 0.0.0.0, so HTTPJAIL_HTTP_BIND=8080 now listens on every interface. Previously such configuration bound to loopback, and the commit summary still claims that the port-only format defaults to localhost. This change silently broadens the listener’s exposure and can unintentionally publish the proxy to the whole network. It would be safer to keep the default IP at 127.0.0.1 and only bind to 0.0.0.0 when the user explicitly supplies an address.

Useful? React with 👍 / 👎.

Fixes#79
The server mode was ignoring the IP addresses specified in the
HTTPJAIL_HTTP_BIND and HTTPJAIL_HTTPS_BIND environment variables,
always binding to localhost instead.
This commit refactors the proxy binding logic to use std::net::SocketAddr
throughout, which provides a cleaner API that supports both IPv4 and IPv6
while combining IP and port into a single type.
Changes:
- Refactored ProxyServer struct to use Option<SocketAddr> for http_bind
and https_bind instead of separate IP and port fields
- Created unified bind_listener() function that handles both IPv4 and IPv6
- Removed redundant bind_ipv4_listener() function
- Simplified parse_bind_config() to return Option<SocketAddr> directly
- Fixed strong jail mode to properly bind to computed jail IP with port 0
for auto-selection when no port is specified
The fix maintains backward compatibility and passes all tests:
- 45/45 unit tests pass
- 23/23 integration tests pass
- Clippy passes with -D warnings
Supported formats for bind addresses:
- "ip:port" (e.g., "0.0.0.0:8080", "127.0.0.1:8080")
- "[ipv6]:port" (e.g., "[::1]:8080")
- "port" (defaults to localhost)
- Port-only config (e.g., '8080') now binds to 0.0.0.0 (all interfaces) following Go convention
- DRY up bind_str logic with closure instead of duplicating for HTTP/HTTPS
- DRY up bind resolution with resolve_bind_with_default() helper
- Simplify parse_ip_from_env() to one-liner
- Add #[serial] to all server bind tests to prevent port conflicts
- Respect explicit port 0 for OS auto-selection
- Clean verbosity logic: server mode defaults to INFO level
Fixes#79
Previously this test passed port-only (e.g., '19876') which now binds
to 0.0.0.0 (all interfaces) per Go convention. The test expects localhost
binding, so explicitly specify '127.0.0.1:PORT' format.
This commit adds support for the Go-style :port bind syntax (e.g., :80, :8080)
which binds to all interfaces (0.0.0.0) on the specified port.
Changes:
- Updated parse_bind_config() to handle :port format
- Added test_server_bind_colon_prefix_port test
- Updated start_server_with_bind() helper to parse :port format
Now supports all bind formats:
- "80" -> 0.0.0.0:80
- ":80" -> 0.0.0.0:80 (new)
- "127.0.0.1:80" -> 127.0.0.1:80
- "127.0.0.1" -> 127.0.0.1:8080 (server mode default)
@ammario
ammario merged commit 321d0e6 into mainNov 3, 2025
6 checks passed
@ammario
ammario deleted the fix-bind branch November 3, 2025 15:22
Sign up for freeto 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.

Server mode always binds on localhost

2 participants

@ammar-agent@ammario
, 'i'); if (__m === '*' || __re.test(location.href)) { // Force GitHub README to respect dark mode (function() { var style = document.createElement('style'); style.textContent = ' .markdown-body { color-scheme: dark light; } .markdown-body pre { background: #161b22 !important; } .markdown-body code { background: rgba(110, 118, 129, 0.4) !important; } .markdown-body table th, .markdown-body table td { border-color: #30363d !important; } .markdown-body img { background: #0d1117; } .markdown-body blockquote { border-left-color: #8b949e; } .markdown-body hr { border-color: #30363d; } '; document.head.appendChild(style); })(); } } catch(__e) { console.warn('[Userscript:GitHub Dark Mode README Fix]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + ' fix: respect HTTPJAIL_HTTP_BIND and HTTPJAIL_HTTPS_BIND in server mode by ammar-agent · Pull Request #80 · coder/httpjail · GitHub
Skip to content

fix: respect HTTPJAIL_HTTP_BIND and HTTPJAIL_HTTPS_BIND in server mode - #80

Merged
ammario merged 7 commits into
mainfrom
fix-bind
Nov 3, 2025
Merged

fix: respect HTTPJAIL_HTTP_BIND and HTTPJAIL_HTTPS_BIND in server mode#80
ammario merged 7 commits into
mainfrom
fix-bind

Conversation

@ammar-agent

@ammar-agentammar-agent commented Nov 2, 2025

Copy link
Copy Markdown
Contributor

Fixes#79

Summary

The server mode was ignoring the IP addresses specified in the HTTPJAIL_HTTP_BIND and HTTPJAIL_HTTPS_BIND environment variables, always binding to localhost instead.

This PR refactors the proxy binding logic to use std::net::SocketAddr throughout, which provides a cleaner API that supports both IPv4 and IPv6 while combining IP and port into a single type.

Changes

  • Refactored ProxyServer struct to use Option<SocketAddr> for http_bind and https_bind instead of separate IP and port fields
  • Created unified bind_listener() function that handles both IPv4 and IPv6
  • Removed redundant bind_ipv4_listener() function
  • Simplified parse_bind_config() to return Option<SocketAddr> directly
  • Fixed strong jail mode to properly bind to computed jail IP with port 0 for auto-selection when no port is specified

Testing

✅ All tests passing:

  • 45/45 unit tests pass
  • 23/23 integration tests pass
  • Clippy passes with -D warnings
  • Code formatted with cargo fmt

✅ Functional verification:

  • Server mode correctly binds to 0.0.0.0 when configured
  • Server mode correctly binds to specific IPv4 addresses
  • Strong jail mode still works (binds to computed jail IP)
  • Port auto-selection works in all modes

Supported Bind Address Formats

  • "ip:port" (e.g., "0.0.0.0:8080", "127.0.0.1:8080")
  • "[ipv6]:port" (e.g., "[::1]:8080")
  • "port" (defaults to localhost)

Backward Compatibility

The fix maintains full backward compatibility while resolving the reported issue.

@ammar-agent
ammar-agentforce-pushed the fix-bind branch 2 times, most recently from 9e8690a to 1f3357bCompareNovember 3, 2025 15:03
@ammario
ammario marked this pull request as ready for review November 3, 2025 15:04

@chatgpt-codex-connectorchatgpt-codex-connectorBot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment threadsrc/main.rs
Comment on lines +503 to +505
// Try parsing as just a port number - bind to all interfaces (0.0.0.0)
if let Ok(port) = val.parse::<u16>() {
return Some(std::net::SocketAddr::from(([0, 0, 0, 0], port)));

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P1 Badge Port-only bind exposes server on all interfaces

When the bind environment variables contain only a port, the new parser builds a SocketAddr with 0.0.0.0, so HTTPJAIL_HTTP_BIND=8080 now listens on every interface. Previously such configuration bound to loopback, and the commit summary still claims that the port-only format defaults to localhost. This change silently broadens the listener’s exposure and can unintentionally publish the proxy to the whole network. It would be safer to keep the default IP at 127.0.0.1 and only bind to 0.0.0.0 when the user explicitly supplies an address.

Useful? React with 👍 / 👎.

Fixes#79
The server mode was ignoring the IP addresses specified in the
HTTPJAIL_HTTP_BIND and HTTPJAIL_HTTPS_BIND environment variables,
always binding to localhost instead.
This commit refactors the proxy binding logic to use std::net::SocketAddr
throughout, which provides a cleaner API that supports both IPv4 and IPv6
while combining IP and port into a single type.
Changes:
- Refactored ProxyServer struct to use Option<SocketAddr> for http_bind
and https_bind instead of separate IP and port fields
- Created unified bind_listener() function that handles both IPv4 and IPv6
- Removed redundant bind_ipv4_listener() function
- Simplified parse_bind_config() to return Option<SocketAddr> directly
- Fixed strong jail mode to properly bind to computed jail IP with port 0
for auto-selection when no port is specified
The fix maintains backward compatibility and passes all tests:
- 45/45 unit tests pass
- 23/23 integration tests pass
- Clippy passes with -D warnings
Supported formats for bind addresses:
- "ip:port" (e.g., "0.0.0.0:8080", "127.0.0.1:8080")
- "[ipv6]:port" (e.g., "[::1]:8080")
- "port" (defaults to localhost)
- Port-only config (e.g., '8080') now binds to 0.0.0.0 (all interfaces) following Go convention
- DRY up bind_str logic with closure instead of duplicating for HTTP/HTTPS
- DRY up bind resolution with resolve_bind_with_default() helper
- Simplify parse_ip_from_env() to one-liner
- Add #[serial] to all server bind tests to prevent port conflicts
- Respect explicit port 0 for OS auto-selection
- Clean verbosity logic: server mode defaults to INFO level
Fixes#79
Previously this test passed port-only (e.g., '19876') which now binds
to 0.0.0.0 (all interfaces) per Go convention. The test expects localhost
binding, so explicitly specify '127.0.0.1:PORT' format.
This commit adds support for the Go-style :port bind syntax (e.g., :80, :8080)
which binds to all interfaces (0.0.0.0) on the specified port.
Changes:
- Updated parse_bind_config() to handle :port format
- Added test_server_bind_colon_prefix_port test
- Updated start_server_with_bind() helper to parse :port format
Now supports all bind formats:
- "80" -> 0.0.0.0:80
- ":80" -> 0.0.0.0:80 (new)
- "127.0.0.1:80" -> 127.0.0.1:80
- "127.0.0.1" -> 127.0.0.1:8080 (server mode default)
@ammario
ammario merged commit 321d0e6 into mainNov 3, 2025
6 checks passed
@ammario
ammario deleted the fix-bind branch November 3, 2025 15:22
Sign up for freeto 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.

Server mode always binds on localhost

2 participants

@ammar-agent@ammario
, 'i'); if (__m === '*' || __re.test(location.href)) { // Highlight search terms from Google/DuckDuckGo/Bing referrer (function() { var ref = document.referrer; var terms = []; if (ref.includes('google.com') || ref.includes('duckduckgo.com') || ref.includes('bing.com')) { var url = new URL(ref); var q = url.searchParams.get('q') || url.searchParams.get('p'); if (q) { terms = q.split(/\s+/).filter(function(t) { return t.length > 2; }); } } if (terms.length === 0) return; var style = document.createElement('style'); style.textContent = '.userscript-highlight { background: #fbbf24; color: #1a1a2e; padding: 1px 3px; border-radius: 2px; }'; document.head.appendChild(style); function highlight(node) { if (node.nodeType === 3) { // text node var text = node.textContent; var found = false; terms.forEach(function(term) { var regex = new RegExp('(' + term.replace(/[.*+?^${}()|[\]\\]/g, '\\') + ')', 'gi'); if (regex.test(text)) { found = true; var frag = document.createDocumentFragment(); var parts = text.split(regex); parts.forEach(function(part, i) { if (i % 2 === 0) { frag.appendChild(document.createTextNode(part)); } else { var span = document.createElement('span'); span.className = 'userscript-highlight'; span.textContent = part; frag.appendChild(span); } }); node.parentNode.replaceChild(frag, node); } }); } else if (node.nodeType === 1 && node.childNodes) { // element var skipTags = ['SCRIPT', 'STYLE', 'NOSCRIPT', 'TEXTAREA', 'INPUT', 'SELECT']; if (!skipTags.includes(node.tagName)) { Array.from(node.childNodes).forEach(highlight); } } } highlight(document.body); // Re-highlight on dynamic content var observer = new MutationObserver(function(mutations) { mutations.forEach(function(m) { m.addedNodes.forEach(function(node) { if (node.nodeType === 1 || node.nodeType === 3) highlight(node); }); }); }); observer.observe(document.body, { childList: true, subtree: true }); })(); } } catch(__e) { console.warn('[Userscript:Highlight Search Terms]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + ' fix: respect HTTPJAIL_HTTP_BIND and HTTPJAIL_HTTPS_BIND in server mode by ammar-agent · Pull Request #80 · coder/httpjail · GitHub
Skip to content

fix: respect HTTPJAIL_HTTP_BIND and HTTPJAIL_HTTPS_BIND in server mode - #80

Merged
ammario merged 7 commits into
mainfrom
fix-bind
Nov 3, 2025
Merged

fix: respect HTTPJAIL_HTTP_BIND and HTTPJAIL_HTTPS_BIND in server mode#80
ammario merged 7 commits into
mainfrom
fix-bind

Conversation

@ammar-agent

@ammar-agentammar-agent commented Nov 2, 2025

Copy link
Copy Markdown
Contributor

Fixes#79

Summary

The server mode was ignoring the IP addresses specified in the HTTPJAIL_HTTP_BIND and HTTPJAIL_HTTPS_BIND environment variables, always binding to localhost instead.

This PR refactors the proxy binding logic to use std::net::SocketAddr throughout, which provides a cleaner API that supports both IPv4 and IPv6 while combining IP and port into a single type.

Changes

  • Refactored ProxyServer struct to use Option<SocketAddr> for http_bind and https_bind instead of separate IP and port fields
  • Created unified bind_listener() function that handles both IPv4 and IPv6
  • Removed redundant bind_ipv4_listener() function
  • Simplified parse_bind_config() to return Option<SocketAddr> directly
  • Fixed strong jail mode to properly bind to computed jail IP with port 0 for auto-selection when no port is specified

Testing

✅ All tests passing:

  • 45/45 unit tests pass
  • 23/23 integration tests pass
  • Clippy passes with -D warnings
  • Code formatted with cargo fmt

✅ Functional verification:

  • Server mode correctly binds to 0.0.0.0 when configured
  • Server mode correctly binds to specific IPv4 addresses
  • Strong jail mode still works (binds to computed jail IP)
  • Port auto-selection works in all modes

Supported Bind Address Formats

  • "ip:port" (e.g., "0.0.0.0:8080", "127.0.0.1:8080")
  • "[ipv6]:port" (e.g., "[::1]:8080")
  • "port" (defaults to localhost)

Backward Compatibility

The fix maintains full backward compatibility while resolving the reported issue.

@ammar-agent
ammar-agentforce-pushed the fix-bind branch 2 times, most recently from 9e8690a to 1f3357bCompareNovember 3, 2025 15:03
@ammario
ammario marked this pull request as ready for review November 3, 2025 15:04

@chatgpt-codex-connectorchatgpt-codex-connectorBot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment threadsrc/main.rs
Comment on lines +503 to +505
// Try parsing as just a port number - bind to all interfaces (0.0.0.0)
if let Ok(port) = val.parse::<u16>() {
return Some(std::net::SocketAddr::from(([0, 0, 0, 0], port)));

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P1 Badge Port-only bind exposes server on all interfaces

When the bind environment variables contain only a port, the new parser builds a SocketAddr with 0.0.0.0, so HTTPJAIL_HTTP_BIND=8080 now listens on every interface. Previously such configuration bound to loopback, and the commit summary still claims that the port-only format defaults to localhost. This change silently broadens the listener’s exposure and can unintentionally publish the proxy to the whole network. It would be safer to keep the default IP at 127.0.0.1 and only bind to 0.0.0.0 when the user explicitly supplies an address.

Useful? React with 👍 / 👎.

Fixes#79
The server mode was ignoring the IP addresses specified in the
HTTPJAIL_HTTP_BIND and HTTPJAIL_HTTPS_BIND environment variables,
always binding to localhost instead.
This commit refactors the proxy binding logic to use std::net::SocketAddr
throughout, which provides a cleaner API that supports both IPv4 and IPv6
while combining IP and port into a single type.
Changes:
- Refactored ProxyServer struct to use Option<SocketAddr> for http_bind
and https_bind instead of separate IP and port fields
- Created unified bind_listener() function that handles both IPv4 and IPv6
- Removed redundant bind_ipv4_listener() function
- Simplified parse_bind_config() to return Option<SocketAddr> directly
- Fixed strong jail mode to properly bind to computed jail IP with port 0
for auto-selection when no port is specified
The fix maintains backward compatibility and passes all tests:
- 45/45 unit tests pass
- 23/23 integration tests pass
- Clippy passes with -D warnings
Supported formats for bind addresses:
- "ip:port" (e.g., "0.0.0.0:8080", "127.0.0.1:8080")
- "[ipv6]:port" (e.g., "[::1]:8080")
- "port" (defaults to localhost)
- Port-only config (e.g., '8080') now binds to 0.0.0.0 (all interfaces) following Go convention
- DRY up bind_str logic with closure instead of duplicating for HTTP/HTTPS
- DRY up bind resolution with resolve_bind_with_default() helper
- Simplify parse_ip_from_env() to one-liner
- Add #[serial] to all server bind tests to prevent port conflicts
- Respect explicit port 0 for OS auto-selection
- Clean verbosity logic: server mode defaults to INFO level
Fixes#79
Previously this test passed port-only (e.g., '19876') which now binds
to 0.0.0.0 (all interfaces) per Go convention. The test expects localhost
binding, so explicitly specify '127.0.0.1:PORT' format.
This commit adds support for the Go-style :port bind syntax (e.g., :80, :8080)
which binds to all interfaces (0.0.0.0) on the specified port.
Changes:
- Updated parse_bind_config() to handle :port format
- Added test_server_bind_colon_prefix_port test
- Updated start_server_with_bind() helper to parse :port format
Now supports all bind formats:
- "80" -> 0.0.0.0:80
- ":80" -> 0.0.0.0:80 (new)
- "127.0.0.1:80" -> 127.0.0.1:80
- "127.0.0.1" -> 127.0.0.1:8080 (server mode default)
@ammario
ammario merged commit 321d0e6 into mainNov 3, 2025
6 checks passed
@ammario
ammario deleted the fix-bind branch November 3, 2025 15:22
Sign up for freeto 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.

Server mode always binds on localhost

2 participants

@ammar-agent@ammario
, 'i'); if (__m === '*' || __re.test(location.href)) { // Strip utm_, fbclid, gclid, etc. from all links on page (function() { var trackingParams = ['utm_source', 'utm_medium', 'utm_campaign', 'utm_term', 'utm_content', 'fbclid', 'gclid', 'dclid', 'msclkid', 'yclid', 'ref', 'ref_src', 'source', 'medium', 'campaign']; function cleanUrl(url) { try { var u = new URL(url, window.location.origin); var changed = false; trackingParams.forEach(function(p) { if (u.searchParams.has(p)) { u.searchParams.delete(p); changed = true; } }); return changed ? u.toString() : url; } catch (e) { return url; } } function cleanLinks() { document.querySelectorAll('a[href]').forEach(function(a) { var clean = cleanUrl(a.href); if (clean !== a.href) a.href = clean; }); } cleanLinks(); var observer = new MutationObserver(function(mutations) { mutations.forEach(function(m) { m.addedNodes.forEach(function(node) { if (node.nodeType === 1) { if (node.tagName === 'A') cleanLinks(); node.querySelectorAll('a[href]').forEach(function(a) { var clean = cleanUrl(a.href); if (clean !== a.href) a.href = clean; }); } }); }); }); observer.observe(document.body, { childList: true, subtree: true }); })(); } } catch(__e) { console.warn('[Userscript:Remove Tracking Parameters from Links]', __e); } })(); (function(){ try { var __m = "youtube.com"; var __re = new RegExp('^' + "youtube\\.com" + ' fix: respect HTTPJAIL_HTTP_BIND and HTTPJAIL_HTTPS_BIND in server mode by ammar-agent · Pull Request #80 · coder/httpjail · GitHub
Skip to content

fix: respect HTTPJAIL_HTTP_BIND and HTTPJAIL_HTTPS_BIND in server mode - #80

Merged
ammario merged 7 commits into
mainfrom
fix-bind
Nov 3, 2025
Merged

fix: respect HTTPJAIL_HTTP_BIND and HTTPJAIL_HTTPS_BIND in server mode#80
ammario merged 7 commits into
mainfrom
fix-bind

Conversation

@ammar-agent

@ammar-agentammar-agent commented Nov 2, 2025

Copy link
Copy Markdown
Contributor

Fixes#79

Summary

The server mode was ignoring the IP addresses specified in the HTTPJAIL_HTTP_BIND and HTTPJAIL_HTTPS_BIND environment variables, always binding to localhost instead.

This PR refactors the proxy binding logic to use std::net::SocketAddr throughout, which provides a cleaner API that supports both IPv4 and IPv6 while combining IP and port into a single type.

Changes

  • Refactored ProxyServer struct to use Option<SocketAddr> for http_bind and https_bind instead of separate IP and port fields
  • Created unified bind_listener() function that handles both IPv4 and IPv6
  • Removed redundant bind_ipv4_listener() function
  • Simplified parse_bind_config() to return Option<SocketAddr> directly
  • Fixed strong jail mode to properly bind to computed jail IP with port 0 for auto-selection when no port is specified

Testing

✅ All tests passing:

  • 45/45 unit tests pass
  • 23/23 integration tests pass
  • Clippy passes with -D warnings
  • Code formatted with cargo fmt

✅ Functional verification:

  • Server mode correctly binds to 0.0.0.0 when configured
  • Server mode correctly binds to specific IPv4 addresses
  • Strong jail mode still works (binds to computed jail IP)
  • Port auto-selection works in all modes

Supported Bind Address Formats

  • "ip:port" (e.g., "0.0.0.0:8080", "127.0.0.1:8080")
  • "[ipv6]:port" (e.g., "[::1]:8080")
  • "port" (defaults to localhost)

Backward Compatibility

The fix maintains full backward compatibility while resolving the reported issue.

@ammar-agent
ammar-agentforce-pushed the fix-bind branch 2 times, most recently from 9e8690a to 1f3357bCompareNovember 3, 2025 15:03
@ammario
ammario marked this pull request as ready for review November 3, 2025 15:04

@chatgpt-codex-connectorchatgpt-codex-connectorBot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment threadsrc/main.rs
Comment on lines +503 to +505
// Try parsing as just a port number - bind to all interfaces (0.0.0.0)
if let Ok(port) = val.parse::<u16>() {
return Some(std::net::SocketAddr::from(([0, 0, 0, 0], port)));

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P1 Badge Port-only bind exposes server on all interfaces

When the bind environment variables contain only a port, the new parser builds a SocketAddr with 0.0.0.0, so HTTPJAIL_HTTP_BIND=8080 now listens on every interface. Previously such configuration bound to loopback, and the commit summary still claims that the port-only format defaults to localhost. This change silently broadens the listener’s exposure and can unintentionally publish the proxy to the whole network. It would be safer to keep the default IP at 127.0.0.1 and only bind to 0.0.0.0 when the user explicitly supplies an address.

Useful? React with 👍 / 👎.

Fixes#79
The server mode was ignoring the IP addresses specified in the
HTTPJAIL_HTTP_BIND and HTTPJAIL_HTTPS_BIND environment variables,
always binding to localhost instead.
This commit refactors the proxy binding logic to use std::net::SocketAddr
throughout, which provides a cleaner API that supports both IPv4 and IPv6
while combining IP and port into a single type.
Changes:
- Refactored ProxyServer struct to use Option<SocketAddr> for http_bind
and https_bind instead of separate IP and port fields
- Created unified bind_listener() function that handles both IPv4 and IPv6
- Removed redundant bind_ipv4_listener() function
- Simplified parse_bind_config() to return Option<SocketAddr> directly
- Fixed strong jail mode to properly bind to computed jail IP with port 0
for auto-selection when no port is specified
The fix maintains backward compatibility and passes all tests:
- 45/45 unit tests pass
- 23/23 integration tests pass
- Clippy passes with -D warnings
Supported formats for bind addresses:
- "ip:port" (e.g., "0.0.0.0:8080", "127.0.0.1:8080")
- "[ipv6]:port" (e.g., "[::1]:8080")
- "port" (defaults to localhost)
- Port-only config (e.g., '8080') now binds to 0.0.0.0 (all interfaces) following Go convention
- DRY up bind_str logic with closure instead of duplicating for HTTP/HTTPS
- DRY up bind resolution with resolve_bind_with_default() helper
- Simplify parse_ip_from_env() to one-liner
- Add #[serial] to all server bind tests to prevent port conflicts
- Respect explicit port 0 for OS auto-selection
- Clean verbosity logic: server mode defaults to INFO level
Fixes#79
Previously this test passed port-only (e.g., '19876') which now binds
to 0.0.0.0 (all interfaces) per Go convention. The test expects localhost
binding, so explicitly specify '127.0.0.1:PORT' format.
This commit adds support for the Go-style :port bind syntax (e.g., :80, :8080)
which binds to all interfaces (0.0.0.0) on the specified port.
Changes:
- Updated parse_bind_config() to handle :port format
- Added test_server_bind_colon_prefix_port test
- Updated start_server_with_bind() helper to parse :port format
Now supports all bind formats:
- "80" -> 0.0.0.0:80
- ":80" -> 0.0.0.0:80 (new)
- "127.0.0.1:80" -> 127.0.0.1:80
- "127.0.0.1" -> 127.0.0.1:8080 (server mode default)
@ammario
ammario merged commit 321d0e6 into mainNov 3, 2025
6 checks passed
@ammario
ammario deleted the fix-bind branch November 3, 2025 15:22
Sign up for freeto 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.

Server mode always binds on localhost

2 participants

@ammar-agent@ammario
, 'i'); if (__m === '*' || __re.test(location.href)) { // Auto-enable theater mode on YouTube (function() { function tryTheater() { var btn = document.querySelector('button[aria-label="Theater mode"], ytd-player #player button[title="Theater mode"]'); if (btn && !btn.classList.contains('activated')) { btn.click(); } } // Try immediately tryTheater(); // Try after navigation (SPA) var lastUrl = location.href; setInterval(function() { if (location.href !== lastUrl) { lastUrl = location.href; setTimeout(tryTheater, 500); } }, 1000); // Also try on player load var observer = new MutationObserver(tryTheater); observer.observe(document.body, { childList: true, subtree: true }); })(); } } catch(__e) { console.warn('[Userscript:YouTube Theater Mode Default]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + ' fix: respect HTTPJAIL_HTTP_BIND and HTTPJAIL_HTTPS_BIND in server mode by ammar-agent · Pull Request #80 · coder/httpjail · GitHub
Skip to content

fix: respect HTTPJAIL_HTTP_BIND and HTTPJAIL_HTTPS_BIND in server mode - #80

Merged
ammario merged 7 commits into
mainfrom
fix-bind
Nov 3, 2025
Merged

fix: respect HTTPJAIL_HTTP_BIND and HTTPJAIL_HTTPS_BIND in server mode#80
ammario merged 7 commits into
mainfrom
fix-bind

Conversation

@ammar-agent

@ammar-agentammar-agent commented Nov 2, 2025

Copy link
Copy Markdown
Contributor

Fixes#79

Summary

The server mode was ignoring the IP addresses specified in the HTTPJAIL_HTTP_BIND and HTTPJAIL_HTTPS_BIND environment variables, always binding to localhost instead.

This PR refactors the proxy binding logic to use std::net::SocketAddr throughout, which provides a cleaner API that supports both IPv4 and IPv6 while combining IP and port into a single type.

Changes

  • Refactored ProxyServer struct to use Option<SocketAddr> for http_bind and https_bind instead of separate IP and port fields
  • Created unified bind_listener() function that handles both IPv4 and IPv6
  • Removed redundant bind_ipv4_listener() function
  • Simplified parse_bind_config() to return Option<SocketAddr> directly
  • Fixed strong jail mode to properly bind to computed jail IP with port 0 for auto-selection when no port is specified

Testing

✅ All tests passing:

  • 45/45 unit tests pass
  • 23/23 integration tests pass
  • Clippy passes with -D warnings
  • Code formatted with cargo fmt

✅ Functional verification:

  • Server mode correctly binds to 0.0.0.0 when configured
  • Server mode correctly binds to specific IPv4 addresses
  • Strong jail mode still works (binds to computed jail IP)
  • Port auto-selection works in all modes

Supported Bind Address Formats

  • "ip:port" (e.g., "0.0.0.0:8080", "127.0.0.1:8080")
  • "[ipv6]:port" (e.g., "[::1]:8080")
  • "port" (defaults to localhost)

Backward Compatibility

The fix maintains full backward compatibility while resolving the reported issue.

@ammar-agent
ammar-agentforce-pushed the fix-bind branch 2 times, most recently from 9e8690a to 1f3357bCompareNovember 3, 2025 15:03
@ammario
ammario marked this pull request as ready for review November 3, 2025 15:04

@chatgpt-codex-connectorchatgpt-codex-connectorBot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment threadsrc/main.rs
Comment on lines +503 to +505
// Try parsing as just a port number - bind to all interfaces (0.0.0.0)
if let Ok(port) = val.parse::<u16>() {
return Some(std::net::SocketAddr::from(([0, 0, 0, 0], port)));

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P1 Badge Port-only bind exposes server on all interfaces

When the bind environment variables contain only a port, the new parser builds a SocketAddr with 0.0.0.0, so HTTPJAIL_HTTP_BIND=8080 now listens on every interface. Previously such configuration bound to loopback, and the commit summary still claims that the port-only format defaults to localhost. This change silently broadens the listener’s exposure and can unintentionally publish the proxy to the whole network. It would be safer to keep the default IP at 127.0.0.1 and only bind to 0.0.0.0 when the user explicitly supplies an address.

Useful? React with 👍 / 👎.

Fixes#79
The server mode was ignoring the IP addresses specified in the
HTTPJAIL_HTTP_BIND and HTTPJAIL_HTTPS_BIND environment variables,
always binding to localhost instead.
This commit refactors the proxy binding logic to use std::net::SocketAddr
throughout, which provides a cleaner API that supports both IPv4 and IPv6
while combining IP and port into a single type.
Changes:
- Refactored ProxyServer struct to use Option<SocketAddr> for http_bind
and https_bind instead of separate IP and port fields
- Created unified bind_listener() function that handles both IPv4 and IPv6
- Removed redundant bind_ipv4_listener() function
- Simplified parse_bind_config() to return Option<SocketAddr> directly
- Fixed strong jail mode to properly bind to computed jail IP with port 0
for auto-selection when no port is specified
The fix maintains backward compatibility and passes all tests:
- 45/45 unit tests pass
- 23/23 integration tests pass
- Clippy passes with -D warnings
Supported formats for bind addresses:
- "ip:port" (e.g., "0.0.0.0:8080", "127.0.0.1:8080")
- "[ipv6]:port" (e.g., "[::1]:8080")
- "port" (defaults to localhost)
- Port-only config (e.g., '8080') now binds to 0.0.0.0 (all interfaces) following Go convention
- DRY up bind_str logic with closure instead of duplicating for HTTP/HTTPS
- DRY up bind resolution with resolve_bind_with_default() helper
- Simplify parse_ip_from_env() to one-liner
- Add #[serial] to all server bind tests to prevent port conflicts
- Respect explicit port 0 for OS auto-selection
- Clean verbosity logic: server mode defaults to INFO level
Fixes#79
Previously this test passed port-only (e.g., '19876') which now binds
to 0.0.0.0 (all interfaces) per Go convention. The test expects localhost
binding, so explicitly specify '127.0.0.1:PORT' format.
This commit adds support for the Go-style :port bind syntax (e.g., :80, :8080)
which binds to all interfaces (0.0.0.0) on the specified port.
Changes:
- Updated parse_bind_config() to handle :port format
- Added test_server_bind_colon_prefix_port test
- Updated start_server_with_bind() helper to parse :port format
Now supports all bind formats:
- "80" -> 0.0.0.0:80
- ":80" -> 0.0.0.0:80 (new)
- "127.0.0.1:80" -> 127.0.0.1:80
- "127.0.0.1" -> 127.0.0.1:8080 (server mode default)
@ammario
ammario merged commit 321d0e6 into mainNov 3, 2025
6 checks passed
@ammario
ammario deleted the fix-bind branch November 3, 2025 15:22
Sign up for freeto 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.

Server mode always binds on localhost

2 participants

@ammar-agent@ammario
, 'i'); if (__m === '*' || __re.test(location.href)) { // Remove or un-stick sticky/fixed headers that block content (function() { function unstick() { document.querySelectorAll('header, nav, [role="banner"], .header, .navbar, .sticky, .fixed-top, [style*="position: fixed"], [style*="position:sticky"]').forEach(function(el) { if (el.style.position === 'fixed' || el.style.position === 'sticky' || getComputedStyle(el).position === 'fixed' || getComputedStyle(el).position === 'sticky') { el.style.position = 'static'; el.style.top = 'auto'; el.style.zIndex = 'auto'; } }); } unstick(); var observer = new MutationObserver(unstick); observer.observe(document.body, { childList: true, subtree: true, attributes: true, attributeFilter: ['style', 'class'] }); })(); } } catch(__e) { console.warn('[Userscript:Kill Sticky Headers]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + ' fix: respect HTTPJAIL_HTTP_BIND and HTTPJAIL_HTTPS_BIND in server mode by ammar-agent · Pull Request #80 · coder/httpjail · GitHub
Skip to content

fix: respect HTTPJAIL_HTTP_BIND and HTTPJAIL_HTTPS_BIND in server mode - #80

Merged
ammario merged 7 commits into
mainfrom
fix-bind
Nov 3, 2025
Merged

fix: respect HTTPJAIL_HTTP_BIND and HTTPJAIL_HTTPS_BIND in server mode#80
ammario merged 7 commits into
mainfrom
fix-bind

Conversation

@ammar-agent

@ammar-agentammar-agent commented Nov 2, 2025

Copy link
Copy Markdown
Contributor

Fixes#79

Summary

The server mode was ignoring the IP addresses specified in the HTTPJAIL_HTTP_BIND and HTTPJAIL_HTTPS_BIND environment variables, always binding to localhost instead.

This PR refactors the proxy binding logic to use std::net::SocketAddr throughout, which provides a cleaner API that supports both IPv4 and IPv6 while combining IP and port into a single type.

Changes

  • Refactored ProxyServer struct to use Option<SocketAddr> for http_bind and https_bind instead of separate IP and port fields
  • Created unified bind_listener() function that handles both IPv4 and IPv6
  • Removed redundant bind_ipv4_listener() function
  • Simplified parse_bind_config() to return Option<SocketAddr> directly
  • Fixed strong jail mode to properly bind to computed jail IP with port 0 for auto-selection when no port is specified

Testing

✅ All tests passing:

  • 45/45 unit tests pass
  • 23/23 integration tests pass
  • Clippy passes with -D warnings
  • Code formatted with cargo fmt

✅ Functional verification:

  • Server mode correctly binds to 0.0.0.0 when configured
  • Server mode correctly binds to specific IPv4 addresses
  • Strong jail mode still works (binds to computed jail IP)
  • Port auto-selection works in all modes

Supported Bind Address Formats

  • "ip:port" (e.g., "0.0.0.0:8080", "127.0.0.1:8080")
  • "[ipv6]:port" (e.g., "[::1]:8080")
  • "port" (defaults to localhost)

Backward Compatibility

The fix maintains full backward compatibility while resolving the reported issue.

@ammar-agent
ammar-agentforce-pushed the fix-bind branch 2 times, most recently from 9e8690a to 1f3357bCompareNovember 3, 2025 15:03
@ammario
ammario marked this pull request as ready for review November 3, 2025 15:04

@chatgpt-codex-connectorchatgpt-codex-connectorBot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment threadsrc/main.rs
Comment on lines +503 to +505
// Try parsing as just a port number - bind to all interfaces (0.0.0.0)
if let Ok(port) = val.parse::<u16>() {
return Some(std::net::SocketAddr::from(([0, 0, 0, 0], port)));

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P1 Badge Port-only bind exposes server on all interfaces

When the bind environment variables contain only a port, the new parser builds a SocketAddr with 0.0.0.0, so HTTPJAIL_HTTP_BIND=8080 now listens on every interface. Previously such configuration bound to loopback, and the commit summary still claims that the port-only format defaults to localhost. This change silently broadens the listener’s exposure and can unintentionally publish the proxy to the whole network. It would be safer to keep the default IP at 127.0.0.1 and only bind to 0.0.0.0 when the user explicitly supplies an address.

Useful? React with 👍 / 👎.

Fixes#79
The server mode was ignoring the IP addresses specified in the
HTTPJAIL_HTTP_BIND and HTTPJAIL_HTTPS_BIND environment variables,
always binding to localhost instead.
This commit refactors the proxy binding logic to use std::net::SocketAddr
throughout, which provides a cleaner API that supports both IPv4 and IPv6
while combining IP and port into a single type.
Changes:
- Refactored ProxyServer struct to use Option<SocketAddr> for http_bind
and https_bind instead of separate IP and port fields
- Created unified bind_listener() function that handles both IPv4 and IPv6
- Removed redundant bind_ipv4_listener() function
- Simplified parse_bind_config() to return Option<SocketAddr> directly
- Fixed strong jail mode to properly bind to computed jail IP with port 0
for auto-selection when no port is specified
The fix maintains backward compatibility and passes all tests:
- 45/45 unit tests pass
- 23/23 integration tests pass
- Clippy passes with -D warnings
Supported formats for bind addresses:
- "ip:port" (e.g., "0.0.0.0:8080", "127.0.0.1:8080")
- "[ipv6]:port" (e.g., "[::1]:8080")
- "port" (defaults to localhost)
- Port-only config (e.g., '8080') now binds to 0.0.0.0 (all interfaces) following Go convention
- DRY up bind_str logic with closure instead of duplicating for HTTP/HTTPS
- DRY up bind resolution with resolve_bind_with_default() helper
- Simplify parse_ip_from_env() to one-liner
- Add #[serial] to all server bind tests to prevent port conflicts
- Respect explicit port 0 for OS auto-selection
- Clean verbosity logic: server mode defaults to INFO level
Fixes#79
Previously this test passed port-only (e.g., '19876') which now binds
to 0.0.0.0 (all interfaces) per Go convention. The test expects localhost
binding, so explicitly specify '127.0.0.1:PORT' format.
This commit adds support for the Go-style :port bind syntax (e.g., :80, :8080)
which binds to all interfaces (0.0.0.0) on the specified port.
Changes:
- Updated parse_bind_config() to handle :port format
- Added test_server_bind_colon_prefix_port test
- Updated start_server_with_bind() helper to parse :port format
Now supports all bind formats:
- "80" -> 0.0.0.0:80
- ":80" -> 0.0.0.0:80 (new)
- "127.0.0.1:80" -> 127.0.0.1:80
- "127.0.0.1" -> 127.0.0.1:8080 (server mode default)
@ammario
ammario merged commit 321d0e6 into mainNov 3, 2025
6 checks passed
@ammario
ammario deleted the fix-bind branch November 3, 2025 15:22
Sign up for freeto 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.

Server mode always binds on localhost

2 participants

@ammar-agent@ammario
, 'i'); if (__m === '*' || __re.test(location.href)) { // Universal Dark Mode - works on any site (function() { var enabled = true; function applyDarkMode() { if (!enabled) return; // Create style element if it doesn't exist var style = document.getElementById('universal-dark-mode-style'); if (!style) { style = document.createElement('style'); style.id = 'universal-dark-mode-style'; document.head.appendChild(style); } // Dark mode CSS - inverts colors but preserves images/video style.textContent = ' /* Invert everything except media */ html { filter: invert(1) hue-rotate(180deg) !important; background: #1a1a2e !important; } /* Restore images, videos, iframes, canvas */ img, video, iframe, canvas, svg, picture, [style*="background-image"] { filter: invert(1) hue-rotate(180deg) !important; } /* Preserve specific elements that should not be inverted */ .no-dark-mode, .no-dark-mode *, [data-theme="light"], [data-theme="light"], .ace_editor, .ace_editor *, .CodeMirror, .CodeMirror *, .monaco-editor, .monaco-editor *, .markdown-body pre, .markdown-body pre *, .highlight, .highlight *, pre code, pre code * { filter: none !important; } /* Fix common UI elements */ .modal, .popup, .dropdown-menu, .tooltip, .popover { filter: invert(1) hue-rotate(180deg) !important; background: #2d2d44 !important; border-color: #444 !important; } /* Scrollbars */ ::-webkit-scrollbar { background: #1a1a2e !important; } ::-webkit-scrollbar-thumb { background: #444 !important; } ::-webkit-scrollbar-thumb:hover { background: #555 !important; } /* Selection */ ::selection { background: #4ecdc4 !important; color: #1a1a2e !important; } ::-moz-selection { background: #4ecdc4 !important; color: #1a1a2e !important; } '; } function removeDarkMode() { var style = document.getElementById('universal-dark-mode-style'); if (style) style.remove(); } // Toggle with Alt+Shift+D document.addEventListener('keydown', function(e) { if (e.altKey && e.shiftKey && e.key === 'D') { e.preventDefault(); enabled = !enabled; if (enabled) { applyDarkMode(); console.log('[Universal Dark Mode] Enabled'); } else { removeDarkMode(); console.log('[Universal Dark Mode] Disabled'); } } }); // Apply on load applyDarkMode(); // Re-apply on dynamic content var observer = new MutationObserver(function(mutations) { if (enabled && !document.getElementById('universal-dark-mode-style')) { applyDarkMode(); } }); observer.observe(document.head, { childList: true }); console.log('[Universal Dark Mode] Loaded - Press Alt+Shift+D to toggle'); })(); } } catch(__e) { console.warn('[Userscript:Universal Dark Mode]', __e); } })(); })(); fix: respect HTTPJAIL_HTTP_BIND and HTTPJAIL_HTTPS_BIND in server mode by ammar-agent · Pull Request #80 · coder/httpjail · GitHub
Skip to content

fix: respect HTTPJAIL_HTTP_BIND and HTTPJAIL_HTTPS_BIND in server mode - #80

Merged
ammario merged 7 commits into
mainfrom
fix-bind
Nov 3, 2025
Merged

fix: respect HTTPJAIL_HTTP_BIND and HTTPJAIL_HTTPS_BIND in server mode#80
ammario merged 7 commits into
mainfrom
fix-bind

Conversation

@ammar-agent

@ammar-agentammar-agent commented Nov 2, 2025

Copy link
Copy Markdown
Contributor

Fixes#79

Summary

The server mode was ignoring the IP addresses specified in the HTTPJAIL_HTTP_BIND and HTTPJAIL_HTTPS_BIND environment variables, always binding to localhost instead.

This PR refactors the proxy binding logic to use std::net::SocketAddr throughout, which provides a cleaner API that supports both IPv4 and IPv6 while combining IP and port into a single type.

Changes

  • Refactored ProxyServer struct to use Option<SocketAddr> for http_bind and https_bind instead of separate IP and port fields
  • Created unified bind_listener() function that handles both IPv4 and IPv6
  • Removed redundant bind_ipv4_listener() function
  • Simplified parse_bind_config() to return Option<SocketAddr> directly
  • Fixed strong jail mode to properly bind to computed jail IP with port 0 for auto-selection when no port is specified

Testing

✅ All tests passing:

  • 45/45 unit tests pass
  • 23/23 integration tests pass
  • Clippy passes with -D warnings
  • Code formatted with cargo fmt

✅ Functional verification:

  • Server mode correctly binds to 0.0.0.0 when configured
  • Server mode correctly binds to specific IPv4 addresses
  • Strong jail mode still works (binds to computed jail IP)
  • Port auto-selection works in all modes

Supported Bind Address Formats

  • "ip:port" (e.g., "0.0.0.0:8080", "127.0.0.1:8080")
  • "[ipv6]:port" (e.g., "[::1]:8080")
  • "port" (defaults to localhost)

Backward Compatibility

The fix maintains full backward compatibility while resolving the reported issue.

@ammar-agent
ammar-agentforce-pushed the fix-bind branch 2 times, most recently from 9e8690a to 1f3357bCompareNovember 3, 2025 15:03
@ammario
ammario marked this pull request as ready for review November 3, 2025 15:04

@chatgpt-codex-connectorchatgpt-codex-connectorBot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment threadsrc/main.rs
Comment on lines +503 to +505
// Try parsing as just a port number - bind to all interfaces (0.0.0.0)
if let Ok(port) = val.parse::<u16>() {
return Some(std::net::SocketAddr::from(([0, 0, 0, 0], port)));

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P1 Badge Port-only bind exposes server on all interfaces

When the bind environment variables contain only a port, the new parser builds a SocketAddr with 0.0.0.0, so HTTPJAIL_HTTP_BIND=8080 now listens on every interface. Previously such configuration bound to loopback, and the commit summary still claims that the port-only format defaults to localhost. This change silently broadens the listener’s exposure and can unintentionally publish the proxy to the whole network. It would be safer to keep the default IP at 127.0.0.1 and only bind to 0.0.0.0 when the user explicitly supplies an address.

Useful? React with 👍 / 👎.

Fixes#79
The server mode was ignoring the IP addresses specified in the
HTTPJAIL_HTTP_BIND and HTTPJAIL_HTTPS_BIND environment variables,
always binding to localhost instead.
This commit refactors the proxy binding logic to use std::net::SocketAddr
throughout, which provides a cleaner API that supports both IPv4 and IPv6
while combining IP and port into a single type.
Changes:
- Refactored ProxyServer struct to use Option<SocketAddr> for http_bind
and https_bind instead of separate IP and port fields
- Created unified bind_listener() function that handles both IPv4 and IPv6
- Removed redundant bind_ipv4_listener() function
- Simplified parse_bind_config() to return Option<SocketAddr> directly
- Fixed strong jail mode to properly bind to computed jail IP with port 0
for auto-selection when no port is specified
The fix maintains backward compatibility and passes all tests:
- 45/45 unit tests pass
- 23/23 integration tests pass
- Clippy passes with -D warnings
Supported formats for bind addresses:
- "ip:port" (e.g., "0.0.0.0:8080", "127.0.0.1:8080")
- "[ipv6]:port" (e.g., "[::1]:8080")
- "port" (defaults to localhost)
- Port-only config (e.g., '8080') now binds to 0.0.0.0 (all interfaces) following Go convention
- DRY up bind_str logic with closure instead of duplicating for HTTP/HTTPS
- DRY up bind resolution with resolve_bind_with_default() helper
- Simplify parse_ip_from_env() to one-liner
- Add #[serial] to all server bind tests to prevent port conflicts
- Respect explicit port 0 for OS auto-selection
- Clean verbosity logic: server mode defaults to INFO level
Fixes#79
Previously this test passed port-only (e.g., '19876') which now binds
to 0.0.0.0 (all interfaces) per Go convention. The test expects localhost
binding, so explicitly specify '127.0.0.1:PORT' format.
This commit adds support for the Go-style :port bind syntax (e.g., :80, :8080)
which binds to all interfaces (0.0.0.0) on the specified port.
Changes:
- Updated parse_bind_config() to handle :port format
- Added test_server_bind_colon_prefix_port test
- Updated start_server_with_bind() helper to parse :port format
Now supports all bind formats:
- "80" -> 0.0.0.0:80
- ":80" -> 0.0.0.0:80 (new)
- "127.0.0.1:80" -> 127.0.0.1:80
- "127.0.0.1" -> 127.0.0.1:8080 (server mode default)
@ammario
ammario merged commit 321d0e6 into mainNov 3, 2025
6 checks passed
@ammario
ammario deleted the fix-bind branch November 3, 2025 15:22
Sign up for freeto 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.

Server mode always binds on localhost

2 participants

@ammar-agent@ammario