Clash.Meta/hub/route/doh.go
2024-07-23 00:01:41 +08:00

67 lines
1.6 KiB
Go

package route
import (
"context"
"encoding/base64"
"io"
"net/http"
"github.com/metacubex/mihomo/component/resolver"
"github.com/go-chi/render"
)
func dohRouter() http.Handler {
return http.HandlerFunc(dohHandler)
}
func dohHandler(w http.ResponseWriter, r *http.Request) {
if resolver.DefaultResolver == nil {
render.Status(r, http.StatusInternalServerError)
render.JSON(w, r, newError("DNS section is disabled"))
return
}
if r.Header.Get("Accept") != "application/dns-message" {
render.Status(r, http.StatusInternalServerError)
render.JSON(w, r, newError("invalid accept header"))
return
}
var dnsData []byte
var err error
switch r.Method {
case "GET":
dnsData, err = base64.RawURLEncoding.DecodeString(r.URL.Query().Get("dns"))
case "POST":
if r.Header.Get("Content-Type") != "application/dns-message" {
render.Status(r, http.StatusInternalServerError)
render.JSON(w, r, newError("invalid content-type"))
return
}
dnsData, err = io.ReadAll(r.Body)
_ = r.Body.Close()
default:
render.Status(r, http.StatusMethodNotAllowed)
render.JSON(w, r, newError("method not allowed"))
return
}
if err != nil {
render.Status(r, http.StatusInternalServerError)
render.JSON(w, r, newError(err.Error()))
return
}
ctx, cancel := context.WithTimeout(context.Background(), resolver.DefaultDNSTimeout)
defer cancel()
dnsData, err = resolver.RelayDnsPacket(ctx, dnsData, dnsData)
if err != nil {
render.Status(r, http.StatusInternalServerError)
render.JSON(w, r, newError(err.Error()))
return
}
render.Status(r, http.StatusOK)
render.Data(w, r, dnsData)
}