Skip to content

Speedtest routing issue #5435

Description

@kiroved

Environment

  • OS: Ubuntu 22.04.5 LTS
  • Hiddify Manager Config version: 12.3.3
  • Hiddify Panel version: 12.3.3
  • Installation type: standard release installer
  • Web server stack: Hiddify nginx / HAProxy
  • Domain mode: direct

There an issue related with the built-in Hiddify Speedtest page.

The Speedtest link generated by the panel looked like this:

https://<my-domain>/<secret-proxy-path>/speedtest/

But opening it in the browser returned:

{"message":"Not Found"}

At first it looked like the Speedtest service itself was not working, but the local service was actually running correctly.

I checked the nginx configuration and found that the Speedtest location existed:

sed -n '50,80p' /opt/hiddify-manager/nginx/parts/common.conf

Relevant part:

location /<secret-proxy-path>/speedtest/ {
  client_max_body_size 10000M;
  proxy_pass http://localhost:438/;
}

Then I checked whether Speedtest was listening locally:

ss -tulpen | grep ':438'

Output showed that nginx was listening on 127.0.0.1:438.

I also checked the local Speedtest endpoint directly:

curl -I http://127.0.0.1:438/
curl http://127.0.0.1:438/ | head

The result was successful:

HTTP/1.1 200 OK
Server: nginx
Content-Type: text/html

and the HTML contained:

<title>Hiddify Speed Test</title>

So the Speedtest service itself was working.

The problem was that the public URL:

https://<my-domain>/<secret-proxy-path>/speedtest/

was not routed to the nginx Speedtest location. Instead, the request was routed to hiddifypanel, which returned:

{"message":"Not Found"}

I checked HAProxy maps and found that the general panel path was routed to hiddifypanel:

grep -R "<secret-proxy-path>\|speedtest" -n /opt/hiddify-manager/haproxy /opt/hiddify-manager/nginx | head -150

Relevant result:

/opt/hiddify-manager/haproxy/maps/path:
/<secret-proxy-path>/ hiddifypanel

/opt/hiddify-manager/haproxy/maps/path_v10:
/<secret-proxy-path>/ hiddifypanel

There was no more specific HAProxy rule for:

/<secret-proxy-path>/speedtest/

Therefore, the generic rule for the panel path intercepted the Speedtest URL before it could reach the nginx Speedtest handler.

Workaround / manual fix

I added a more specific HAProxy rule for Speedtest before the generic panel rule.

I backed up the relevant files first:

mkdir -p /root/hiddify-haproxy-backup

cp -a /opt/hiddify-manager/haproxy/haproxy.cfg /root/hiddify-haproxy-backup/haproxy.cfg.$(date +%F_%H-%M-%S)
cp -a /opt/hiddify-manager/haproxy/maps/path /root/hiddify-haproxy-backup/path.$(date +%F_%H-%M-%S)
cp -a /opt/hiddify-manager/haproxy/maps/path_v10 /root/hiddify-haproxy-backup/path_v10.$(date +%F_%H-%M-%S)
cp -a /opt/hiddify-manager/haproxy/maps/path_h2 /root/hiddify-haproxy-backup/path_h2.$(date +%F_%H-%M-%S)

Then I added a more specific rule for Speedtest:

python3 - <<'PY'
from pathlib import Path

prefix = "/<secret-proxy-path>"
speed_line = f"{prefix}/speedtest/ nginx_dispatcher_http_h2"
general_line = f"{prefix}/ hiddifypanel"

for file in [
    Path("/opt/hiddify-manager/haproxy/maps/path"),
    Path("/opt/hiddify-manager/haproxy/maps/path_v10"),
    Path("/opt/hiddify-manager/haproxy/maps/path_h2"),
]:
    text = file.read_text()
    if speed_line not in text:
        text = text.replace(general_line, speed_line + "\n" + general_line)
        file.write_text(text)

cfg = Path("/opt/hiddify-manager/haproxy/haproxy.cfg")
text = cfg.read_text()
speed_rule = f"    use_backend nginx_dispatcher_http_h2 if {{ path_beg {prefix}/speedtest/ }}"
general_rule_start = f"    use_backend hiddifypanel if {{ path_beg {prefix}/"
if speed_rule not in text:
    lines = text.splitlines()
    out = []
    inserted = False
    for line in lines:
        if not inserted and line.startswith(general_rule_start):
            out.append(speed_rule)
            inserted = True
        out.append(line)
    cfg.write_text("\n".join(out) + "\n")
PY

Then I validated HAProxy config:

haproxy -c -f /opt/hiddify-manager/haproxy/haproxy.cfg

After that I restarted HAProxy and nginx:

systemctl restart hiddify-haproxy
systemctl restart hiddify-nginx

After this manual fix, Speedtest started working correctly through the public URL:

https://<my-domain>/<secret-proxy-path>/speedtest/

Summary

The built-in Speedtest service was running correctly on 127.0.0.1:438, but the public Speedtest URL was routed to hiddifypanel because HAProxy had only a generic rule for:

/<secret-proxy-path>/ → hiddifypanel

and no more specific rule for:

/<secret-proxy-path>/speedtest/ → nginx_dispatcher_http_h2

Could you please check whether the generated HAProxy maps should include a specific Speedtest route before the generic panel route?

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions