-
-
Save StFS/90d090cb811cb25d2d9fde35e838704c to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package com.genuitysci.fileservice.interceptor | |
import io.quarkus.runtime.configuration.MemorySize | |
import org.eclipse.microprofile.config.ConfigProvider | |
import org.jboss.resteasy.resteasy_jaxrs.i18n.Messages | |
import java.io.IOException | |
import java.io.InputStream | |
import java.io.OutputStream | |
import java.math.BigInteger | |
import java.util.zip.GZIPInputStream | |
import java.util.zip.GZIPOutputStream | |
import javax.ws.rs.WebApplicationException | |
import javax.ws.rs.core.HttpHeaders | |
import javax.ws.rs.core.Response | |
import javax.ws.rs.core.Response.Status.* | |
import javax.ws.rs.ext.* | |
/** | |
* Custom gzip support, workaround for https://github.com/quarkusio/quarkus/issues/12647 | |
* - even though the issue was closed, it's not fixed! | |
* | |
* NB: should be deleted when quarkus will have proper built-in gzip support. | |
*/ | |
@Provider | |
class GZIPInterceptor : ReaderInterceptor, WriterInterceptor { | |
// The below properties are lazy-loaded in this weird way to support native image building. | |
// The native build initializes all classes and if these properties were initialized in a | |
// constructor the would be initialized at build time and not runtime. | |
private var _isEnabled: Boolean? = null | |
private val isEnabled: Boolean | |
get() { | |
if (_isEnabled == null) { | |
val quarkusResteasyGzipEnabled = | |
ConfigProvider.getConfig().getOptionalValue("quarkus.resteasy.gzip.enabled", Boolean::class.java) | |
val ftsResteasyGzipEnabled = ConfigProvider.getConfig() | |
.getOptionalValue("nextcode.fts.resteasy.gzip.enabled", Boolean::class.java) | |
ftsResteasyGzipEnabled.ifPresent { | |
quarkusResteasyGzipEnabled.ifPresent { | |
if (quarkusResteasyGzipEnabled.get()) { | |
throw IOException("Can't have both Quarkus and FTS gzip interceptors enabled") | |
} | |
} | |
_isEnabled = ftsResteasyGzipEnabled.get() | |
} | |
} | |
return _isEnabled as Boolean | |
} | |
private var _maxInput: MemorySize? = null | |
private val maxInputBytes: Long | |
get() { | |
if (_maxInput == null) { | |
val ftsResteasyGzipMaxInput = ConfigProvider.getConfig() | |
.getOptionalValue("nextcode.fts.resteasy.gzip.max-input", MemorySize::class.java) | |
if (ftsResteasyGzipMaxInput.isPresent) { | |
_maxInput = ftsResteasyGzipMaxInput.get() | |
} else { | |
_maxInput = MemorySize(BigInteger.valueOf(100 * 1024 * 1024)) // Default to 100M | |
} | |
} | |
return _maxInput!!.asLongValue() | |
} | |
@Throws(IOException::class) | |
override fun aroundReadFrom(context: ReaderInterceptorContext): Any { | |
if (!isEnabled) { | |
return context.proceed() | |
} | |
val clientAcceptEncodingHeaders = context.headers[HttpHeaders.ACCEPT_ENCODING] | |
val clientAcceptsGzip = clientAcceptEncodingHeaders?.flatMap { headerLine -> | |
headerLine.split(",").map { headerItem -> headerItem.trim() } | |
}?.contains("gzip") ?: false | |
if (clientAcceptsGzip) { | |
context.setProperty(COMPRESS_RESPONSE, true) | |
} | |
val requestContentEncoding = context.headers.getFirst(HttpHeaders.CONTENT_ENCODING) | |
if (requestContentEncoding?.contains("gzip") == true) { | |
context.inputStream = ObservableInputStream(GZIPInputStream(context.inputStream)) { bytesRead -> | |
if (bytesRead > maxInputBytes) { | |
// We can only do this after we've read the content as streams usually don't support reporting size | |
val size = if (maxInputBytes > Int.MAX_VALUE) Int.MAX_VALUE else maxInputBytes.toInt() | |
throw WebApplicationException( | |
Response.status(REQUEST_ENTITY_TOO_LARGE) | |
.entity(Messages.MESSAGES.gzipExceedsMaxSize(size)).build() | |
) | |
} | |
} | |
} | |
return context.proceed() | |
} | |
@Throws(IOException::class) | |
override fun aroundWriteTo(context: WriterInterceptorContext) { | |
if (!isEnabled) { | |
return context.proceed() | |
} | |
if (true == context.getProperty(COMPRESS_RESPONSE)) { | |
val headers = context.headers | |
headers.add(HttpHeaders.CONTENT_ENCODING, "gzip") | |
context.outputStream = GZIPOutputStream(context.outputStream) | |
} | |
context.proceed() | |
} | |
companion object { | |
const val COMPRESS_RESPONSE = "__COMPRESS_RESPONSE__" | |
} | |
} | |
/** | |
* An input stream that observes the amount of data streamed and reports it to a callback function. | |
*/ | |
class ObservableInputStream( | |
private val wrapped: InputStream, | |
private val onBytesRead: (Long) -> Unit | |
) : InputStream() { | |
private var bytesRead: Long = 0 | |
// Delegate all read methods of InputStream, collecting the bytes read. | |
@Throws(IOException::class) | |
override fun read(): Int { | |
val res = wrapped.read() | |
if (res > -1) { | |
bytesRead++ | |
} | |
onBytesRead(bytesRead) | |
return res | |
} | |
@Throws(IOException::class) | |
override fun read(b: ByteArray): Int { | |
val res = wrapped.read(b) | |
if (res > -1) { | |
bytesRead += res | |
onBytesRead(bytesRead) | |
} | |
return res | |
} | |
@Throws(IOException::class) | |
override fun read(b: ByteArray, off: Int, len: Int): Int { | |
val res = wrapped.read(b, off, len) | |
if (res > -1) { | |
bytesRead += res | |
onBytesRead(bytesRead) | |
} | |
return res | |
} | |
// Delegate all other methods of InputStream directly | |
@Throws(IOException::class) | |
override fun close() { | |
wrapped.close() | |
} | |
@Throws(IOException::class) | |
override fun readAllBytes(): ByteArray { | |
return wrapped.readAllBytes() | |
} | |
@Throws(IOException::class) | |
override fun readNBytes(len: Int): ByteArray { | |
return wrapped.readNBytes(len) | |
} | |
@Throws(IOException::class) | |
override fun readNBytes(b: ByteArray, off: Int, len: Int): Int { | |
return wrapped.readNBytes(b, off, len) | |
} | |
@Throws(IOException::class) | |
override fun skip(n: Long): Long { | |
return wrapped.skip(n) | |
} | |
@Throws(IOException::class) | |
override fun skipNBytes(n: Long) { | |
wrapped.skipNBytes(n) | |
} | |
@Throws(IOException::class) | |
override fun available(): Int { | |
return wrapped.available() | |
} | |
override fun mark(readlimit: Int) { | |
wrapped.mark(readlimit) | |
} | |
@Throws(IOException::class) | |
override fun reset() { | |
wrapped.reset() | |
} | |
override fun markSupported(): Boolean { | |
return wrapped.markSupported() | |
} | |
@Throws(IOException::class) | |
override fun transferTo(out: OutputStream): Long { | |
return wrapped.transferTo(out) | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
> Task :compileKotlin | |
Caching disabled for task ':compileKotlin' because: | |
Build cache is disabled | |
Task ':compileKotlin' is not up-to-date because: | |
Task has failed previously. | |
The input changes require a full rebuild for incremental task ':compileKotlin'. | |
file or directory '/Users/stefan/work/gor/quarkus/file-transfer-service/src/main/java', not found | |
file or directory '/Users/stefan/work/gor/quarkus/file-transfer-service/src/main/java', not found | |
Using Kotlin/JVM incremental compilation | |
i: starting the daemon as: /Library/Java/JavaVirtualMachines/adoptopenjdk-11.jdk/Contents/Home/bin/java -cp /Users/stefan/.gradle/caches/modules-2/files-2.1/org.jetbrains.kotlin/kotlin-compiler-embeddable/1.3.72/fb72232c8fa977d5e07d33c43381ddbdc5edab6/kotlin-compiler-embeddable-1.3.72.jar:/Users/stefan/.gradle/caches/modules-2/files-2.1/org.jetbrains.kotlin/kotlin-reflect/1.3.72/86613e1a669a701b0c660bfd2af4f82a7ae11fca/kotlin-reflect-1.3.72.jar:/Users/stefan/.gradle/caches/modules-2/files-2.1/org.jetbrains.kotlin/kotlin-stdlib/1.3.72/8032138f12c0180bc4e51fe139d4c52b46db6109/kotlin-stdlib-1.3.72.jar:/Users/stefan/.gradle/caches/modules-2/files-2.1/org.jetbrains.kotlin/kotlin-script-runtime/1.3.72/657d8d34d91e1964b4439378c09933e840bfe8d5/kotlin-script-runtime-1.3.72.jar:/Users/stefan/.gradle/caches/modules-2/files-2.1/org.jetbrains.kotlin/kotlin-daemon-embeddable/1.3.72/53bbaa2816dbf6bdb85f629451b1fcc88f2164d2/kotlin-daemon-embeddable-1.3.72.jar:/Users/stefan/.gradle/caches/modules-2/files-2.1/org.jetbrains.intellij.deps/trove4j/1.0.20181211/216c2e14b070f334479d800987affe4054cd563f/trove4j-1.0.20181211.jar:/Users/stefan/.gradle/caches/modules-2/files-2.1/org.jetbrains.kotlin/kotlin-stdlib-common/1.3.72/6ca8bee3d88957eaaaef077c41c908c9940492d8/kotlin-stdlib-common-1.3.72.jar:/Users/stefan/.m2/repository/org/jetbrains/annotations/13.0/annotations-13.0.jar -Djava.awt.headless=true -Djava.rmi.server.hostname=127.0.0.1 -Xmx512m -XX:MaxMetaspaceSize=256m -Dkotlin.environment.keepalive -ea org.jetbrains.kotlin.daemon.KotlinCompileDaemon --daemon-runFilesPath /Users/stefan/Library/Application Support/kotlin/daemon --daemon-autoshutdownIdleSeconds=7200 --daemon-compilerClasspath /Users/stefan/.gradle/caches/modules-2/files-2.1/org.jetbrains.kotlin/kotlin-compiler-embeddable/1.3.72/fb72232c8fa977d5e07d33c43381ddbdc5edab6/kotlin-compiler-embeddable-1.3.72.jar:/Users/stefan/.gradle/caches/modules-2/files-2.1/org.jetbrains.kotlin/kotlin-reflect/1.3.72/86613e1a669a701b0c660bfd2af4f82a7ae11fca/kotlin-reflect-1.3.72.jar:/Users/stefan/.gradle/caches/modules-2/files-2.1/org.jetbrains.kotlin/kotlin-stdlib/1.3.72/8032138f12c0180bc4e51fe139d4c52b46db6109/kotlin-stdlib-1.3.72.jar:/Users/stefan/.gradle/caches/modules-2/files-2.1/org.jetbrains.kotlin/kotlin-script-runtime/1.3.72/657d8d34d91e1964b4439378c09933e840bfe8d5/kotlin-script-runtime-1.3.72.jar:/Users/stefan/.gradle/caches/modules-2/files-2.1/org.jetbrains.kotlin/kotlin-daemon-embeddable/1.3.72/53bbaa2816dbf6bdb85f629451b1fcc88f2164d2/kotlin-daemon-embeddable-1.3.72.jar:/Users/stefan/.gradle/caches/modules-2/files-2.1/org.jetbrains.intellij.deps/trove4j/1.0.20181211/216c2e14b070f334479d800987affe4054cd563f/trove4j-1.0.20181211.jar:/Users/stefan/.gradle/caches/modules-2/files-2.1/org.jetbrains.kotlin/kotlin-stdlib-common/1.3.72/6ca8bee3d88957eaaaef077c41c908c9940492d8/kotlin-stdlib-common-1.3.72.jar:/Users/stefan/.m2/repository/org/jetbrains/annotations/13.0/annotations-13.0.jar | |
i: Received the message signalling that the daemon is ready | |
i: new daemon started, trying to find it | |
i: found daemon on port 17766 (28 ms old), trying to connect | |
i: connected to the daemon | |
Options for KOTLIN DAEMON: IncrementalCompilationOptions(super=CompilationOptions(compilerMode=INCREMENTAL_COMPILER, targetPlatform=JVM, reportCategories=[0], reportSeverity=2, requestedCompilationResults=[0]kotlinScriptExtensions=[kt, kts, java]), areFileChangesKnown=false, modifiedFiles=null, deletedFiles=null, workingDir=/Users/stefan/work/gor/quarkus/file-transfer-service/build/kotlin/compileKotlin, multiModuleICSettings=MultiModuleICSettings(buildHistoryFile=/Users/stefan/work/gor/quarkus/file-transfer-service/build/kotlin/compileKotlin/build-history.bin, useModuleDetection=false), usePreciseJavaTracking=trueoutputFiles=[/Users/stefan/work/gor/quarkus/file-transfer-service/build/classes/kotlin/main, /Users/stefan/work/gor/quarkus/file-transfer-service/build/kotlin/compileKotlin]) | |
e: /Users/stefan/work/gor/quarkus/file-transfer-service/src/main/kotlin/com/genuitysci/fileservice/interceptor/GZIPInterceptor.kt: (187, 5): 'skipNBytes' overrides nothing | |
e: /Users/stefan/work/gor/quarkus/file-transfer-service/src/main/kotlin/com/genuitysci/fileservice/interceptor/GZIPInterceptor.kt: (188, 15): Unresolved reference: skipNBytes | |
> Task :compileKotlin FAILED | |
:compileKotlin (Thread[Execution worker for ':',5,main]) completed. Took 7.144 secs. | |
FAILURE: Build failed with an exception. |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment