Motivation: According to the spec: All pseudo-header fields MUST appear in the header block before regular header fields. Any request or response that contains a pseudo-header field that appears in a header block after a regular header field MUST be treated as malformed (Section 8.1.2.6). Pseudo-header fields are only valid in the context in which they are defined. Pseudo-header fields defined for requests MUST NOT appear in responses; pseudo-header fields defined for responses MUST NOT appear in requests. Pseudo-header fields MUST NOT appear in trailers. Endpoints MUST treat a request or response that contains undefined or invalid pseudo-header fields as malformed (Section 8.1.2.6). Clients MUST NOT accept a malformed response. Note that these requirements are intended to protect against several types of common attacks against HTTP; they are deliberately strict because being permissive can expose implementations to these vulnerabilities. Modifications: - Introduce validation in HPackDecoder Result: - Requests with unknown pseudo-field headers are rejected - Requests with containing response specific pseudo-headers are rejected - Requests where pseudo-header appear after regular header are rejected - h2spec 8.1.2.1 pass
105 lines
2.9 KiB
Java
105 lines
2.9 KiB
Java
/*
|
|
* Copyright 2017 The Netty Project
|
|
*
|
|
* The Netty Project licenses this file to you 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 io.netty.handler.codec.http2;
|
|
|
|
import io.netty.handler.codec.CharSequenceValueConverter;
|
|
import io.netty.handler.codec.DefaultHeaders;
|
|
|
|
import static io.netty.util.AsciiString.CASE_INSENSITIVE_HASHER;
|
|
import static io.netty.util.AsciiString.CASE_SENSITIVE_HASHER;
|
|
|
|
/**
|
|
* Http2Headers implementation that preserves headers insertion order.
|
|
*/
|
|
public class InOrderHttp2Headers
|
|
extends DefaultHeaders<CharSequence, CharSequence, Http2Headers> implements Http2Headers {
|
|
|
|
InOrderHttp2Headers() {
|
|
super(CharSequenceValueConverter.INSTANCE);
|
|
}
|
|
|
|
@Override
|
|
public boolean equals(Object o) {
|
|
return o instanceof Http2Headers && equals((Http2Headers) o, CASE_SENSITIVE_HASHER);
|
|
}
|
|
|
|
@Override
|
|
public int hashCode() {
|
|
return hashCode(CASE_SENSITIVE_HASHER);
|
|
}
|
|
|
|
@Override
|
|
public Http2Headers method(CharSequence value) {
|
|
set(PseudoHeaderName.METHOD.value(), value);
|
|
return this;
|
|
}
|
|
|
|
@Override
|
|
public Http2Headers scheme(CharSequence value) {
|
|
set(PseudoHeaderName.SCHEME.value(), value);
|
|
return this;
|
|
}
|
|
|
|
@Override
|
|
public Http2Headers authority(CharSequence value) {
|
|
set(PseudoHeaderName.AUTHORITY.value(), value);
|
|
return this;
|
|
}
|
|
|
|
@Override
|
|
public Http2Headers path(CharSequence value) {
|
|
set(PseudoHeaderName.PATH.value(), value);
|
|
return this;
|
|
}
|
|
|
|
@Override
|
|
public Http2Headers status(CharSequence value) {
|
|
set(PseudoHeaderName.STATUS.value(), value);
|
|
return this;
|
|
}
|
|
|
|
@Override
|
|
public CharSequence method() {
|
|
return get(PseudoHeaderName.METHOD.value());
|
|
}
|
|
|
|
@Override
|
|
public CharSequence scheme() {
|
|
return get(PseudoHeaderName.SCHEME.value());
|
|
}
|
|
|
|
@Override
|
|
public CharSequence authority() {
|
|
return get(PseudoHeaderName.AUTHORITY.value());
|
|
}
|
|
|
|
@Override
|
|
public CharSequence path() {
|
|
return get(PseudoHeaderName.PATH.value());
|
|
}
|
|
|
|
@Override
|
|
public CharSequence status() {
|
|
return get(PseudoHeaderName.STATUS.value());
|
|
}
|
|
|
|
@Override
|
|
public boolean contains(CharSequence name, CharSequence value, boolean caseInsensitive) {
|
|
return contains(name, value, caseInsensitive ? CASE_INSENSITIVE_HASHER : CASE_SENSITIVE_HASHER);
|
|
}
|
|
}
|