nebius/SWE-rebench-V2-PRs huggingface dataset:
Repository: tipsy/javalin
Pull request #1054 (2020-09-01 22:11:29)

[javalinvue] Escape params


Patch:
diff --git a/javalin/src/main/java/io/javalin/plugin/rendering/vue/JavalinVue.kt b/javalin/src/main/java/io/javalin/plugin/rendering/vue/JavalinVue.kt
index 723eddb6..1ca23ae2 100644
--- a/javalin/src/main/java/io/javalin/plugin/rendering/vue/JavalinVue.kt
+++ b/javalin/src/main/java/io/javalin/plugin/rendering/vue/JavalinVue.kt
@@ -55,8 +55,8 @@ object JavalinVue {
 
     internal fun getState(ctx: Context, state: Any?) = "\n<script>\n" + """
         |    Vue.prototype.${"$"}javalin = {
-        |        pathParams: ${JavalinJson.toJson(ctx.pathParamMap())},
-        |        queryParams: ${JavalinJson.toJson(ctx.queryParamMap())},
+        |        pathParams: ${JavalinJson.toJson(ctx.pathParamMap().mapKeys { escape(it.key) }.mapValues { escape(it.value) })},
+        |        queryParams: ${JavalinJson.toJson(ctx.queryParamMap().mapKeys { escape(it.key) }.mapValues { it.value.map { escape(it) } })},
         |        state: ${JavalinJson.toJson(state ?: stateFunction(ctx))}
         |    }""".trimMargin() + "\n</script>\n"
 
@@ -103,3 +103,14 @@ object PathMaster {
 }
 
 fun Path.readText() = String(Files.readAllBytes(this))
+
+fun escape(string: String?) = string?.toCharArray()?.map {
+    when (it) {
+        '<' -> "&lt;"
+        '>' -> "&gt;"
+        '&' -> "&amp;"
+        '"' -> "&quot;"
+        '\'' -> "&#x27;"
+        else -> it
+    }
+}?.joinToString("")


Test patch:
diff --git a/javalin/src/test/java/io/javalin/TestJavalinVue.kt b/javalin/src/test/java/io/javalin/TestJavalinVue.kt
index a25add6d..ea695fae 100644
--- a/javalin/src/test/java/io/javalin/TestJavalinVue.kt
+++ b/javalin/src/test/java/io/javalin/TestJavalinVue.kt
@@ -76,6 +76,18 @@ class TestJavalinVue {
         assertThat(http.getBody("/unicode")).contains("<div>Test ÆØÅ</div>")
     }
 
+    @Test
+    fun `default params are escaped`() = TestUtil.test { app, http ->
+        val xss = "%3Cscript%3Ealert%281%29%3Cscript%3E"
+        app.get("/escaped", VueComponent("<test-component></test-component>"))
+        // keys
+        assertThat(http.getBody("/escaped?${xss}=value")).doesNotContain("<script>alert(1)<script>")
+        assertThat(http.getBody("/escaped?${xss}=value")).contains("&lt;script&gt;alert(1)&lt;script&gt;")
+        // values
+        assertThat(http.getBody("/escaped?key=${xss}")).doesNotContain("<script>alert(1)<script>")
+        assertThat(http.getBody("/escaped?key=${xss}")).contains("&lt;script&gt;alert(1)&lt;script&gt;")
+    }
+
     @Test
     fun `component shorthand works`() = TestUtil.test { app, http ->
         app.get("/shorthand", VueComponent("test-component"))
Repository: tipsy/javalin
Pull request #1147 (2021-01-15 14:45:47)

MicrometerPlugin registers connections after startup
This lets the micrometer plugin register the JettyConnectionMetrics after Javalin has started


Patch:
diff --git a/javalin/src/main/java/io/javalin/plugin/metrics/MicrometerPlugin.kt b/javalin/src/main/java/io/javalin/plugin/metrics/MicrometerPlugin.kt
index 9ea47798..465e6ef6 100644
--- a/javalin/src/main/java/io/javalin/plugin/metrics/MicrometerPlugin.kt
+++ b/javalin/src/main/java/io/javalin/plugin/metrics/MicrometerPlugin.kt
@@ -61,9 +61,12 @@ class MicrometerPlugin @JvmOverloads constructor(private val registry: MeterRegi
             }))
 
             JettyServerThreadPoolMetrics(server.threadPool, tags).bindTo(registry)
