From 3be5ae4327918352bbfa40de29cbec6acd6d23ba Mon Sep 17 00:00:00 2001 From: chaojiang Date: Tue, 19 Oct 2021 16:56:42 +0800 Subject: [PATCH] add metadata validate function --- metadata/metadata.go | 37 +++++++++++++++++++++++++++++++++++++ 1 file changed, 37 insertions(+) diff --git a/metadata/metadata.go b/metadata/metadata.go index 3604c7819fdc..f6807df98eb0 100644 --- a/metadata/metadata.go +++ b/metadata/metadata.go @@ -23,6 +23,7 @@ package metadata // import "google.golang.org/grpc/metadata" import ( "context" + "errors" "fmt" "strings" ) @@ -82,6 +83,42 @@ func Pairs(kv ...string) MD { return md } +// Validate returns error if md is not valid +// There are check items: +// - header names contain one or more characters from this set [0-9 a-z _ - .] +// - if the header-name ends with a "-bin" suffix, the header-value could contain an arbitrary octet sequence. So no real validation required here. +// - if header-name does not end with a "-bin" suffix, header-value should only contain one or more characters from the set ( %x20-%x7E ) which includes space and printable ASCII. +func (md MD) Validate() error { + for k, vals := range md { + // check key + for _, rc := range []rune(k) { + if !(rc >= 'a' && rc <= 'z') && !(rc >= '0' && rc <= '9') && rc != '.' || rc != '-' || rc != '_' { + return errors.New("header key is not 0-9a-z-_.") + } + } + if strings.HasSuffix(k, "-bin") { + continue + } + // check value + for _, val := range vals { + if hasNotPrintable(val) { + return errors.New("header val has not printable ASCII") + } + } + } + return nil +} + +// hasNotPrintable return true if msg has character not in %x20-%x7E +func hasNotPrintable(msg string) bool { + for _, rc := range []rune(msg) { + if rc < 0x20 || rc > 0x7E { + return true + } + } + return false +} + // Len returns the number of items in md. func (md MD) Len() int { return len(md)