Skip to content

Commit

Permalink
Introduce HTTP content encoding H1 & H2 (#1174)
Browse files Browse the repository at this point in the history
* Introduce HTTP content encoding H1 & H2

Motivation:

Our HTTP clients & servers don't support any form of compression. There are many use cases that involve large payloads, that compression could make a difference on the HTTP timings.

Modifications:

H1 & H2 protocols were altered to support a list of supported-encodings. We provide the default ones out of the box as part of the discoverability helper ContentEncodings, which offers, GZIP & DEFLATE.
To keep the behavior consistent between the two protocols, we chose to communicate the compression technique to the relevant endpoints through the 'Content-Encoding & Accept-Content-Encoding' headers, rather than on the 'Transfer-Encoding & TE' headers, which are not supported by H2.

Result:

Once the client & server are configured to support different encodings through the new filters (`ContentCodingHttpRequesterFilter` and `ContentCodingHttpServiceFilter`), the server will decide on the encoding based on the client's advertised headers. To disable the encoding for a particular request, or enforce a specific encoding, one can call response.encoding(...) to do so. That, bypasses the auto-selection, and also ignores compatibility checks with the client.

Encoding & Decoding is done in a streaming fashion.
  • Loading branch information
tkountis authored Nov 19, 2020
1 parent 7a58081 commit c2e214e
Show file tree
Hide file tree
Showing 61 changed files with 2,252 additions and 116 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,15 @@ default Buffer newBuffer(boolean direct) {
*/
Buffer newBuffer(int initialCapacity);

/**
* Create a new buffer with the given initial capacity and given max capacity.
*
* @param initialCapacity the initial capacity of the buffer.
* @param maxCapacity the maximum capacity of the buffer.
* @return a new buffer.
*/
Buffer newBuffer(int initialCapacity, int maxCapacity);

/**
* Create a new buffer with the given initial capacity.
*
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,11 @@ public Buffer newBuffer(int initialCapacity) {
throw new UnsupportedOperationException();
}

@Override
public Buffer newBuffer(final int initialCapacity, final int maxCapacity) {
throw new UnsupportedOperationException();
}

@Override
public Buffer newBuffer(int initialCapacity, boolean direct) {
throw new UnsupportedOperationException();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -133,6 +133,11 @@ public Buffer newBuffer(int initialCapacity) {
return new NettyBuffer<>(buffer(initialCapacity));
}

@Override
public Buffer newBuffer(final int initialCapacity, final int maxCapacity) {
return new NettyBuffer<>(buffer(initialCapacity, maxCapacity));
}

@Override
public Buffer newBuffer(int initialCapacity, boolean direct) {
return new NettyBuffer<>(direct ? directBuffer(initialCapacity) : heapBuffer(initialCapacity));
Expand Down
27 changes: 27 additions & 0 deletions servicetalk-encoding-api/build.gradle
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
/*
* Copyright © 2020 Apple Inc. and the ServiceTalk project 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.
*/

apply plugin: "io.servicetalk.servicetalk-gradle-plugin-internal-library"

dependencies {
api project(":servicetalk-buffer-api")
api project(":servicetalk-concurrent-api")

implementation project(":servicetalk-annotations")
implementation project(":servicetalk-concurrent-internal")
implementation "com.google.code.findbugs:jsr305:$jsr305Version"
implementation "org.slf4j:slf4j-api:$slf4jVersion"
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
/*
* Copyright © 2020 Apple Inc. and the ServiceTalk project 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 io.servicetalk.encoding.api;

import java.util.Objects;

abstract class AbstractContentCodec implements ContentCodec {

private final CharSequence name;

AbstractContentCodec(final CharSequence name) {
this.name = name;
}

public final CharSequence name() {
return name;
}

@Override
public boolean equals(final Object o) {
if (this == o) {
return true;
}
if (o == null || getClass() != o.getClass()) {
return false;
}
final AbstractContentCodec that = (AbstractContentCodec) o;
return name.equals(that.name);
}

@Override
public int hashCode() {
return Objects.hash(name);
}

@Override
public String toString() {
return "ContentCodec{" +
"name=" + name +
'}';
}
}
Loading

0 comments on commit c2e214e

Please sign in to comment.