Skip to content

Commit ee12d2b

Browse files
committed
feat: added allowed hosts, schemes, headers config
1 parent f06c137 commit ee12d2b

4 files changed

Lines changed: 89 additions & 29 deletions

File tree

src/main/kotlin/co/statu/parsek/config/ParsekConfig.kt

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,21 @@ data class ParsekConfig(
1111
) {
1212
companion object {
1313
data class RouterConfig(
14-
@SerializedName("api-prefix") var apiPrefix: String = "/api"
14+
@SerializedName("api-prefix") var apiPrefix: String = "/api",
15+
@SerializedName("allowed-hosts") var allowedHosts: Set<String> = setOf("localhost", "127.0.0.1", "0.0.0.0"),
16+
@SerializedName("allowed-schemes") var allowedSchemes: Set<String> = setOf("http", "https"),
17+
@SerializedName("allowed-headers") var allowedHeaders: Set<String> = setOf(
18+
"x-requested-with",
19+
"Access-Control-Allow-Origin",
20+
"origin",
21+
"Content-Type",
22+
"accept",
23+
"X-PINGARUNER",
24+
"x-csrf-token"
25+
),
26+
@SerializedName("allowed-methods") var allowedMethods: Set<String> = setOf(
27+
"GET", "POST", "OPTIONS", "DELETE", "PATCH", "PUT"
28+
)
1529
)
1630

1731
data class ServerConfig(
Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
package co.statu.parsek.config.migration
2+
3+
import co.statu.parsek.annotation.Migration
4+
import co.statu.parsek.config.ConfigMigration
5+
import io.vertx.core.json.JsonArray
6+
import io.vertx.core.json.JsonObject
7+
8+
@Migration
9+
class ConfigMigration3To4 : ConfigMigration(3, 4, "Add CORS configuration to router section") {
10+
override fun migrate(config: JsonObject) {
11+
val router = config.getJsonObject("router") ?: JsonObject().also { config.put("router", it) }
12+
13+
if (!router.containsKey("allowed-hosts")) {
14+
router.put("allowed-hosts", JsonArray(listOf("localhost", "127.0.0.1", "0.0.0.0")))
15+
}
16+
17+
if (!router.containsKey("allowed-schemes")) {
18+
router.put("allowed-schemes", JsonArray(listOf("http", "https")))
19+
}
20+
21+
if (!router.containsKey("allowed-headers")) {
22+
router.put(
23+
"allowed-headers", JsonArray(
24+
listOf(
25+
"x-requested-with",
26+
"Access-Control-Allow-Origin",
27+
"origin",
28+
"Content-Type",
29+
"accept",
30+
"X-PINGARUNER",
31+
"x-csrf-token"
32+
)
33+
)
34+
)
35+
}
36+
37+
if (!router.containsKey("allowed-methods")) {
38+
router.put(
39+
"allowed-methods", JsonArray(
40+
listOf(
41+
"GET", "POST", "OPTIONS", "DELETE", "PATCH", "PUT"
42+
)
43+
)
44+
)
45+
}
46+
}
47+
}

src/main/kotlin/co/statu/parsek/model/Route.kt

Lines changed: 19 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -16,49 +16,39 @@ abstract class Route {
1616

1717
abstract fun getHandler(): Handler<RoutingContext>
1818

19-
open val allowedSchemes = setOf("http", "https")
20-
open val allowedHosts = setOf("localhost", "127.0.0.1", "0.0.0.0")
21-
22-
open val allowedHeaders = setOf(
23-
"x-requested-with",
24-
"Access-Control-Allow-Origin",
25-
"origin",
26-
"Content-Type",
27-
"accept",
28-
"X-PINGARUNER",
29-
"x-csrf-token"
30-
)
31-
32-
open val allowedMethods = setOf<HttpMethod>(
33-
HttpMethod.GET,
34-
HttpMethod.POST,
35-
HttpMethod.OPTIONS,
36-
HttpMethod.DELETE,
37-
HttpMethod.PATCH,
38-
HttpMethod.PUT
39-
)
40-
41-
open fun corsHandler(): Handler<RoutingContext>? = Handler { ctx ->
19+
open val allowedSchemes: Set<String> = emptySet()
20+
open val allowedHosts: Set<String> = emptySet()
21+
22+
open val allowedHeaders: Set<String> = emptySet()
23+
24+
open val allowedMethods: Set<HttpMethod> = emptySet()
25+
26+
open fun corsHandler(
27+
hosts: Set<String> = allowedHosts,
28+
schemes: Set<String> = allowedSchemes,
29+
headers: Set<String> = allowedHeaders,
30+
methods: Set<HttpMethod> = allowedMethods
31+
): Handler<RoutingContext>? = Handler { ctx ->
4232
val origin = ctx.request().getHeader("Origin")
4333
if (origin != null) {
4434
try {
4535
val uri = URI(origin)
4636
// Check the scheme and host
47-
if (uri.scheme in allowedSchemes && uri.host in allowedHosts) {
37+
if (uri.scheme in schemes && uri.host in hosts) {
4838
// If the origin is allowed, add it to the response header
49-
ctx.response().putHeader("Access-Control-Allow-Origin", "*")
39+
ctx.response().putHeader("Access-Control-Allow-Origin", origin)
5040
}
5141
} catch (_: Exception) {
5242
// If the URI cannot be parsed, do not add any header.
5343
}
5444
}
5545

5646
// Add the allowed methods to the header:
57-
val methodsAsString = allowedMethods.joinToString(",") { it.name() }
47+
val methodsAsString = methods.joinToString(",") { it.name() }
5848
ctx.response().putHeader("Access-Control-Allow-Methods", methodsAsString)
5949

6050
// Add the allowed headers to the header:
61-
val headersAsString = allowedHeaders.joinToString(",")
51+
val headersAsString = headers.joinToString(",")
6252
ctx.response().putHeader("Access-Control-Allow-Headers", headersAsString)
6353

6454
// If it's a Preflight (OPTIONS) request, end the response immediately:
@@ -69,6 +59,8 @@ abstract class Route {
6959
}
7060
}
7161

62+
open fun corsHandler(): Handler<RoutingContext>? = corsHandler()
63+
7264
open fun bodyHandler(): Handler<RoutingContext>? = BodyHandler.create()
7365

7466
open fun getValidationHandler(schemaRepository: SchemaRepository): ValidationHandler? =

src/main/kotlin/co/statu/parsek/route/RouterProvider.kt

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ import co.statu.parsek.config.ConfigManager
1010
import co.statu.parsek.model.Api
1111
import co.statu.parsek.model.Route
1212
import io.vertx.core.Vertx
13+
import io.vertx.core.http.HttpMethod
1314
import io.vertx.ext.web.Router
1415
import io.vertx.ext.web.handler.SessionHandler
1516
import io.vertx.ext.web.sstore.LocalSessionStore
@@ -149,7 +150,13 @@ class RouterProvider private constructor(
149150
routedRoute.handler(bodyHandler)
150151
}
151152

152-
val corsHandler = route.corsHandler()
153+
val corsHandler = route.corsHandler(
154+
hosts = route.allowedHosts.takeIf { it.isNotEmpty() } ?: routerConfig.allowedHosts,
155+
schemes = route.allowedSchemes.takeIf { it.isNotEmpty() } ?: routerConfig.allowedSchemes,
156+
headers = route.allowedHeaders.takeIf { it.isNotEmpty() } ?: routerConfig.allowedHeaders,
157+
methods = (route.allowedMethods.takeIf { it.isNotEmpty() }?.map { it.name() }?.toSet()
158+
?: routerConfig.allowedMethods).map { HttpMethod.valueOf(it) }.toSet()
159+
)
153160

154161
if (corsHandler != null) {
155162
routedRoute.handler(corsHandler)

0 commit comments

Comments
 (0)