Skip to content

Commit

Permalink
feat: return bad request error when unknown compression format in req…
Browse files Browse the repository at this point in the history
…uest #647
  • Loading branch information
fengelniederhammer committed Feb 16, 2024
1 parent 7e49aa5 commit 4720332
Show file tree
Hide file tree
Showing 2 changed files with 57 additions and 5 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,9 @@ import org.springframework.core.annotation.Order
import org.springframework.core.env.Environment
import org.springframework.http.HttpHeaders.ACCEPT_ENCODING
import org.springframework.http.HttpHeaders.CONTENT_ENCODING
import org.springframework.http.HttpStatus
import org.springframework.http.MediaType
import org.springframework.http.ProblemDetail
import org.springframework.http.converter.StringHttpMessageConverter
import org.springframework.stereotype.Component
import org.springframework.web.context.annotation.RequestScope
Expand Down Expand Up @@ -71,6 +73,25 @@ class CompressionFilter(val objectMapper: ObjectMapper, val requestCompression:
) {
val reReadableRequest = CachedBodyHttpServletRequest(request, objectMapper)

try {
validateCompressionProperty(reReadableRequest)
} catch (e: UnknownCompressionFormatException) {
response.status = HttpStatus.BAD_REQUEST.value()
response.contentType = MediaType.APPLICATION_JSON_VALUE
response.writer.write(
objectMapper.writeValueAsString(
LapisErrorResponse(
ProblemDetail.forStatus(HttpStatus.BAD_REQUEST).apply {
title = HttpStatus.BAD_REQUEST.reasonPhrase
detail = "Unknown compression format: ${e.unknownFormatValue}. " +
"Supported formats are: ${Compression.entries.joinToString { it.value }}"
},
),
),
)
return
}

val requestWithContentEncoding = HeaderModifyingRequestWrapper(
reReadableRequest = reReadableRequest,
headerName = ACCEPT_ENCODING,
Expand All @@ -91,6 +112,14 @@ class CompressionFilter(val objectMapper: ObjectMapper, val requestCompression:
maybeCompressingResponse.outputStream.close()
}

private fun validateCompressionProperty(reReadableRequest: CachedBodyHttpServletRequest) {
val compressionFormat = reReadableRequest.getStringField(COMPRESSION_PROPERTY) ?: return

if (Compression.entries.toSet().none { it.value == compressionFormat }) {
throw UnknownCompressionFormatException(unknownFormatValue = compressionFormat)
}
}

private fun createMaybeCompressingResponse(
response: HttpServletResponse,
acceptEncodingHeaders: Enumeration<String>?,
Expand All @@ -110,6 +139,8 @@ private fun computeAcceptEncodingValueFromRequest(reReadableRequest: CachedBodyH
else -> null
}

private class UnknownCompressionFormatException(val unknownFormatValue: String) : Exception()

class CompressingResponse(
response: HttpServletResponse,
compression: Compression,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,15 @@ package org.genspectrum.lapis.controller
import com.github.luben.zstd.ZstdInputStream
import com.ninjasquad.springmockk.MockkBean
import io.mockk.every
import org.genspectrum.lapis.controller.SampleRoute.AGGREGATED
import org.genspectrum.lapis.controller.SampleRoute.ALIGNED_AMINO_ACID_SEQUENCES
import org.genspectrum.lapis.controller.SampleRoute.ALIGNED_NUCLEOTIDE_SEQUENCES
import org.genspectrum.lapis.controller.SampleRoute.UNALIGNED_NUCLEOTIDE_SEQUENCES
import org.genspectrum.lapis.model.SiloQueryModel
import org.genspectrum.lapis.request.LapisInfo
import org.hamcrest.Matchers.containsString
import org.junit.jupiter.api.BeforeEach
import org.junit.jupiter.api.Test
import org.junit.jupiter.params.ParameterizedTest
import org.junit.jupiter.params.provider.MethodSource
import org.springframework.beans.factory.annotation.Autowired
Expand All @@ -20,6 +26,7 @@ import org.springframework.test.web.servlet.MockMvc
import org.springframework.test.web.servlet.request.MockHttpServletRequestBuilder
import org.springframework.test.web.servlet.result.MockMvcResultMatchers.content
import org.springframework.test.web.servlet.result.MockMvcResultMatchers.header
import org.springframework.test.web.servlet.result.MockMvcResultMatchers.jsonPath
import org.springframework.test.web.servlet.result.MockMvcResultMatchers.status
import java.util.zip.GZIPInputStream

Expand All @@ -39,6 +46,20 @@ class LapisControllerCompressionTest(
every { lapisInfo.dataVersion } returns "1234"
}

@Test
fun `WHEN I send a request with unknown compression format THEN should show an error`() {
val invalidCompressionFormat = "invalidCompressionFormat"
mockMvc.perform(
getSample("${AGGREGATED.pathSegment}?compression=$invalidCompressionFormat"),
)
.andExpect(status().isBadRequest)
.andExpect(
jsonPath("\$.error.detail")
.value(containsString("Unknown compression format: $invalidCompressionFormat")),
)
}


@ParameterizedTest(name = "{0}")
@MethodSource("getScenarios")
fun `endpoints return compressed data`(requestsScenario: RequestScenario) {
Expand Down Expand Up @@ -83,21 +104,21 @@ class LapisControllerCompressionTest(
)
} +
getRequests(
SampleRoute.AGGREGATED,
AGGREGATED,
dataFormat = MockDataCollection.DataFormat.NESTED_JSON,
compressionFormat = "gzip",
expectedContentType = APPLICATION_JSON_VALUE,
) +
getRequests(
SampleRoute.AGGREGATED,
AGGREGATED,
dataFormat = MockDataCollection.DataFormat.TSV,
compressionFormat = "zstd",
expectedContentType = "$TEXT_TSV_HEADER;charset=UTF-8",
) +
listOf(
"${SampleRoute.UNALIGNED_NUCLEOTIDE_SEQUENCES.pathSegment}/main",
"${SampleRoute.ALIGNED_NUCLEOTIDE_SEQUENCES.pathSegment}/main",
"${SampleRoute.ALIGNED_AMINO_ACID_SEQUENCES.pathSegment}/gene1",
"${UNALIGNED_NUCLEOTIDE_SEQUENCES.pathSegment}/main",
"${ALIGNED_NUCLEOTIDE_SEQUENCES.pathSegment}/main",
"${ALIGNED_AMINO_ACID_SEQUENCES.pathSegment}/gene1",
)
.flatMap { getFastaRequests(it, "gzip") + getFastaRequests(it, "zstd") }
}
Expand Down

0 comments on commit 4720332

Please sign in to comment.