123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263 |
- 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)
- }
|