Source file src/pkg/net/http/header.go
     1	
     2	
     3	
     4	
     5	package http
     6	
     7	import (
     8		"io"
     9		"net/http/httptrace"
    10		"net/textproto"
    11		"sort"
    12		"strings"
    13		"sync"
    14		"time"
    15	)
    16	
    17	
    18	
    19	
    20	
    21	type Header map[string][]string
    22	
    23	
    24	
    25	
    26	
    27	func (h Header) Add(key, value string) {
    28		textproto.MIMEHeader(h).Add(key, value)
    29	}
    30	
    31	
    32	
    33	
    34	
    35	
    36	func (h Header) Set(key, value string) {
    37		textproto.MIMEHeader(h).Set(key, value)
    38	}
    39	
    40	
    41	
    42	
    43	
    44	
    45	
    46	func (h Header) Get(key string) string {
    47		return textproto.MIMEHeader(h).Get(key)
    48	}
    49	
    50	
    51	func (h Header) get(key string) string {
    52		if v := h[key]; len(v) > 0 {
    53			return v[0]
    54		}
    55		return ""
    56	}
    57	
    58	
    59	
    60	func (h Header) has(key string) bool {
    61		_, ok := h[key]
    62		return ok
    63	}
    64	
    65	
    66	
    67	
    68	func (h Header) Del(key string) {
    69		textproto.MIMEHeader(h).Del(key)
    70	}
    71	
    72	
    73	func (h Header) Write(w io.Writer) error {
    74		return h.write(w, nil)
    75	}
    76	
    77	func (h Header) write(w io.Writer, trace *httptrace.ClientTrace) error {
    78		return h.writeSubset(w, nil, trace)
    79	}
    80	
    81	
    82	func (h Header) Clone() Header {
    83		if h == nil {
    84			return nil
    85		}
    86	
    87		
    88		nv := 0
    89		for _, vv := range h {
    90			nv += len(vv)
    91		}
    92		sv := make([]string, nv) 
    93		h2 := make(Header, len(h))
    94		for k, vv := range h {
    95			n := copy(sv, vv)
    96			h2[k] = sv[:n:n]
    97			sv = sv[n:]
    98		}
    99		return h2
   100	}
   101	
   102	var timeFormats = []string{
   103		TimeFormat,
   104		time.RFC850,
   105		time.ANSIC,
   106	}
   107	
   108	
   109	
   110	
   111	func ParseTime(text string) (t time.Time, err error) {
   112		for _, layout := range timeFormats {
   113			t, err = time.Parse(layout, text)
   114			if err == nil {
   115				return
   116			}
   117		}
   118		return
   119	}
   120	
   121	var headerNewlineToSpace = strings.NewReplacer("\n", " ", "\r", " ")
   122	
   123	
   124	type stringWriter struct {
   125		w io.Writer
   126	}
   127	
   128	func (w stringWriter) WriteString(s string) (n int, err error) {
   129		return w.w.Write([]byte(s))
   130	}
   131	
   132	type keyValues struct {
   133		key    string
   134		values []string
   135	}
   136	
   137	
   138	
   139	
   140	type headerSorter struct {
   141		kvs []keyValues
   142	}
   143	
   144	func (s *headerSorter) Len() int           { return len(s.kvs) }
   145	func (s *headerSorter) Swap(i, j int)      { s.kvs[i], s.kvs[j] = s.kvs[j], s.kvs[i] }
   146	func (s *headerSorter) Less(i, j int) bool { return s.kvs[i].key < s.kvs[j].key }
   147	
   148	var headerSorterPool = sync.Pool{
   149		New: func() interface{} { return new(headerSorter) },
   150	}
   151	
   152	
   153	
   154	
   155	func (h Header) sortedKeyValues(exclude map[string]bool) (kvs []keyValues, hs *headerSorter) {
   156		hs = headerSorterPool.Get().(*headerSorter)
   157		if cap(hs.kvs) < len(h) {
   158			hs.kvs = make([]keyValues, 0, len(h))
   159		}
   160		kvs = hs.kvs[:0]
   161		for k, vv := range h {
   162			if !exclude[k] {
   163				kvs = append(kvs, keyValues{k, vv})
   164			}
   165		}
   166		hs.kvs = kvs
   167		sort.Sort(hs)
   168		return kvs, hs
   169	}
   170	
   171	
   172	
   173	func (h Header) WriteSubset(w io.Writer, exclude map[string]bool) error {
   174		return h.writeSubset(w, exclude, nil)
   175	}
   176	
   177	func (h Header) writeSubset(w io.Writer, exclude map[string]bool, trace *httptrace.ClientTrace) error {
   178		ws, ok := w.(io.StringWriter)
   179		if !ok {
   180			ws = stringWriter{w}
   181		}
   182		kvs, sorter := h.sortedKeyValues(exclude)
   183		var formattedVals []string
   184		for _, kv := range kvs {
   185			for _, v := range kv.values {
   186				v = headerNewlineToSpace.Replace(v)
   187				v = textproto.TrimString(v)
   188				for _, s := range []string{kv.key, ": ", v, "\r\n"} {
   189					if _, err := ws.WriteString(s); err != nil {
   190						headerSorterPool.Put(sorter)
   191						return err
   192					}
   193				}
   194				if trace != nil && trace.WroteHeaderField != nil {
   195					formattedVals = append(formattedVals, v)
   196				}
   197			}
   198			if trace != nil && trace.WroteHeaderField != nil {
   199				trace.WroteHeaderField(kv.key, formattedVals)
   200				formattedVals = nil
   201			}
   202		}
   203		headerSorterPool.Put(sorter)
   204		return nil
   205	}
   206	
   207	
   208	
   209	
   210	
   211	
   212	
   213	
   214	func CanonicalHeaderKey(s string) string { return textproto.CanonicalMIMEHeaderKey(s) }
   215	
   216	
   217	
   218	
   219	
   220	func hasToken(v, token string) bool {
   221		if len(token) > len(v) || token == "" {
   222			return false
   223		}
   224		if v == token {
   225			return true
   226		}
   227		for sp := 0; sp <= len(v)-len(token); sp++ {
   228			
   229			
   230			
   231			
   232			
   233			
   234			if b := v[sp]; b != token[0] && b|0x20 != token[0] {
   235				continue
   236			}
   237			
   238			if sp > 0 && !isTokenBoundary(v[sp-1]) {
   239				continue
   240			}
   241			
   242			if endPos := sp + len(token); endPos != len(v) && !isTokenBoundary(v[endPos]) {
   243				continue
   244			}
   245			if strings.EqualFold(v[sp:sp+len(token)], token) {
   246				return true
   247			}
   248		}
   249		return false
   250	}
   251	
   252	func isTokenBoundary(b byte) bool {
   253		return b == ' ' || b == ',' || b == '\t'
   254	}
   255	
View as plain text