Something went wrong. Try again.
sloproxy
Something went wrong. Try again.
2.6 kB · 100 lines
Go
at main
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101package htmlsanitize
import ( "bytes" "encoding/json" "html" "io" "mime" "strings")
// String escapes text before it is returned to browser-facing management clients.func String(value string) string { return html.EscapeString(value)}
// Strings escapes each string in values while preserving order.func Strings(values []string) []string { out := make([]string, 0, len(values)) for _, value := range values { out = append(out, String(value)) } return out}
// JSONBody escapes all string values in a JSON document.func JSONBody(body []byte) ([]byte, bool) { trimmed := bytes.TrimSpace(body) if len(trimmed) == 0 { return body, false }
decoder := json.NewDecoder(bytes.NewReader(trimmed)) decoder.UseNumber() var value any if errDecode := decoder.Decode(&value); errDecode != nil { return body, false } var extra any if errExtra := decoder.Decode(&extra); errExtra != io.EOF { return body, false }
var buffer bytes.Buffer encoder := json.NewEncoder(&buffer) encoder.SetEscapeHTML(false) if errEncode := encoder.Encode(JSONValue(value)); errEncode != nil { return body, false } return bytes.TrimSuffix(buffer.Bytes(), []byte("\n")), true}
// JSONBodyIfLikely escapes JSON bodies when the content type or body shape indicates JSON.func JSONBodyIfLikely(body []byte, contentType string) ([]byte, bool) { if IsJSONContentType(contentType) || LooksLikeJSON(body) { return JSONBody(body) } return body, false}
// JSONValue recursively escapes string values in JSON-compatible data.func JSONValue(value any) any { switch typed := value.(type) { case string: return String(typed) case []any: out := make([]any, len(typed)) for index, item := range typed { out[index] = JSONValue(item) } return out case map[string]any: out := make(map[string]any, len(typed)) for key, item := range typed { out[key] = JSONValue(item) } return out default: return value }}
// IsJSONContentType reports whether contentType is application/json or a +json type.func IsJSONContentType(contentType string) bool { mediaType, _, errParse := mime.ParseMediaType(strings.TrimSpace(contentType)) if errParse != nil { mediaType = strings.TrimSpace(contentType) } mediaType = strings.ToLower(mediaType) return mediaType == "application/json" || strings.HasSuffix(mediaType, "+json")}
// LooksLikeJSON reports whether body starts with an object or array JSON marker.func LooksLikeJSON(body []byte) bool { trimmed := bytes.TrimSpace(body) if len(trimmed) == 0 { return false } return trimmed[0] == '{' || trimmed[0] == '['}