mirror of
https://gitclone.com/github.com/MetaCubeX/Clash.Meta
synced 2024-11-15 13:41:23 +08:00
64 lines
1.6 KiB
Go
64 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.PlainText(w, r, "DNS section is disabled")
|
|
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.PlainText(w, r, "invalid content-type")
|
|
return
|
|
}
|
|
reader := io.LimitReader(r.Body, 65535) // according to rfc8484, the maximum size of the DNS message is 65535 bytes
|
|
dnsData, err = io.ReadAll(reader)
|
|
_ = r.Body.Close()
|
|
default:
|
|
render.Status(r, http.StatusMethodNotAllowed)
|
|
render.PlainText(w, r, "method not allowed")
|
|
return
|
|
}
|
|
if err != nil {
|
|
render.Status(r, http.StatusInternalServerError)
|
|
render.PlainText(w, r, 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.PlainText(w, r, err.Error())
|
|
return
|
|
}
|
|
|
|
w.Header().Set("Content-Type", "application/dns-message")
|
|
w.WriteHeader(http.StatusOK)
|
|
_, _ = w.Write(dnsData)
|
|
}
|