|
@@ -46,6 +46,7 @@ import (
|
|
|
"sync"
|
|
"sync"
|
|
|
"time"
|
|
"time"
|
|
|
|
|
|
|
|
|
|
+ "golang.org/x/net/http/httpguts"
|
|
|
"golang.org/x/net/http2/hpack"
|
|
"golang.org/x/net/http2/hpack"
|
|
|
)
|
|
)
|
|
|
|
|
|
|
@@ -1817,7 +1818,7 @@ func (st *stream) processTrailerHeaders(f *MetaHeadersFrame) error {
|
|
|
if st.trailer != nil {
|
|
if st.trailer != nil {
|
|
|
for _, hf := range f.RegularFields() {
|
|
for _, hf := range f.RegularFields() {
|
|
|
key := sc.canonicalHeader(hf.Name)
|
|
key := sc.canonicalHeader(hf.Name)
|
|
|
- if !ValidTrailerHeader(key) {
|
|
|
|
|
|
|
+ if !httpguts.ValidTrailerHeader(key) {
|
|
|
// TODO: send more details to the peer somehow. But http2 has
|
|
// TODO: send more details to the peer somehow. But http2 has
|
|
|
// no way to send debug data at a stream level. Discuss with
|
|
// no way to send debug data at a stream level. Discuss with
|
|
|
// HTTP folk.
|
|
// HTTP folk.
|
|
@@ -2284,7 +2285,7 @@ func (rws *responseWriterState) hasTrailers() bool { return len(rws.trailers) !=
|
|
|
// written in the trailers at the end of the response.
|
|
// written in the trailers at the end of the response.
|
|
|
func (rws *responseWriterState) declareTrailer(k string) {
|
|
func (rws *responseWriterState) declareTrailer(k string) {
|
|
|
k = http.CanonicalHeaderKey(k)
|
|
k = http.CanonicalHeaderKey(k)
|
|
|
- if !ValidTrailerHeader(k) {
|
|
|
|
|
|
|
+ if !httpguts.ValidTrailerHeader(k) {
|
|
|
// Forbidden by RFC 7230, section 4.1.2.
|
|
// Forbidden by RFC 7230, section 4.1.2.
|
|
|
rws.conn.logf("ignoring invalid trailer %q", k)
|
|
rws.conn.logf("ignoring invalid trailer %q", k)
|
|
|
return
|
|
return
|
|
@@ -2838,41 +2839,6 @@ func new400Handler(err error) http.HandlerFunc {
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
-// ValidTrailerHeader reports whether name is a valid header field name to appear
|
|
|
|
|
-// in trailers.
|
|
|
|
|
-// See: http://tools.ietf.org/html/rfc7230#section-4.1.2
|
|
|
|
|
-func ValidTrailerHeader(name string) bool {
|
|
|
|
|
- name = http.CanonicalHeaderKey(name)
|
|
|
|
|
- if strings.HasPrefix(name, "If-") || badTrailer[name] {
|
|
|
|
|
- return false
|
|
|
|
|
- }
|
|
|
|
|
- return true
|
|
|
|
|
-}
|
|
|
|
|
-
|
|
|
|
|
-var badTrailer = map[string]bool{
|
|
|
|
|
- "Authorization": true,
|
|
|
|
|
- "Cache-Control": true,
|
|
|
|
|
- "Connection": true,
|
|
|
|
|
- "Content-Encoding": true,
|
|
|
|
|
- "Content-Length": true,
|
|
|
|
|
- "Content-Range": true,
|
|
|
|
|
- "Content-Type": true,
|
|
|
|
|
- "Expect": true,
|
|
|
|
|
- "Host": true,
|
|
|
|
|
- "Keep-Alive": true,
|
|
|
|
|
- "Max-Forwards": true,
|
|
|
|
|
- "Pragma": true,
|
|
|
|
|
- "Proxy-Authenticate": true,
|
|
|
|
|
- "Proxy-Authorization": true,
|
|
|
|
|
- "Proxy-Connection": true,
|
|
|
|
|
- "Range": true,
|
|
|
|
|
- "Realm": true,
|
|
|
|
|
- "Te": true,
|
|
|
|
|
- "Trailer": true,
|
|
|
|
|
- "Transfer-Encoding": true,
|
|
|
|
|
- "Www-Authenticate": true,
|
|
|
|
|
-}
|
|
|
|
|
-
|
|
|
|
|
// h1ServerKeepAlivesDisabled reports whether hs has its keep-alives
|
|
// h1ServerKeepAlivesDisabled reports whether hs has its keep-alives
|
|
|
// disabled. See comments on h1ServerShutdownChan above for why
|
|
// disabled. See comments on h1ServerShutdownChan above for why
|
|
|
// the code is written this way.
|
|
// the code is written this way.
|