Skip to content

Commit afd5951

Browse files
committed
fix: switch port when falling back between HTTP/HTTPS protocols
- When falling back from HTTPS to HTTP on port 443, now switches to port 80 - When falling back from HTTP to HTTPS on port 80, now switches to port 443 - Prevents 'plain HTTP request sent to HTTPS port' errors during fallback - Added test cases for determineMostLikelySchemeOrder and port fallback logic
1 parent f7712f7 commit afd5951

File tree

2 files changed

+126
-0
lines changed

2 files changed

+126
-0
lines changed

runner/ports_optimization_test.go

Lines changed: 115 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,115 @@
1+
package runner
2+
3+
import (
4+
"testing"
5+
6+
"github.com/projectdiscovery/httpx/common/httpx"
7+
"github.com/stretchr/testify/require"
8+
)
9+
10+
func TestDetermineMostLikelySchemeOrder(t *testing.T) {
11+
tests := []struct {
12+
name string
13+
input string
14+
expected string
15+
}{
16+
{
17+
name: "port 80 should return HTTP",
18+
input: "example.com:80",
19+
expected: httpx.HTTP,
20+
},
21+
{
22+
name: "port 8080 should return HTTP",
23+
input: "example.com:8080",
24+
expected: httpx.HTTP,
25+
},
26+
{
27+
name: "port 443 should return HTTPS",
28+
input: "example.com:443",
29+
expected: httpx.HTTPS,
30+
},
31+
{
32+
name: "port 8443 should return HTTP (port > 1024)",
33+
input: "example.com:8443",
34+
expected: httpx.HTTP,
35+
},
36+
{
37+
name: "no port should return HTTPS",
38+
input: "example.com",
39+
expected: httpx.HTTPS,
40+
},
41+
{
42+
name: "port 443 with IP should return HTTPS",
43+
input: "1.2.3.4:443",
44+
expected: httpx.HTTPS,
45+
},
46+
{
47+
name: "port 80 with IP should return HTTP",
48+
input: "1.2.3.4:80",
49+
expected: httpx.HTTP,
50+
},
51+
}
52+
53+
for _, tc := range tests {
54+
t.Run(tc.name, func(t *testing.T) {
55+
result := determineMostLikelySchemeOrder(tc.input)
56+
require.Equal(t, tc.expected, result, "unexpected scheme for input %s", tc.input)
57+
})
58+
}
59+
}
60+
61+
func TestSwitchPortForFallback(t *testing.T) {
62+
// Test that when switching from HTTPS to HTTP on port 443, port should become 80
63+
// And when switching from HTTP to HTTPS on port 80, port should become 443
64+
tests := []struct {
65+
name string
66+
inputPort string
67+
inputProtocol string
68+
expectedNewPort string
69+
}{
70+
{
71+
name: "HTTPS:443 fallback should switch to port 80",
72+
inputPort: "443",
73+
inputProtocol: httpx.HTTPS,
74+
expectedNewPort: "80",
75+
},
76+
{
77+
name: "HTTP:80 fallback should switch to port 443",
78+
inputPort: "80",
79+
inputProtocol: httpx.HTTP,
80+
expectedNewPort: "443",
81+
},
82+
{
83+
name: "HTTPS:8443 fallback should keep port 8443",
84+
inputPort: "8443",
85+
inputProtocol: httpx.HTTPS,
86+
expectedNewPort: "8443", // non-default port stays the same
87+
},
88+
{
89+
name: "HTTP:8080 fallback should keep port 8080",
90+
inputPort: "8080",
91+
inputProtocol: httpx.HTTP,
92+
expectedNewPort: "8080", // non-default port stays the same
93+
},
94+
}
95+
96+
for _, tc := range tests {
97+
t.Run(tc.name, func(t *testing.T) {
98+
newPort := getPortForFallback(tc.inputPort, tc.inputProtocol)
99+
require.Equal(t, tc.expectedNewPort, newPort, "unexpected port for fallback")
100+
})
101+
}
102+
}
103+
104+
// getPortForFallback returns the port to use when falling back to the other protocol
105+
// This is the logic used in runner.go analyze function
106+
func getPortForFallback(currentPort, currentProtocol string) string {
107+
if currentProtocol == httpx.HTTPS && currentPort == "443" {
108+
return "80"
109+
}
110+
if currentProtocol == httpx.HTTP && currentPort == "80" {
111+
return "443"
112+
}
113+
return currentPort
114+
}
115+

runner/runner.go

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1754,10 +1754,21 @@ retry:
17541754
errString = strings.TrimSpace(splitErr[len(splitErr)-1])
17551755

17561756
if !retried && origProtocol == httpx.HTTPorHTTPS {
1757+
// switch protocol and adjust port accordingly
17571758
if protocol == httpx.HTTPS {
17581759
protocol = httpx.HTTP
1760+
// if port is 443 (default HTTPS), switch to 80 (default HTTP)
1761+
if URL.Port() == "443" {
1762+
URL.UpdatePort("80")
1763+
target.Host = URL.Hostname() + ":80"
1764+
}
17591765
} else {
17601766
protocol = httpx.HTTPS
1767+
// if port is 80 (default HTTP), switch to 443 (default HTTPS)
1768+
if URL.Port() == "80" {
1769+
URL.UpdatePort("443")
1770+
target.Host = URL.Hostname() + ":443"
1771+
}
17611772
}
17621773
retried = true
17631774
goto retry

0 commit comments

Comments
 (0)