diff --git a/internal/aghhttp/aghhttp.go b/internal/aghhttp/aghhttp.go index 57a1c868..64e31075 100644 --- a/internal/aghhttp/aghhttp.go +++ b/internal/aghhttp/aghhttp.go @@ -6,6 +6,7 @@ import ( "io" "net/http" + "github.com/AdguardTeam/AdGuardHome/internal/version" "github.com/AdguardTeam/golibs/log" ) @@ -28,3 +29,9 @@ func Error(r *http.Request, w http.ResponseWriter, code int, format string, args log.Error("%s %s: %s", r.Method, r.URL, text) http.Error(w, text, code) } + +// UserAgent returns the ID of the service as a User-Agent string. It can also +// be used as the value of the Server HTTP header. +func UserAgent() (ua string) { + return fmt.Sprintf("AdGuardDNS/%s", version.Version()) +} diff --git a/internal/aghhttp/header.go b/internal/aghhttp/header.go new file mode 100644 index 00000000..87a18396 --- /dev/null +++ b/internal/aghhttp/header.go @@ -0,0 +1,21 @@ +package aghhttp + +// HTTP Headers + +// HTTP header name constants. +// +// TODO(a.garipov): Remove unused. +const ( + HdrNameAcceptEncoding = "Accept-Encoding" + HdrNameAccessControlAllowOrigin = "Access-Control-Allow-Origin" + HdrNameContentType = "Content-Type" + HdrNameContentEncoding = "Content-Encoding" + HdrNameServer = "Server" + HdrNameTrailer = "Trailer" + HdrNameUserAgent = "User-Agent" +) + +// HTTP header value constants. +const ( + HdrValApplicationJSON = "application/json" +) diff --git a/internal/next/websvc/json.go b/internal/next/websvc/json.go index 15b2f7e2..4b35c694 100644 --- a/internal/next/websvc/json.go +++ b/internal/next/websvc/json.go @@ -8,11 +8,15 @@ import ( "strconv" "time" + "github.com/AdguardTeam/AdGuardHome/internal/aghhttp" "github.com/AdguardTeam/golibs/log" ) // JSON Utilities +// nsecPerMsec is the number of nanoseconds in a millisecond. +const nsecPerMsec = float64(time.Millisecond / time.Nanosecond) + // JSONDuration is a time.Duration that can be decoded from JSON and encoded // into JSON according to our API conventions. type JSONDuration time.Duration @@ -55,9 +59,6 @@ type JSONTime time.Time // type check var _ json.Marshaler = JSONTime{} -// nsecPerMsec is the number of nanoseconds in a millisecond. -const nsecPerMsec = float64(time.Millisecond / time.Nanosecond) - // MarshalJSON implements the json.Marshaler interface for JSONTime. err is // always nil. func (t JSONTime) MarshalJSON() (b []byte, err error) { @@ -88,7 +89,12 @@ func (t *JSONTime) UnmarshalJSON(b []byte) (err error) { // writeJSONResponse encodes v into w and logs any errors it encounters. r is // used to get additional information from the request. -func writeJSONResponse(w io.Writer, r *http.Request, v any) { +func writeJSONResponse(w http.ResponseWriter, r *http.Request, v any) { + // TODO(a.garipov): Put some of these to a middleware. + h := w.Header() + h.Set(aghhttp.HdrNameContentType, aghhttp.HdrValApplicationJSON) + h.Set(aghhttp.HdrNameServer, aghhttp.UserAgent()) + err := json.NewEncoder(w).Encode(v) if err != nil { log.Error("websvc: writing resp to %s %s: %s", r.Method, r.URL.Path, err) diff --git a/internal/version/version.go b/internal/version/version.go index 2091d859..ca78efff 100644 --- a/internal/version/version.go +++ b/internal/version/version.go @@ -63,14 +63,6 @@ func Version() (v string) { return version } -// Constants defining the format of module information string. -const ( - modInfoAtSep = "@" - modInfoDevSep = " " - modInfoSumLeft = " (sum: " - modInfoSumRight = ")" -) - // fmtModule returns formatted information about module. The result looks like: // // github.com/Username/module@v1.2.3 (sum: someHASHSUM=) @@ -87,14 +79,16 @@ func fmtModule(m *debug.Module) (formatted string) { stringutil.WriteToBuilder(b, m.Path) if ver := m.Version; ver != "" { - sep := modInfoAtSep + sep := "@" if ver == "(devel)" { - sep = modInfoDevSep + sep = " " } + stringutil.WriteToBuilder(b, sep, ver) } + if sum := m.Sum; sum != "" { - stringutil.WriteToBuilder(b, modInfoSumLeft, sum, modInfoSumRight) + stringutil.WriteToBuilder(b, "(sum: ", sum, ")") } return b.String()