+            app.events {
+                it.serverStarted {
+                    JettyConnectionMetrics.addToAllConnectors(server, registry, tags)
+                }
+            }
         }
-
-        JettyConnectionMetrics(registry, tags)
     }
 
     companion object {


Test patch:
diff --git a/javalin/src/test/kotlin/io/javalin/plugin/metrics/MicrometerPluginTest.kt b/javalin/src/test/kotlin/io/javalin/plugin/metrics/MicrometerPluginTest.kt
new file mode 100644
index 00000000..c04548bf
--- /dev/null
+++ b/javalin/src/test/kotlin/io/javalin/plugin/metrics/MicrometerPluginTest.kt
@@ -0,0 +1,29 @@
+package io.javalin.plugin.metrics
+
+import io.javalin.Javalin
+import io.javalin.testing.TestUtil
+import io.micrometer.core.instrument.simple.SimpleMeterRegistry
+import org.assertj.core.api.Assertions.assertThat
+import org.assertj.core.api.Assertions.fail
+import org.junit.Test
+
+class MicrometerPluginTest {
+
+    @Test
+    fun `test that JettyConnectionMetrics is registered`() {
+        val registry = SimpleMeterRegistry()
+
+        TestUtil.test(Javalin.create { it.registerPlugin(MicrometerPlugin(registry)) }) { app, http ->
+            app.get("/test") { ctx -> ctx.json("Hello world") }
+            repeat(10) {
+                http.get("/test")
+            }
+        }
+
+        val maxConnectionGauge = registry.find("jetty.connections.max").gauge() ?: fail("\"jetty.connections.max\" not found")
+        assertThat(maxConnectionGauge.value()).isGreaterThan(0.0)
+
+        val messagesOutCounter = registry.find("jetty.connections.messages.out").counter() ?: fail("\"jetty.connections.messages.out\" not found")
+        assertThat(messagesOutCounter.count()).isGreaterThan(0.0)
+    }
+}
Repository: tipsy/javalin
Pull request #564 (2019-04-20 09:18:44)

Reset result stream after read


Patch:
diff --git a/src/main/java/io/javalin/http/Context.kt b/src/main/java/io/javalin/http/Context.kt
index e68cf77d..7dde9826 100644
--- a/src/main/java/io/javalin/http/Context.kt
+++ b/src/main/java/io/javalin/http/Context.kt
@@ -326,7 +326,7 @@ open class Context(@JvmField val req: HttpServletRequest, @JvmField val res: Htt
     fun result(resultString: String) = result(resultString.byteInputStream(responseCharset()))
 
     /** Gets the current context result as a [String] (if set). */
-    fun resultString() = resultStream?.apply { reset() }?.readBytes()?.toString(responseCharset())
+    fun resultString() = resultStream?.apply { reset() }?.readBytes()?.toString(responseCharset()).also { resultStream?.reset() }
 
     /**
      * Sets context result to the specified [InputStream].


Test patch:
diff --git a/src/test/java/io/javalin/TestResponse.kt b/src/test/java/io/javalin/TestResponse.kt
index 713bbe40..d195ec7b 100644
--- a/src/test/java/io/javalin/TestResponse.kt
+++ b/src/test/java/io/javalin/TestResponse.kt
@@ -119,4 +119,17 @@ class TestResponse {
         assertThat(http.get("/create-cookie").headers.getFirst(Header.SET_COOKIE)).contains("Max-Age=7")
     }
 
+    // Fix for https://github.com/tipsy/javalin/issues/543
+    @Test
+    fun `reading the result string resets the stream`() = TestUtil.test { app, http ->
+        val result = "Hello World"
+
+        app.get("/test") { context ->
+            context.result(result)
+            context.resultString()
+        }
+
+        assertThat(http.getBody("/test")).isEqualTo(result)
+    }
+
 }
Repository: tipsy/javalin
Pull request #926 (2020-04-13 07:54:39)

issue #925 CORS security flaw

tipsy: Thanks!

Patch:
diff --git a/javalin/src/main/java/io/javalin/http/util/CorsUtil.kt b/javalin/src/main/java/io/javalin/http/util/CorsUtil.kt
index 8e3e1b85..20248f32 100644
--- a/javalin/src/main/java/io/javalin/http/util/CorsUtil.kt
+++ b/javalin/src/main/java/io/javalin/http/util/CorsUtil.kt
@@ -14,7 +14,7 @@ import io.javalin.plugin.openapi.annotations.OpenApi
 class CorsBeforeHandler(private val origins: List<String>) : Handler {
     override fun handle(ctx: Context) {
         (ctx.header(Header.ORIGIN) ?: ctx.header(Header.REFERER))?.let { header ->
-            origins.map { it.removeSuffix("/") }.firstOrNull { it == "*" || header.startsWith(it) }?.let {
+            origins.map { it.removeSuffix("/") }.firstOrNull { it == "*" || header == it }?.let {
                 ctx.header(Header.ACCESS_CONTROL_ALLOW_ORIGIN, header)
                 ctx.header(Header.ACCESS_CONTROL_ALLOW_CREDENTIALS, "true")
             }


Test patch:
diff --git a/javalin/src/test/java/io/javalin/TestCors.kt b/javalin/src/test/java/io/javalin/TestCors.kt
index a8d63536..dbdac797 100644
--- a/javalin/src/test/java/io/javalin/TestCors.kt
+++ b/javalin/src/test/java/io/javalin/TestCors.kt
@@ -39,6 +39,16 @@ class TestCors {
         }
     }
 
+    @Test
+    fun `rejectCorsForInvalidOrigin reject where origin doesn't match`() {
+        val javalin = Javalin.create { it.enableCorsForOrigin("origin-1.com") }
+        TestUtil.test(javalin) { app, http ->
+            app.get("/") { ctx -> ctx.result("Hello") }
+            assertThat(Unirest.get(http.origin).header(ORIGIN, "origin-2.com").asString().headers[ACCESS_CONTROL_ALLOW_ORIGIN]).isNull()
+            assertThat(Unirest.get(http.origin).header(ORIGIN, "origin-1.com.au").asString().headers[ACCESS_CONTROL_ALLOW_ORIGIN]).isNull()
+        }
+    }
+
     @Test
     fun `enableCorsForAllOrigins enables cors for all origins`() {
         val javalin = Javalin.create { it.enableCorsForAllOrigins() }
Repository: tipsy/javalin
Pull request #1001 (2020-06-08 17:16:19)

Fix for properly decoding form param keys
Keys in x-www-form-urlencoded form params should also be %-decoded, according to specs


Patch:
diff --git a/javalin/src/main/java/io/javalin/http/util/ContextUtil.kt b/javalin/src/main/java/io/javalin/http/util/ContextUtil.kt
index 8cb12f54..447c1674 100644
--- a/javalin/src/main/java/io/javalin/http/util/ContextUtil.kt
+++ b/javalin/src/main/java/io/javalin/http/util/ContextUtil.kt
@@ -34,7 +34,7 @@ object ContextUtil {
 
     fun splitKeyValueStringAndGroupByKey(string: String, charset: String): Map<String, List<String>> {
         return if (string.isEmpty()) mapOf() else string.split("&").map { it.split("=", limit = 2) }.groupBy(
-                { it[0] },
+                { URLDecoder.decode(it[0], charset) },
                 { if (it.size > 1) URLDecoder.decode(it[1], charset) else "" }
         ).mapValues { it.value.toList() }
     }


Test patch:
diff --git a/javalin/src/test/java/io/javalin/TestBodyReading.kt b/javalin/src/test/java/io/javalin/TestBodyReading.kt
index 29fb84e3..367483ab 100644
--- a/javalin/src/test/java/io/javalin/TestBodyReading.kt
+++ b/javalin/src/test/java/io/javalin/TestBodyReading.kt
@@ -11,6 +11,8 @@ import io.javalin.testing.TestUtil
 import org.assertj.core.api.Assertions.assertThat
 import org.junit.Test
 import java.io.ByteArrayInputStream
+import java.net.URLEncoder
+import java.nio.charset.StandardCharsets
 
 class TestBodyReading {
 
@@ -75,9 +77,17 @@ class TestBodyReading {
                 ctx.result(formParamString)
             }
         }
-        val params = "a=1&a=2&a=3&b=1&b=2&c=1&d=&e&f=%28%23%29"
+        val params = "a=1" +      // single value
+                "&b=1&b=2&b=3" +  // multiple values
+                "&c=1=1" +        // value with '=' character
+                "&d=" +           // empty value
+                "&e" +            // also empty value
+                "&f=" + urlEncode("( # )") +   // %-encoded value with special chars
+                "&" + urlEncode("<g>") + "=g"  // %-encoded key with special chars
         val response = http.post("/body-reader?$params").body(params).asString()
-        assertThat(response.body).isEqualTo("a: 1, as: [1, 2, 3]. b: 1, bs: [1, 2]. c: 1, cs: [1]. d: , ds: []. e: , es: []. f: (#), fs: [(#)]")
+        assertThat(response.body).isEqualTo("a: 1, as: [1]. b: 1, bs: [1, 2, 3]. c: 1=1, cs: [1=1]. d: , ds: []. e: , es: []. f: ( # ), fs: [( # )]. <g>: g, <g>s: [g]")
     }
 
+    private fun urlEncode(text: String) = URLEncoder.encode(text, StandardCharsets.UTF_8.name())
+
 }
Repository: tipsy/javalin
Pull request #1265 (2021-06-01 14:32:37)

[context] Expose HandlerType in Context (#1264)
Backport of #1264


Patch:
diff --git a/javalin/src/main/java/io/javalin/http/Context.kt b/javalin/src/main/java/io/javalin/http/Context.kt
index 5ee01e6e..4b2df864 100644
--- a/javalin/src/main/java/io/javalin/http/Context.kt
+++ b/javalin/src/main/java/io/javalin/http/Context.kt
@@ -500,4 +500,7 @@ open class Context(@JvmField val req: HttpServletRequest, @JvmField val res: Htt
 
     /** Gets a list of all the [splat] values. */
     fun splats(): List<String> = Collections.unmodifiableList(splatList)
+
+    /** Gets the handler type of the current handler */
+    fun handlerType() : HandlerType = handlerType
 }


Test patch:
diff --git a/javalin/src/test/java/io/javalin/TestContextHandlerType.java b/javalin/src/test/java/io/javalin/TestContextHandlerType.java
new file mode 100644
index 00000000..d871d27e
--- /dev/null
+++ b/javalin/src/test/java/io/javalin/TestContextHandlerType.java
@@ -0,0 +1,30 @@
+/*
+ * Javalin - https://javalin.io
+ * Copyright 2021 David Åse
+ * Licensed under Apache 2.0: https://github.com/tipsy/javalin/blob/master/LICENSE
+ */
+package io.javalin;
+
+import io.javalin.http.HandlerType;
+import io.javalin.testing.TestUtil;
+import org.assertj.core.api.Assertions;
+import org.junit.Test;
+
+import java.util.ArrayList;
+import java.util.List;
+
+public class TestContextHandlerType {
+
+    @Test
+    public void testHandlerTypeCanBeAccessedInContext() {
+        TestUtil.test(Javalin.create(), (app, http) -> {
+            List<HandlerType> handlerTypes = new ArrayList<>();
+            app.before(ctx -> handlerTypes.add(ctx.handlerType()));
+            app.after(ctx -> handlerTypes.add(ctx.handlerType()));
+            app.get("/", ctx -> handlerTypes.add(ctx.handlerType()));
+
+            Assertions.assertThat(http.get("/").getStatus()).isEqualTo(200);
+            Assertions.assertThat(handlerTypes).containsExactly(HandlerType.BEFORE, HandlerType.GET, HandlerType.AFTER);
+        });
+    }
+}
Repository: tipsy/javalin
Pull request #1287 (2021-06-19 09:05:16)

Disable Default Server-header
#1284 : Disable Default Server Header 

tipsy: Thanks, this looks perfect @Gmugra! Could you add a test too?

Patch:
diff --git a/.gitignore b/.gitignore
index db834a63..f98b368e 100644
--- a/.gitignore
+++ b/.gitignore
@@ -10,3 +10,9 @@ buildNumber.properties
 
 .idea
 *.iml
+
+# ignore Eclipse specifics
+.classpath
+.settings
+.project
+.factorypath
diff --git a/javalin/src/main/java/io/javalin/core/JavalinServer.kt b/javalin/src/main/java/io/javalin/core/JavalinServer.kt
index cb05a380..3bcfb3fd 100644
--- a/javalin/src/main/java/io/javalin/core/JavalinServer.kt
+++ b/javalin/src/main/java/io/javalin/core/JavalinServer.kt
@@ -9,6 +9,7 @@ package io.javalin.core
 import io.javalin.core.util.JavalinLogger
 import io.javalin.websocket.JavalinWsServlet
 import org.eclipse.jetty.server.Handler
+import org.eclipse.jetty.server.HttpConnectionFactory
 import org.eclipse.jetty.server.Request
 import org.eclipse.jetty.server.Server
 import org.eclipse.jetty.server.ServerConnector
@@ -76,6 +77,11 @@ class JavalinServer(val config: JavalinConfig) {
     private fun defaultConnector(server: Server) = ServerConnector(server).apply {
         this.port = serverPort
         this.host = serverHost
+        this.getConnectionFactories().forEach {
+            if (it is HttpConnectionFactory) {
+                it.getHttpConfiguration().setSendServerVersion(false)
+            }
+        }
     }
 
     private fun defaultSessionHandler() = SessionHandler().apply { httpOnly = true }
diff --git a/javalin/src/main/java/io/javalin/http/JavalinServlet.kt b/javalin/src/main/java/io/javalin/http/JavalinServlet.kt
index 225d1682..2fd7b987 100644
--- a/javalin/src/main/java/io/javalin/http/JavalinServlet.kt
+++ b/javalin/src/main/java/io/javalin/http/JavalinServlet.kt
@@ -74,7 +74,6 @@ class JavalinServlet(val config: JavalinConfig) : HttpServlet() {
             }
 
             LogUtil.setup(ctx, matcher, config.inner.requestLogger != null) // start request lifecycle
-            ctx.header(Header.SERVER, "Javalin")
             ctx.contentType(config.defaultContentType)
             tryBeforeAndEndpointHandlers()
             if (ctx.resultFuture() == null) {


Test patch:
diff --git a/javalin/src/test/java/io/javalin/TestServerHeader.kt b/javalin/src/test/java/io/javalin/TestServerHeader.kt
new file mode 100644
index 00000000..e0842605
--- /dev/null
+++ b/javalin/src/test/java/io/javalin/TestServerHeader.kt
@@ -0,0 +1,16 @@
+package io.javalin
+
+import com.mashape.unirest.http.HttpMethod
+import io.javalin.testing.TestUtil
+import org.assertj.core.api.Assertions.assertThat
+import org.junit.Test
+
+class TestServerHeader {
+
+    @Test
+    fun `server header is not set by default`() = TestUtil.test { app, http ->
+        app.get("/hello") { ctx -> ctx.status(200).result("Hello world") }
+        val response = http.call(HttpMethod.GET, "/hello")
+        assertThat(response.headers.getFirst("Server")).isNull()
+    }
+}
\ No newline at end of file
Repository: tipsy/javalin
Pull request #1343 (2021-08-13 16:52:06)

GH-1340 Provide toString() implementation for HttpCode
* Associated with https://github.com/tipsy/javalin/issues/1340

tipsy: Thanks @dzikoysk !

Patch:
diff --git a/javalin/src/main/java/io/javalin/http/HttpCode.kt b/javalin/src/main/java/io/javalin/http/HttpCode.kt
index 254e38e5..de2c6561 100644
--- a/javalin/src/main/java/io/javalin/http/HttpCode.kt
+++ b/javalin/src/main/java/io/javalin/http/HttpCode.kt
@@ -60,6 +60,9 @@ enum class HttpCode(val status: Int, val message: String) {
     NOT_EXTENDED(510, "Not Extended"),
     NETWORK_AUTHENTICATION_REQUIRED(511, "Network Authentication Required");
 
+    override fun toString(): String =
+        "$status $message"
+
     companion object {
         fun forStatus(status: Int) = values().find { it.status == status }
     }


Test patch:
diff --git a/javalin/src/test/java/io/javalin/http/HttpCodeTest.kt b/javalin/src/test/java/io/javalin/http/HttpCodeTest.kt
index 390c3752..7b4d5899 100644
--- a/javalin/src/test/java/io/javalin/http/HttpCodeTest.kt
+++ b/javalin/src/test/java/io/javalin/http/HttpCodeTest.kt
@@ -19,4 +19,11 @@ class HttpCodeTest {
         assertThat(HttpCode.forStatus(542345)).isNull()
     }
 
+    @Test
+    fun `http code provides formatted implementation of toString() method`() {
+        HttpCode.values().forEach {
+            assertThat("${it.status} ${it.message}").isEqualTo(it.toString())
+        }
+    }
+
 }
Repository: tipsy/javalin
Pull request #1519 (2022-04-16 19:06:45)

[tests] Bump Unirest to 3.13.8
Related: ~ https://github.com/Kong/unirest-java/issues/439


Patch:
diff --git a/pom.xml b/pom.xml
index 20af947f..b8140561 100644
--- a/pom.xml
+++ b/pom.xml
@@ -115,7 +115,7 @@
         <bytebuddy.version>1.11.13</bytebuddy.version>
         <bytebuddyagent.version>1.11.13</bytebuddyagent.version>
         <okhttp.version>4.9.1</okhttp.version>
-        <unirest.version>3.13.6</unirest.version>
+        <unirest.version>3.13.8</unirest.version>
         <selenium.chrome.driver.version>4.1.3</selenium.chrome.driver.version>
         <webdrivermanager.version>5.1.0</webdrivermanager.version>
     </properties>


Test patch:
diff --git a/javalin/src/test/java/io/javalin/TestRouting.kt b/javalin/src/test/java/io/javalin/TestRouting.kt
index 82dbe579..5598d5b9 100644
--- a/javalin/src/test/java/io/javalin/TestRouting.kt
+++ b/javalin/src/test/java/io/javalin/TestRouting.kt
@@ -47,14 +47,14 @@ class TestRouting {
         app.options("/mapped", TestUtil.okHandler)
         app.addHandler(TRACE, "/mapped", TestUtil.okHandler)
 
-        for (httpMethod in http.allMethods()) {
+        for (httpMethod in HttpMethod.all()) {
             assertThat(http.call(httpMethod, "/mapped").status).isEqualTo(200)
         }
     }
 
     @Test
     fun `all unmapped verbs return 404`() = TestUtil.test { _, http ->
-        for (httpMethod in http.allMethods()) {
+        for (httpMethod in HttpMethod.all()) {
             assertThat(http.call(httpMethod, "/unmapped").status).isEqualTo(404)
         }
     }
diff --git a/javalin/src/test/java/io/javalin/testing/HttpUtil.kt b/javalin/src/test/java/io/javalin/testing/HttpUtil.kt
index aad33f6f..66486370 100644
--- a/javalin/src/test/java/io/javalin/testing/HttpUtil.kt
+++ b/javalin/src/test/java/io/javalin/testing/HttpUtil.kt
@@ -16,7 +16,6 @@ class HttpUtil(port: Int) {
     @JvmField
     val origin: String = "http://localhost:$port"
 
-    fun allMethods() = HttpMethod.GET.all() // TODO: Can be changed to HttpMethod.all() when https://github.com/Kong/unirest-java/issues/439 will be fixed
     fun enableUnirestRedirects() = Unirest.config().reset().followRedirects(true)
     fun disableUnirestRedirects() = Unirest.config().reset().followRedirects(false)