Files
telemt-api/internal/proxy/mihomo.go
T
Denozordec 2d7b06260e
Publish telemt-api gateway Docker image / test (push) Successful in 34s
Publish telemt-api gateway Docker image / build-and-push (push) Successful in 2m55s
Implement Mihomo external-controller support in configuration and gateway
- Added optional Mihomo configuration fields in `config.compose.yaml` and `config.example.yaml` for enhanced integration with the Mihomo external-controller.
- Updated the `Gateway` to handle Mihomo API requests, including proxying and error handling for Mihomo-specific endpoints.
- Enhanced the documentation in `GATEWAY_RUN.md` to guide users on configuring Mihomo integration.
- Introduced new utility functions in the web client for interacting with Mihomo API endpoints, improving the overall user experience.
- Updated the sidebar in the Svelte components to include a link to the Mihomo section, enhancing navigation.
2026-03-31 00:32:19 +07:00

74 lines
1.9 KiB
Go

package proxy
import (
"encoding/json"
"net/http"
"net/http/httputil"
"net/url"
"strings"
)
// NewMihomoForward proxies /api/{alias}/mihomo/... to Mihomo external-controller (REST + WebSocket).
func NewMihomoForward(
target *url.URL,
stripPrefix string,
auth string,
rt http.RoundTripper,
errHandler func(http.ResponseWriter, *http.Request, error),
) http.Handler {
if errHandler == nil {
errHandler = defaultForwardErrorHandler
}
if rt == nil {
rt = http.DefaultTransport
}
rp := &httputil.ReverseProxy{
Director: func(req *http.Request) {
NormalizeRequestURLPath(req)
p := req.URL.Path
if !strings.HasPrefix(p, stripPrefix) {
return
}
rest := strings.TrimPrefix(p, stripPrefix)
rest = strings.TrimPrefix(rest, "/")
q := req.URL.RawQuery
dest := JoinPathPrefix(target, "/", rest)
req.URL.Scheme = dest.Scheme
req.URL.Host = dest.Host
req.URL.Path = dest.Path
req.URL.RawQuery = q
req.Host = dest.Host
req.Header.Del("Authorization")
if auth != "" {
req.Header.Set("Authorization", auth)
}
},
Transport: rt,
ErrorHandler: func(w http.ResponseWriter, r *http.Request, err error) {
errHandler(w, r, err)
},
}
return rp
}
// MihomoMetaJSON returns a JSON body for GET .../mihomo/meta (display URL without credentials).
func MihomoMetaJSON(target *url.URL) []byte {
display := strings.TrimSuffix(target.String(), "/")
b, _ := json.Marshal(map[string]any{
"ok": true,
"controller_base": display,
})
return b
}
// MihomoJSONError writes a JSON error for Mihomo routes when proxy is not configured.
func MihomoJSONError(w http.ResponseWriter, code, msg string) {
w.Header().Set("Content-Type", "application/json; charset=utf-8")
w.WriteHeader(http.StatusNotFound)
_ = json.NewEncoder(w).Encode(map[string]any{
"ok": false,
"error": map[string]string{"code": code, "message": msg},
})
}