Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add support for brotli compression format #2213

Closed
wants to merge 36 commits into from
Closed
Show file tree
Hide file tree
Changes from 35 commits
Commits
Show all changes
36 commits
Select commit Hold shift + click to select a range
c6c8111
Add brotli compression support
TharmiganK May 17, 2024
3be5f57
Fix compression test case
TharmiganK May 17, 2024
89915a8
[Automated] Update the native jar versions
TharmiganK May 17, 2024
30a4e1a
[Automated] Update the native jar versions
TharmiganK May 17, 2024
da6e6ed
Update changelog
TharmiganK May 17, 2024
5ee556b
Add native image configurations
TharmiganK May 17, 2024
de6d132
Merge remote-tracking branch 'refs/remotes/origin/master' into br-enc…
TharmiganK May 30, 2024
8eb0422
Merge branch 'master' into br-encoding-format
TharmiganK Jun 5, 2024
a2040c7
Merge branch 'master' into br-encoding-format
TharmiganK Jun 11, 2024
fc32ad1
Merge branch 'master' into br-encoding-format
TharmiganK Jun 13, 2024
a06d2b2
Merge branch 'master' into br-encoding-format
TharmiganK Jun 17, 2024
fc25863
Merge branch 'master' into br-encoding-format
TharmiganK Jul 15, 2024
6204b2e
Merge branch 'master' into br-encoding-format
TharmiganK Jul 29, 2024
691e52e
Merge branch 'master' into br-encoding-format
TharmiganK Aug 1, 2024
7d4f51b
Merge branch 'master' into br-encoding-format
TharmiganK Aug 15, 2024
8ef5d5c
Add brotli encoder support for HTTP2
TharmiganK Aug 15, 2024
9f1a143
Merge branch 'master' into br-encoding-format
TharmiganK Aug 15, 2024
a8005ce
Update the test case with brotli encoding support
TharmiganK Aug 15, 2024
129d816
Merge branch 'master' into br-encoding-format
TharmiganK Aug 16, 2024
e2481be
Merge branch 'master' into br-encoding-format
TharmiganK Aug 20, 2024
eb758ed
Add ballerina client tests
TharmiganK Aug 21, 2024
5cfe311
Merge branch 'master' into br-encoding-format
TharmiganK Aug 21, 2024
ac6cc07
Merge branch 'master' into br-encoding-format
TharmiganK Aug 23, 2024
08d16d3
Merge branch 'master' into br-encoding-format
TharmiganK Sep 2, 2024
187852b
Merge branch 'master' into br-encoding-format
TharmiganK Sep 2, 2024
b6a733e
Merge branch 'master' into br-encoding-format
TharmiganK Sep 4, 2024
9c1c6c8
Merge branch 'master' into br-encoding-format
TharmiganK Sep 5, 2024
545664c
Merge branch 'master' into br-encoding-format
TharmiganK Sep 9, 2024
4375808
Merge branch 'master' into br-encoding-format
TharmiganK Sep 10, 2024
0d78e71
Merge branch 'master' into br-encoding-format
TharmiganK Sep 13, 2024
7341bd7
Merge branch 'master' into br-encoding-format
TharmiganK Sep 18, 2024
b2a5e9a
Merge branch 'master' into br-encoding-format
TharmiganK Sep 23, 2024
f9317e8
Merge remote-tracking branch 'origin/master' into br-encoding-format
TharmiganK Nov 11, 2024
336baa9
Merge branch 'master' into br-encoding-format
TharmiganK Nov 12, 2024
0c3a352
Update changelog
TharmiganK Nov 12, 2024
7fb41dc
Remove new line
TharmiganK Nov 12, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -112,25 +112,103 @@ function testAutoCompress() {
test:assertFalse(response.hasHeader(common:CONTENT_ENCODING),
msg = "The content-encoding header should be null and the identity which means no compression " +
"should be done to the response");
common:assertTextPayload(response.getTextPayload(), "Hello World!!!");
} else {
test:assertFail(msg = "Found unexpected output type: " + response.message());
}
}

