/*
 *
 * Copyright 2020 gRPC authors.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *
 */

// Package metadata contains functions to set and get metadata from addresses. // // This package is experimental.
package metadata import ( ) type mdKeyType string const mdKey = mdKeyType("grpc.internal.address.metadata") type mdValue metadata.MD func ( mdValue) ( interface{}) bool { , := .(mdValue) if ! { return false } if len() != len() { return false } for , := range { := [] if len() != len() { return false } for , := range { if [] != { return false } } } return true } // Get returns the metadata of addr. func ( resolver.Address) metadata.MD { := .Attributes if == nil { return nil } , := .Value(mdKey).(mdValue) return metadata.MD() } // Set sets (overrides) the metadata in addr. // // When a SubConn is created with this address, the RPCs sent on it will all // have this metadata. func ( resolver.Address, metadata.MD) resolver.Address { .Attributes = .Attributes.WithValue(mdKey, mdValue()) return } // Validate returns an error if the input md contains invalid keys or values. // // If the header is not a pseudo-header, the following items are checked: // - header names must contain one or more characters from this set [0-9 a-z _ - .]. // - if the header-name ends with a "-bin" suffix, no validation of the header value is performed. // - otherwise, the header value must contain one or more characters from the set [%x20-%x7E]. func ( metadata.MD) error { for , := range { // pseudo-header will be ignored if [0] == ':' { continue } // check key, for i that saving a conversion if not using for range for := 0; < len(); ++ { := [] if !( >= 'a' && <= 'z') && !( >= '0' && <= '9') && != '.' && != '-' && != '_' { return fmt.Errorf("header key %q contains illegal characters not in [0-9a-z-_.]", ) } } if strings.HasSuffix(, "-bin") { continue } // check value for , := range { if hasNotPrintable() { return fmt.Errorf("header key %q contains value with non-printable ASCII characters", ) } } } return nil } // hasNotPrintable return true if msg contains any characters which are not in %x20-%x7E func ( string) bool { // for i that saving a conversion if not using for range for := 0; < len(); ++ { if [] < 0x20 || [] > 0x7E { return true } } return false }