Skip to content

Commit

Permalink
Add brotli4j compression classes and dependencies
Browse files Browse the repository at this point in the history
  • Loading branch information
jcarranzan committed Mar 20, 2024
1 parent 03a2e0c commit da67735
Show file tree
Hide file tree
Showing 8 changed files with 247 additions and 0 deletions.
4 changes: 4 additions & 0 deletions http/http-advanced-reactive/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -94,5 +94,9 @@
<groupId>commons-io</groupId>
<artifactId>commons-io</artifactId>
</dependency>
<dependency>
<groupId>com.aayushatharva.brotli4j</groupId>
<artifactId>brotli4j</artifactId>
</dependency>
</dependencies>
</project>
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
package io.quarkus.ts.http.advanced.reactive;

import com.aayushatharva.brotli4j.Brotli4jLoader;
import com.aayushatharva.brotli4j.decoder.BrotliInputStream;
import com.aayushatharva.brotli4j.encoder.BrotliOutputStream;
import com.aayushatharva.brotli4j.encoder.Encoder;

import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;

public class Brotli4JCompressionUtil {
public static void compressAFile(String inputFilePath, String outFilePath) throws IOException {
// Load the native library
Brotli4jLoader.ensureAvailability();

FileInputStream inFile = new FileInputStream(inputFilePath);
FileOutputStream outFile = new FileOutputStream(outFilePath + ".br");

Encoder.Parameters params = new Encoder.Parameters().setQuality(4);

BrotliOutputStream brotliOutputStream = new BrotliOutputStream(outFile, params);

int read = inFile.read();
while (read > -1) {
brotliOutputStream.write(read);
read = inFile.read();
}

// Close the BrotliOutputStream. This also closes the FileOutputStream.
brotliOutputStream.close();
inFile.close();
}

public static void deCompressAFile(String compressedFilePath, String decompressedFilePath) throws IOException {
// Load the native library
Brotli4jLoader.ensureAvailability();

FileInputStream inFile = new FileInputStream(compressedFilePath);
FileOutputStream outFile = new FileOutputStream(decompressedFilePath);

BrotliInputStream brotliInputStream = new BrotliInputStream(inFile);

int read = brotliInputStream.read();
while (read > -1) {
outFile.write(read);
read = brotliInputStream.read();
}

// Close the BrotliInputStream. This also closes the FileInputStream.
brotliInputStream.close();
outFile.close();
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
package io.quarkus.ts.http.advanced.reactive;

import jakarta.enterprise.context.ApplicationScoped;

import io.netty.handler.codec.compression.BrotliOptions;
import io.netty.handler.codec.compression.StandardCompressionOptions;
import io.quarkus.runtime.Startup;
import io.quarkus.vertx.http.HttpServerOptionsCustomizer;
import io.vertx.core.http.HttpServerOptions;

@Startup
@ApplicationScoped
public class Brotli4JHttpServerConfig implements HttpServerOptionsCustomizer {
// It depends on compression level that we want apply
private int compressionLevel = 4;

@Override
public void customizeHttpServer(HttpServerOptions options) {
options.addCompressor(getBrotliOptions(compressionLevel));
}

@Override
public void customizeHttpsServer(HttpServerOptions options) {
options.addCompressor(getBrotliOptions(compressionLevel));
}

private static BrotliOptions getBrotliOptions(int compressionLevel) {
return StandardCompressionOptions.brotli();
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
package io.quarkus.ts.http.advanced.reactive;

import java.util.HashMap;

import jakarta.inject.Inject;
import jakarta.ws.rs.GET;
import jakarta.ws.rs.Path;
import jakarta.ws.rs.Produces;
import jakarta.ws.rs.core.MediaType;

@Path("/compression")
public class Brotli4JResource {

final static String DEFAULT_TEXT_PLAIN = "As you know, every little bit counts";

@Inject
Brotli4JRestMock brotli4JRestMock;

@GET
@Path("/brotli/json")
@Produces(MediaType.APPLICATION_JSON)
public HashMap<String, Object> jsonHttpResponse() {
return brotli4JRestMock.returnResponse();
}

@GET
@Path("/text")
@Produces(MediaType.TEXT_PLAIN)
public String textPlainHttpResponse() {
return DEFAULT_TEXT_PLAIN;
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
package io.quarkus.ts.http.advanced.reactive;

import java.io.IOException;
import java.io.InputStream;
import java.util.HashMap;

import jakarta.annotation.PostConstruct;
import jakarta.enterprise.context.ApplicationScoped;
import jakarta.inject.Inject;

import org.jboss.logging.Logger;

import com.fasterxml.jackson.core.exc.StreamReadException;
import com.fasterxml.jackson.databind.DatabindException;
import com.fasterxml.jackson.databind.ObjectMapper;

@ApplicationScoped
public class Brotli4JRestMock {

private static final Logger LOGGER = Logger.getLogger(Brotli4JRestMock.class);
@Inject
private ObjectMapper objectMapper;

private static HashMap<String, Object> response = null;

@PostConstruct
public void init() {
try (InputStream inputStream = getClass().getResourceAsStream("/json_sample.json")) {
byte[] bytes = inputStream.readAllBytes();
response = objectMapper.readValue(bytes, HashMap.class);
} catch (StreamReadException | DatabindException e) {
LOGGER.error("Error occurred while deserializing JSON file {}" + e.getMessage());
} catch (IOException e) {
LOGGER.error("Error occurred while reading the JSON file {} " + e.getMessage());
}
}

public HashMap<String, Object> returnResponse() {
return response;
}

}
22 changes: 22 additions & 0 deletions http/http-advanced-reactive/src/main/resources/json_sample.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
{
"glossary": {
"title": "example glossary",
"GlossDiv": {
"title": "Hello from a JSON sample",
"GlossList": {
"GlossEntry": {
"ID": "SGML",
"SortAs": "SGML",
"GlossTerm": "Standard Generalized Markup Language",
"Acronym": "SGML",
"Abbrev": "ISO 8879:1986",
"GlossDef": {
"para": "A meta-markup language, used to create markup languages such as DocBook.",
"GlossSeeAlso": ["GML", "XML"]
},
"GlossSee": "markup"
}
}
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
package io.quarkus.ts.http.advanced.reactive;

import static org.hamcrest.Matchers.contains;
import static org.hamcrest.Matchers.is;

import org.junit.jupiter.api.Tag;
import org.junit.jupiter.api.Test;

import io.quarkus.test.bootstrap.RestService;
import io.quarkus.test.scenarios.QuarkusScenario;
import io.quarkus.test.services.QuarkusApplication;

import java.io.IOException;

@Tag("QQE-378")
@QuarkusScenario
public class Brotli4JHttpIT {
@QuarkusApplication(classes = { Brotli4JHttpServerConfig.class, Brotli4JResource.class, Brotli4JRestMock.class
}, properties = "compression.properties")
static RestService app = new RestService();

private final static String DEFAULT_TEXT_PLAIN = "As you know, every little bit counts";

@Test
public void checkTextPlainWithoutBrotli4JEncoding() {
app.given()
.get("/compression/text")
.then()
.statusCode(200)
.and()
.header("content-length", "36")
.body(is(DEFAULT_TEXT_PLAIN)).log().all();
}

@Test
public void checkTextPlainWithtBrotli4J() {
app.given()
.header("Accept-Encoding", "br")
.get("/compression/text")
.then()
.statusCode(200)
.and()
.header("content-length", "43")
.header("content-encoding", "br");

}

@Test
public void checkJsonBrotli4JCompression() {
app.given()
.header("Accept-Encoding", "br")
.get("/compression/brotli/json")
.then()
.statusCode(200)
.header("content-length", "236")
.header("content-encoding", "br");
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
quarkus.oidc.enabled=false
quarkus.http.enable-compression=true
quarkus.http.compress-media-types=application/json,text/plain,application/xml

0 comments on commit da67735

Please sign in to comment.