//Test Compression.AUTO, with Accept-Encoding header.
//Test Compression.AUTO, with Accept-Encoding header - gzip.
//The response here means the one that should be sent to transport, not to end user.
@test:Config {}
function testAutoCompressWithAcceptEncoding() {
function testAutoCompressWithAcceptEncoding1() {
http:Response|error response = compressionClient->get("/autoCompress", {[common:ACCEPT_ENCODING] : [common:ENCODING_GZIP]});
if response is http:Response {
test:assertFalse(response.hasHeader(common:CONTENT_ENCODING),
msg = "The content-encoding header should be null and the original value of Accept-Encoding should " +
"be used for compression from the backend");
common:assertTextPayload(response.getTextPayload(), "Hello World!!!");
} else {
test:assertFail(msg = "Found unexpected output type: " + response.message());
}
}

//Test Compression.AUTO, with Accept-Encoding header - br.
//The response here means the one that should be sent to transport, not to end user.
@test:Config {}
function testAutoCompressWithAcceptEncoding2() {
http:Response|error response = compressionClient->get("/autoCompress", {[common:ACCEPT_ENCODING] : [common:ENCODING_BR]});
if response is http:Response {
test:assertFalse(response.hasHeader(common:CONTENT_ENCODING),
msg = "The content-encoding header should be null and the original value of Accept-Encoding should " +
"be used for compression from the backend");
common:assertTextPayload(response.getTextPayload(), "Hello World!!!");
} else {
test:assertFail(msg = "Found unexpected output type: " + response.message());
}
}

//Test Compression.AUTO, with Accept-Encoding header - deflate.
//The response here means the one that should be sent to transport, not to end user.
@test:Config {}
function testAutoCompressWithAcceptEncoding3() {
http:Response|error response = compressionClient->get("/autoCompress", {[common:ACCEPT_ENCODING] : [common:ENCODING_DEFLATE]});
if response is http:Response {
test:assertFalse(response.hasHeader(common:CONTENT_ENCODING),
msg = "The content-encoding header should be null and the original value of Accept-Encoding should " +
"be used for compression from the backend");
common:assertTextPayload(response.getTextPayload(), "Hello World!!!");
} else {
test:assertFail(msg = "Found unexpected output type: " + response.message());
}
}

//Test Compression.AUTO, with Accept-Encoding header - gzip, deflate.
//The response here means the one that should be sent to transport, not to end user.
@test:Config {}
function testAutoCompressWithAcceptEncoding4() {
http:Response|error response = compressionClient->get("/autoCompress", {[common:ACCEPT_ENCODING] : [common:ENCODING_GZIP, common:ENCODING_DEFLATE]});
if response is http:Response {
test:assertFalse(response.hasHeader(common:CONTENT_ENCODING),
msg = "The content-encoding header should be null and the original value of Accept-Encoding should " +
"be used for compression from the backend");
common:assertTextPayload(response.getTextPayload(), "Hello World!!!");
} else {
test:assertFail(msg = "Found unexpected output type: " + response.message());
}
}

//Test Compression.AUTO, with Accept-Encoding header - gzip, br.
//The response here means the one that should be sent to transport, not to end user.
@test:Config {}
function testAutoCompressWithAcceptEncoding5() {
http:Response|error response = compressionClient->get("/autoCompress", {[common:ACCEPT_ENCODING] : [common:ENCODING_GZIP, common:ENCODING_BR]});
if response is http:Response {
test:assertFalse(response.hasHeader(common:CONTENT_ENCODING),
msg = "The content-encoding header should be null and the original value of Accept-Encoding should " +
"be used for compression from the backend");
common:assertTextPayload(response.getTextPayload(), "Hello World!!!");
} else {
test:assertFail(msg = "Found unexpected output type: " + response.message());
}
}

//Test Compression.AUTO, with Accept-Encoding header - gzip, deflate, br.
//The response here means the one that should be sent to transport, not to end user.
@test:Config {}
function testAutoCompressWithAcceptEncoding6() {
http:Response|error response = compressionClient->get("/autoCompress", {[common:ACCEPT_ENCODING] : [common:ENCODING_GZIP, common:ENCODING_DEFLATE, common:ENCODING_BR]});
if response is http:Response {
test:assertFalse(response.hasHeader(common:CONTENT_ENCODING),
msg = "The content-encoding header should be null and the original value of Accept-Encoding should " +
"be used for compression from the backend");
common:assertTextPayload(response.getTextPayload(), "Hello World!!!");
} else {
test:assertFail(msg = "Found unexpected output type: " + response.message());
}
}


//Test Compression.AUTO, with contentTypes and without Accept-Encoding header.
//The response here means the one that should be sent to transport, not to end user.
@test:Config {}
Expand All @@ -154,23 +232,52 @@ function testAlwaysCompress() returns error? {
if response is http:Response {
test:assertEquals(check response.getHeader(common:CONTENT_ENCODING), common:ENCODING_GZIP,
msg = "The content-encoding header should be gzip.");
common:assertTextPayload(response.getTextPayload(), "Hello World!!!");
} else {
test:assertFail(msg = "Found unexpected output type: " + response.message());
}
}

//Test Compression.ALWAYS, with Accept-Encoding header.
//Test Compression.ALWAYS, with Accept-Encoding header - deflate.
//The response here means the one that should be sent to transport, not to end user.
@test:Config {}
function testAlwaysCompressWithAcceptEncoding() {
http:Request req = new;
req.setTextPayload("hello");
req.setHeader(common:ACCEPT_ENCODING, common:ENCODING_DEFLATE);
http:Response|error response = compressionClient->post("/alwaysCompress", req);
function testAlwaysCompressWithAcceptEncoding1() {
http:Response|error response = compressionClient->get("/alwaysCompress", {[common:ACCEPT_ENCODING]: common:ENCODING_DEFLATE});
if response is http:Response {
test:assertFalse(response.hasHeader(common:CONTENT_ENCODING),
msg = "The content-encoding header should be set to null and the transport will use the original" +
"Accept-Encoding value for compression.");
common:assertTextPayload(response.getTextPayload(), "Hello World!!!");
} else {
test:assertFail(msg = "Found unexpected output type: " + response.message());
}
}

//Test Compression.ALWAYS, with Accept-Encoding header - br.
//The response here means the one that should be sent to transport, not to end user.
@test:Config {}
function testAlwaysCompressWithAcceptEncoding2() {
http:Response|error response = compressionClient->get("/alwaysCompress", {[common:ACCEPT_ENCODING]: common:ENCODING_BR});
if response is http:Response {
test:assertFalse(response.hasHeader(common:CONTENT_ENCODING),
msg = "The content-encoding header should be set to null and the transport will use the original" +
"Accept-Encoding value for compression.");
common:assertTextPayload(response.getTextPayload(), "Hello World!!!");
} else {
test:assertFail(msg = "Found unexpected output type: " + response.message());
}
}

//Test Compression.ALWAYS, with Accept-Encoding header - deflate, br.
//The response here means the one that should be sent to transport, not to end user.
@test:Config {}
function testAlwaysCompressWithAcceptEncoding3() {
http:Response|error response = compressionClient->get("/alwaysCompress", {[common:ACCEPT_ENCODING]: [common:ENCODING_DEFLATE + "," + common:ENCODING_BR]});
if response is http:Response {
test:assertFalse(response.hasHeader(common:CONTENT_ENCODING),
msg = "The content-encoding header should be set to null and the transport will use the original" +
"Accept-Encoding value for compression.");
common:assertTextPayload(response.getTextPayload(), "Hello World!!!");
} else {
test:assertFail(msg = "Found unexpected output type: " + response.message());
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ function testAcceptEncodingEnabled() {
http:Response|error response = acceptEncodingEnableEP->post("/", req);
if response is http:Response {
test:assertEquals(response.statusCode, 200, msg = "Found unexpected output");
common:assertJsonValue(response.getJsonPayload(), "acceptEncoding", "deflate, gzip");
common:assertJsonValue(response.getJsonPayload(), "acceptEncoding", "deflate, gzip, br");
common:assertHeaderValue(response.server, "Mysql");
} else {
test:assertFail(msg = "Found unexpected output type: " + response.message());
Expand Down
1 change: 1 addition & 0 deletions ballerina-tests/http-test-common/constants.bal
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,7 @@ public const string SERVER = "server";

public const string ENCODING_GZIP = "gzip";
public const string ENCODING_DEFLATE = "deflate";
public const string ENCODING_BR = "br";
public const string HTTP_TRANSFER_ENCODING_IDENTITY = "identity";

public const string HTTP_METHOD_GET = "GET";
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@ function testHttp2AcceptEncodingEnabled() {
http:Response|error response = http2AcceptEncodingEnableEP->post("/", req);
if response is http:Response {
test:assertEquals(response.statusCode, 200, msg = "Found unexpected output");
common:assertJsonValue(response.getJsonPayload(), "acceptEncoding", "deflate, gzip");
common:assertJsonValue(response.getJsonPayload(), "acceptEncoding", "deflate, gzip, br");
common:assertHeaderValue(response.server, "Mysql");
} else {
test:assertFail(msg = "Found unexpected output type: " + response.message());
Expand Down
36 changes: 36 additions & 0 deletions ballerina/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -147,6 +147,40 @@ dependencies {
externalJars(group: 'com.google.protobuf', name: 'protobuf-java', version: "${protobufVersion}") {
transitive = false
}

externalJars(group: 'com.aayushatharva.brotli4j', name: 'brotli4j', version: "${brotli4jVersion}") {
transitive = false
}
externalJars(group: 'com.aayushatharva.brotli4j', name: 'service', version: "${brotli4jVersion}") {
transitive = false
}
externalJars(group: 'com.aayushatharva.brotli4j', name: 'native-linux-ppc64le', version: "${brotli4jVersion}") {
transitive = false
}
externalJars(group: 'com.aayushatharva.brotli4j', name: 'native-linux-x86_64', version: "${brotli4jVersion}") {
transitive = false
}
externalJars(group: 'com.aayushatharva.brotli4j', name: 'native-linux-aarch64', version: "${brotli4jVersion}") {
transitive = false
}
externalJars(group: 'com.aayushatharva.brotli4j', name: 'native-linux-armv7', version: "${brotli4jVersion}") {
transitive = false
}
externalJars(group: 'com.aayushatharva.brotli4j', name: 'native-linux-riscv64', version: "${brotli4jVersion}") {
transitive = false
}
externalJars(group: 'com.aayushatharva.brotli4j', name: 'native-osx-x86_64', version: "${brotli4jVersion}") {
transitive = false
}
externalJars(group: 'com.aayushatharva.brotli4j', name: 'native-osx-aarch64', version: "${brotli4jVersion}") {
transitive = false
}
externalJars(group: 'com.aayushatharva.brotli4j', name: 'native-windows-x86_64', version: "${brotli4jVersion}") {
transitive = false
}
externalJars(group: 'com.aayushatharva.brotli4j', name: 'native-windows-aarch64', version: "${brotli4jVersion}") {
transitive = false
}
}

task updateTomlFiles {
Expand All @@ -164,6 +198,7 @@ task updateTomlFiles {
def stdlibDependentLz4Version = project.lz4Version
def stdlibDependentMarshallingVersion = project.marshallingVersion
def stdlibDependentProtobufVersion = project.protobufVersion
def stdlibDependentBrotli4jVersion = project.brotli4jVersion
def ballerinaToOpenApiVersion = project.ballerinaToOpenApiVersion

def newBallerinaToml = ballerinaTomlFilePlaceHolder.text.replace("@project.version@", project.version)
Expand All @@ -181,6 +216,7 @@ task updateTomlFiles {
newBallerinaToml = newBallerinaToml.replace("@lz4.version@", stdlibDependentLz4Version)
newBallerinaToml = newBallerinaToml.replace("@marshalling.version@", stdlibDependentMarshallingVersion)
newBallerinaToml = newBallerinaToml.replace("@protobuf.version@", stdlibDependentProtobufVersion)
newBallerinaToml = newBallerinaToml.replace("@brotli4j.version@", stdlibDependentBrotli4jVersion)
ballerinaTomlFile.text = newBallerinaToml

def newCompilerPluginToml = compilerPluginTomlFilePlaceHolder.text.replace("@project.version@", project.version)
Expand Down
66 changes: 66 additions & 0 deletions build-config/resources/Ballerina.toml
Original file line number Diff line number Diff line change
Expand Up @@ -171,3 +171,69 @@ groupId = "com.google.protobufl"
artifactId = "protobuf-java"
version = "@protobuf.version@"
path = "./lib/[email protected]@.jar"

[[platform.java17.dependency]]
groupId = "com.aayushatharva.brotli4j"
artifactId = "brotli4j"
version = "@brotli4j.version@"
path = "./lib/[email protected]@.jar"

[[platform.java17.dependency]]
groupId = "com.aayushatharva.brotli4j"
artifactId = "service"
version = "@brotli4j.version@"
path = "./lib/[email protected]@.jar"

[[platform.java17.dependency]]
groupId = "com.aayushatharva.brotli4j"
artifactId = "native-linux-ppc64le"
version = "@brotli4j.version@"
path = "./lib/[email protected]@.jar"

[[platform.java17.dependency]]
groupId = "com.aayushatharva.brotli4j"
artifactId = "native-linux-x86_64"
version = "@brotli4j.version@"
path = "./lib/[email protected]@.jar"

[[platform.java17.dependency]]
groupId = "com.aayushatharva.brotli4j"
artifactId = "native-linux-aarch64"
version = "@brotli4j.version@"
path = "./lib/[email protected]@.jar"

[[platform.java17.dependency]]
groupId = "com.aayushatharva.brotli4j"
artifactId = "native-linux-armv7"
version = "@brotli4j.version@"
path = "./lib/[email protected]@.jar"

[[platform.java17.dependency]]
groupId = "com.aayushatharva.brotli4j"
artifactId = "native-linux-riscv64"
version = "@brotli4j.version@"
path = "./lib/[email protected]@.jar"

[[platform.java17.dependency]]
groupId = "com.aayushatharva.brotli4j"
artifactId = "native-osx-x86_64"
version = "@brotli4j.version@"
path = "./lib/[email protected]@.jar"

[[platform.java17.dependency]]
groupId = "com.aayushatharva.brotli4j"
artifactId = "native-osx-aarch64"
version = "@brotli4j.version@"
path = "./lib/[email protected]@.jar"

[[platform.java17.dependency]]
groupId = "com.aayushatharva.brotli4j"
artifactId = "native-windows-x86_64"
version = "@brotli4j.version@"
path = "./lib/[email protected]@.jar"

[[platform.java17.dependency]]
groupId = "com.aayushatharva.brotli4j"
artifactId = "native-windows-aarch64"
version = "@brotli4j.version@"
path = "./lib/[email protected]@.jar"
2 changes: 2 additions & 0 deletions changelog.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
- [Introduce util functions to convert query and header record with the `http:Query` and the `http:Header` annotations](https://github.com/ballerina-platform/ballerina-library/issues/7019)
- [Migrate client and service data binding lang utils usage into data.jsondata module utils `toJson` and `parserAsType`] (https://github.com/ballerina-platform/ballerina-library/issues/6747)
- [Add static code rules](https://github.com/ballerina-platform/ballerina-library/issues/7283)
- [Add compression/decompression support for `brotli` compression format](https://github.com/ballerina-platform/ballerina-library/issues/6547)

### Fixed

Expand All @@ -25,6 +26,7 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
## [2.12.0] - 2024-08-20

### Added

TharmiganK marked this conversation as resolved.
Show resolved Hide resolved
- [Add support for Server-Sent Events](https://github.com/ballerina-platform/ballerina-library/issues/6687)
- [Introduce default status code response record](https://github.com/ballerina-platform/ballerina-library/issues/6491)
- [Add connection eviction feature to handle connections that receive GO_AWAY from the client](https://github.com/ballerina-platform/ballerina-library/issues/6734)
Expand Down
1 change: 1 addition & 0 deletions gradle.properties
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ lz4Version=1.3.0
marshallingVersion=2.0.5.Final
protobufVersion=3.25.5
jacocoVersion=0.8.10
brotli4jVersion=1.16.0
ballerinaToOpenApiVersion=2.1.0
swaggerCoreVersion=2.2.22

Expand Down
11 changes: 11 additions & 0 deletions native/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,17 @@ dependencies {
implementation group: 'org.bouncycastle', name: 'bcutil-jdk18on', version: "${bouncycastleVersion}"
implementation group: 'org.bouncycastle', name: 'bcpkix-jdk18on', version: "${bouncycastleVersion}"
implementation group: 'jakarta.xml.bind', name: 'jakarta.xml.bind-api', version: "${jakartaXmlBindVersion}"
implementation group: 'com.aayushatharva.brotli4j', name: 'brotli4j', version: "${brotli4jVersion}"
implementation group: 'com.aayushatharva.brotli4j', name: 'service', version: "${brotli4jVersion}"
implementation group: 'com.aayushatharva.brotli4j', name: 'native-linux-ppc64le', version: "${brotli4jVersion}"
implementation group: 'com.aayushatharva.brotli4j', name: 'native-linux-x86_64', version: "${brotli4jVersion}"
implementation group: 'com.aayushatharva.brotli4j', name: 'native-linux-aarch64', version: "${brotli4jVersion}"
implementation group: 'com.aayushatharva.brotli4j', name: 'native-linux-armv7', version: "${brotli4jVersion}"
implementation group: 'com.aayushatharva.brotli4j', name: 'native-linux-riscv64', version: "${brotli4jVersion}"
implementation group: 'com.aayushatharva.brotli4j', name: 'native-osx-x86_64', version: "${brotli4jVersion}"
implementation group: 'com.aayushatharva.brotli4j', name: 'native-osx-aarch64', version: "${brotli4jVersion}"
implementation group: 'com.aayushatharva.brotli4j', name: 'native-windows-x86_64', version: "${brotli4jVersion}"
implementation group: 'com.aayushatharva.brotli4j', name: 'native-windows-aarch64', version: "${brotli4jVersion}"

testImplementation group: 'org.mock-server', name: 'mockserver-netty', version:"${mockserverNettyVersion}"
testImplementation group: 'com.mashape.unirest', name: 'unirest-java', version:"${unirestVersion}"
Expand Down
Loading
Loading