mirror of
https://github.com/gotson/komga.git
synced 2025-12-22 00:13:30 +01:00
fix: handle query parameters with square brackets
because of https://github.com/flutterchina/dio/issues/799
This commit is contained in:
parent
f04674d6cd
commit
245dea906c
4 changed files with 343 additions and 0 deletions
|
|
@ -1,6 +1,24 @@
|
|||
package org.gotson.komga.infrastructure.language
|
||||
|
||||
import java.util.Enumeration
|
||||
import java.util.SortedMap
|
||||
|
||||
fun <T> List<T>.toIndexedMap(): SortedMap<Int, T> =
|
||||
mapIndexed { i, e -> i to e }.toMap().toSortedMap()
|
||||
|
||||
fun <T> List<T>.toEnumeration(): Enumeration<T> {
|
||||
return object : Enumeration<T> {
|
||||
var count = 0
|
||||
|
||||
override fun hasMoreElements(): Boolean {
|
||||
return this.count < size
|
||||
}
|
||||
|
||||
override fun nextElement(): T {
|
||||
if (this.count < size) {
|
||||
return get(this.count++)
|
||||
}
|
||||
throw NoSuchElementException("List enumeration asked for more elements than present")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,33 @@
|
|||
package org.gotson.komga.infrastructure.web
|
||||
|
||||
import org.springframework.boot.web.servlet.FilterRegistrationBean
|
||||
import org.springframework.context.annotation.Bean
|
||||
import org.springframework.context.annotation.Configuration
|
||||
import javax.servlet.Filter
|
||||
import javax.servlet.FilterChain
|
||||
import javax.servlet.ServletRequest
|
||||
import javax.servlet.ServletResponse
|
||||
import javax.servlet.http.HttpServletRequest
|
||||
|
||||
@Configuration
|
||||
class BracketParamsFilterConfiguration {
|
||||
@Bean
|
||||
fun bracketParamsFilter(): FilterRegistrationBean<BracketParamsFilter> =
|
||||
FilterRegistrationBean(BracketParamsFilter())
|
||||
.also {
|
||||
it.addUrlPatterns(
|
||||
"/api/*"
|
||||
)
|
||||
it.setName("queryParamsFilter")
|
||||
}
|
||||
|
||||
inner class BracketParamsFilter : Filter {
|
||||
override fun doFilter(request: ServletRequest?, response: ServletResponse?, chain: FilterChain?) {
|
||||
chain?.doFilter(BracketParamsRequestWrapper(request as HttpServletRequest), response)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
|
@ -0,0 +1,34 @@
|
|||
package org.gotson.komga.infrastructure.web
|
||||
|
||||
import org.gotson.komga.infrastructure.language.toEnumeration
|
||||
import java.util.Enumeration
|
||||
import javax.servlet.http.HttpServletRequest
|
||||
import javax.servlet.http.HttpServletRequestWrapper
|
||||
|
||||
class BracketParamsRequestWrapper(request: HttpServletRequest) : HttpServletRequestWrapper(request) {
|
||||
override fun getParameter(name: String): String? {
|
||||
val nameWithoutSuffix = name.removeSuffix("[]")
|
||||
val values = listOfNotNull(super.getParameter(nameWithoutSuffix), super.getParameter("$nameWithoutSuffix[]"))
|
||||
return if (values.isEmpty()) null
|
||||
else values.joinToString(",")
|
||||
}
|
||||
|
||||
override fun getParameterValues(name: String): Array<String>? {
|
||||
val nameWithoutSuffix = name.removeSuffix("[]")
|
||||
val regular = super.getParameterValues(nameWithoutSuffix)
|
||||
val suffix = super.getParameterValues("$nameWithoutSuffix[]")
|
||||
val values = listOfNotNull(regular, suffix)
|
||||
return if (values.isEmpty()) null
|
||||
else values.reduce { acc, strings -> acc + strings }
|
||||
}
|
||||
|
||||
override fun getParameterNames(): Enumeration<String> =
|
||||
super.getParameterNames().toList().map { it.removeSuffix("[]") }.distinct().toEnumeration()
|
||||
|
||||
override fun getParameterMap(): MutableMap<String, Array<String>> {
|
||||
return super.getParameterMap().asSequence()
|
||||
.groupBy({ it.key.removeSuffix("[]") }, { it.value })
|
||||
.mapValues { it.value.reduce { acc, strings -> acc + strings } }
|
||||
.toMutableMap()
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,258 @@
|
|||
package org.gotson.komga.infrastructure.web
|
||||
|
||||
import org.assertj.core.api.Assertions.assertThat
|
||||
import org.junit.jupiter.api.Nested
|
||||
import org.junit.jupiter.api.Test
|
||||
import org.springframework.mock.web.MockHttpServletRequest
|
||||
|
||||
class BracketParamsRequestWrapperTest {
|
||||
@Nested
|
||||
inner class ParameterNames {
|
||||
@Test
|
||||
fun `given parameters with and without brackets when getting parameter names then only the name without bracket is returned`() {
|
||||
// given
|
||||
val request = MockHttpServletRequest()
|
||||
request.setParameter("param")
|
||||
request.setParameter("param[]")
|
||||
|
||||
// when
|
||||
val filtered = BracketParamsRequestWrapper(request)
|
||||
|
||||
// then
|
||||
assertThat(filtered.parameterNames.toList()).containsExactlyInAnyOrder("param")
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `given parameters with brackets when getting parameter names then only the name without bracket is returned`() {
|
||||
// given
|
||||
val request = MockHttpServletRequest()
|
||||
request.setParameter("param[]")
|
||||
|
||||
// when
|
||||
val filtered = BracketParamsRequestWrapper(request)
|
||||
|
||||
// then
|
||||
assertThat(filtered.parameterNames.toList()).containsExactlyInAnyOrder("param")
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `given parameters without brackets when getting parameter names then only the name without bracket is returned`() {
|
||||
// given
|
||||
val request = MockHttpServletRequest()
|
||||
request.setParameter("param")
|
||||
|
||||
// when
|
||||
val filtered = BracketParamsRequestWrapper(request)
|
||||
|
||||
// then
|
||||
assertThat(filtered.parameterNames.toList()).containsExactlyInAnyOrder("param")
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `given empty parameters when getting parameter names then it is empty`() {
|
||||
// given
|
||||
val request = MockHttpServletRequest()
|
||||
|
||||
// when
|
||||
val filtered = BracketParamsRequestWrapper(request)
|
||||
|
||||
// then
|
||||
assertThat(filtered.parameterNames.toList()).isEmpty()
|
||||
}
|
||||
}
|
||||
|
||||
@Nested
|
||||
inner class ParameterValue {
|
||||
@Test
|
||||
fun `given parameters with and without brackets when getting parameter value then both values are joined to string`() {
|
||||
// given
|
||||
val request = MockHttpServletRequest()
|
||||
request.setParameter("param", "a")
|
||||
request.setParameter("param[]", "b")
|
||||
|
||||
// when
|
||||
val filtered = BracketParamsRequestWrapper(request)
|
||||
val value = filtered.getParameter("param")
|
||||
val valueBracket = filtered.getParameter("param[]")
|
||||
|
||||
// then
|
||||
assertThat(value).isEqualTo(valueBracket)
|
||||
assertThat(value).isEqualTo("a,b")
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `given parameters with brackets when getting parameter value single value is returned`() {
|
||||
// given
|
||||
val request = MockHttpServletRequest()
|
||||
request.setParameter("param[]", "b")
|
||||
|
||||
// when
|
||||
val filtered = BracketParamsRequestWrapper(request)
|
||||
val value = filtered.getParameter("param")
|
||||
val valueBracket = filtered.getParameter("param[]")
|
||||
|
||||
// then
|
||||
assertThat(value).isEqualTo(valueBracket)
|
||||
assertThat(value).isEqualTo("b")
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `given parameters without brackets when getting parameter value single value is returned`() {
|
||||
// given
|
||||
val request = MockHttpServletRequest()
|
||||
request.setParameter("param", "b")
|
||||
|
||||
// when
|
||||
val filtered = BracketParamsRequestWrapper(request)
|
||||
val value = filtered.getParameter("param")
|
||||
val valueBracket = filtered.getParameter("param[]")
|
||||
|
||||
// then
|
||||
assertThat(value).isEqualTo(valueBracket)
|
||||
assertThat(value).isEqualTo("b")
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `given empty parameters when getting parameter value then return null`() {
|
||||
// given
|
||||
val request = MockHttpServletRequest()
|
||||
|
||||
// when
|
||||
val filtered = BracketParamsRequestWrapper(request)
|
||||
val value = filtered.getParameter("param")
|
||||
|
||||
// then
|
||||
assertThat(value).isNull()
|
||||
}
|
||||
}
|
||||
|
||||
@Nested
|
||||
inner class ParameterValues {
|
||||
@Test
|
||||
fun `given parameters with and without brackets when getting parameter values then both values are returned`() {
|
||||
// given
|
||||
val request = MockHttpServletRequest()
|
||||
request.setParameter("param[]", "a")
|
||||
request.setParameter("param", "b")
|
||||
|
||||
// when
|
||||
val filtered = BracketParamsRequestWrapper(request)
|
||||
val values = filtered.getParameterValues("param")
|
||||
val valuesBracket = filtered.getParameterValues("param[]")
|
||||
|
||||
// then
|
||||
assertThat(values).isEqualTo(valuesBracket)
|
||||
assertThat(values).containsExactlyInAnyOrder("a", "b")
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `given parameters with brackets when getting parameter values then value is returned`() {
|
||||
// given
|
||||
val request = MockHttpServletRequest()
|
||||
request.setParameter("param[]", "a")
|
||||
|
||||
// when
|
||||
val filtered = BracketParamsRequestWrapper(request)
|
||||
val values = filtered.getParameterValues("param")
|
||||
val valuesBracket = filtered.getParameterValues("param[]")
|
||||
|
||||
// then
|
||||
assertThat(values).isEqualTo(valuesBracket)
|
||||
assertThat(values).containsExactlyInAnyOrder("a")
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `given parameters without brackets when getting parameter values then value is returned`() {
|
||||
// given
|
||||
val request = MockHttpServletRequest()
|
||||
request.setParameter("param", "a")
|
||||
|
||||
// when
|
||||
val filtered = BracketParamsRequestWrapper(request)
|
||||
val values = filtered.getParameterValues("param")
|
||||
val valuesBracket = filtered.getParameterValues("param[]")
|
||||
|
||||
// then
|
||||
assertThat(values).isEqualTo(valuesBracket)
|
||||
assertThat(values).containsExactlyInAnyOrder("a")
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `given empty parameters when getting parameter values then return null`() {
|
||||
// given
|
||||
val request = MockHttpServletRequest()
|
||||
|
||||
// when
|
||||
val filtered = BracketParamsRequestWrapper(request)
|
||||
val values = filtered.getParameterValues("param")
|
||||
|
||||
// then
|
||||
assertThat(values).isNull()
|
||||
}
|
||||
}
|
||||
|
||||
@Nested
|
||||
inner class ParameterMap {
|
||||
@Test
|
||||
fun `given parameters with and without brackets when getting parameter map then both values are returned`() {
|
||||
// given
|
||||
val request = MockHttpServletRequest()
|
||||
request.setParameter("param[]", "a")
|
||||
request.setParameter("param", "b")
|
||||
|
||||
// when
|
||||
val filtered = BracketParamsRequestWrapper(request)
|
||||
val map = filtered.parameterMap
|
||||
|
||||
// then
|
||||
assertThat(map.keys).hasSize(1)
|
||||
assertThat(map.keys).containsExactly("param")
|
||||
assertThat(map["param"]).containsExactlyInAnyOrder("a", "b")
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `given parameters with brackets when getting parameter map then key without bracket is returned`() {
|
||||
// given
|
||||
val request = MockHttpServletRequest()
|
||||
request.setParameter("param[]", "a")
|
||||
|
||||
// when
|
||||
val filtered = BracketParamsRequestWrapper(request)
|
||||
val map = filtered.parameterMap
|
||||
|
||||
// then
|
||||
assertThat(map.keys).hasSize(1)
|
||||
assertThat(map.keys).containsExactly("param")
|
||||
assertThat(map["param"]).containsExactlyInAnyOrder("a")
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `given parameters without brackets when getting parameter map then key without bracket is returned`() {
|
||||
// given
|
||||
val request = MockHttpServletRequest()
|
||||
request.setParameter("param", "a")
|
||||
|
||||
// when
|
||||
val filtered = BracketParamsRequestWrapper(request)
|
||||
val map = filtered.parameterMap
|
||||
|
||||
// then
|
||||
assertThat(map.keys).hasSize(1)
|
||||
assertThat(map.keys).containsExactly("param")
|
||||
assertThat(map["param"]).containsExactlyInAnyOrder("a")
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `given empty parameters when getting parameter map then empty map is returned`() {
|
||||
// given
|
||||
val request = MockHttpServletRequest()
|
||||
|
||||
// when
|
||||
val filtered = BracketParamsRequestWrapper(request)
|
||||
val map = filtered.parameterMap
|
||||
|
||||
// then
|
||||
assertThat(map).isEmpty()
|
||||
}
|
||||
}
|
||||
}
|
||||
Loading…
Reference in a new issue