Merge pull request #157 from Termina1/cors-options
Preflight request support and CORS-headers
This commit is contained in:
@@ -401,6 +401,14 @@ See <<tls>> section
|
|||||||
If set to `true` then Dshackle preserves _batch_ order based on request order.
|
If set to `true` then Dshackle preserves _batch_ order based on request order.
|
||||||
Note that latter is ineffective and use this option only when a client cannot reference responses by their IDs.
|
Note that latter is ineffective and use this option only when a client cannot reference responses by their IDs.
|
||||||
|
|
||||||
|
| `сors-origin`
|
||||||
|
|
|
||||||
|
| Access-Control-Allow-Origin contents. If empty the header will be omitted in response
|
||||||
|
|
||||||
|
| `cors-allowed-headers`
|
||||||
|
| `Content-Type`
|
||||||
|
| Access-Control-Allow-Headers contents. Takes effect only if сors-origi is present in config
|
||||||
|
|
||||||
| `routes`
|
| `routes`
|
||||||
|
|
|
|
||||||
a| Routing paths for Proxy.
|
a| Routing paths for Proxy.
|
||||||
|
|||||||
@@ -55,6 +55,16 @@ open class ProxyConfig {
|
|||||||
*/
|
*/
|
||||||
var preserveBatchOrder: Boolean = false
|
var preserveBatchOrder: Boolean = false
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Access-Control-Allow-Origin contents. If null then will omit this header completely
|
||||||
|
*/
|
||||||
|
var corsOrigin: String? = null
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Access-Control-Allow-Headers contents. Takes effect only if corsOrigin is not null
|
||||||
|
*/
|
||||||
|
var corsAllowedHeaders: String = "Content-Type"
|
||||||
|
|
||||||
class Route(
|
class Route(
|
||||||
/**
|
/**
|
||||||
* URL binding for the route. http://$host:$port/$id
|
* URL binding for the route. http://$host:$port/$id
|
||||||
|
|||||||
@@ -64,6 +64,12 @@ class ProxyConfigReader : YamlConfigReader(), ConfigReader<ProxyConfig> {
|
|||||||
getValueAsBool(input, "preserve-batch-order")?.let {
|
getValueAsBool(input, "preserve-batch-order")?.let {
|
||||||
config.preserveBatchOrder = it
|
config.preserveBatchOrder = it
|
||||||
}
|
}
|
||||||
|
getValueAsString(input, "cors-origin")?.let {
|
||||||
|
config.corsOrigin = it
|
||||||
|
}
|
||||||
|
getValueAsString(input, "cors-allowed-headers")?.let {
|
||||||
|
config.corsAllowedHeaders = it
|
||||||
|
}
|
||||||
val currentRoutes = HashSet<String>()
|
val currentRoutes = HashSet<String>()
|
||||||
getList<MappingNode>(input, "routes")?.let { routes ->
|
getList<MappingNode>(input, "routes")?.let { routes ->
|
||||||
config.routes = routes.value.map { route ->
|
config.routes = routes.value.map { route ->
|
||||||
|
|||||||
@@ -49,6 +49,19 @@ class HttpHandler(
|
|||||||
private val log = LoggerFactory.getLogger(HttpHandler::class.java)
|
private val log = LoggerFactory.getLogger(HttpHandler::class.java)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private fun addCorsHeadersIfSet(resp: HttpServerResponse): HttpServerResponse {
|
||||||
|
return config.corsOrigin?.let {
|
||||||
|
resp.addHeader(HttpHeaders.ACCESS_CONTROL_ALLOW_ORIGIN, it)
|
||||||
|
.addHeader(HttpHeaders.ACCESS_CONTROL_ALLOW_HEADERS, config.corsAllowedHeaders)
|
||||||
|
} ?: resp
|
||||||
|
}
|
||||||
|
|
||||||
|
fun preflight(): BiFunction<HttpServerRequest, HttpServerResponse, Publisher<Void>> {
|
||||||
|
return BiFunction { _, resp ->
|
||||||
|
addCorsHeadersIfSet(resp).send()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
fun proxy(routeConfig: ProxyConfig.Route): BiFunction<HttpServerRequest, HttpServerResponse, Publisher<Void>> {
|
fun proxy(routeConfig: ProxyConfig.Route): BiFunction<HttpServerRequest, HttpServerResponse, Publisher<Void>> {
|
||||||
return BiFunction { req, resp ->
|
return BiFunction { req, resp ->
|
||||||
// handle access events
|
// handle access events
|
||||||
@@ -59,7 +72,8 @@ class HttpHandler(
|
|||||||
val results = processRequest(routeConfig.blockchain, request, eventHandler)
|
val results = processRequest(routeConfig.blockchain, request, eventHandler)
|
||||||
// make sure that the access log handler is closed at the end, so it can render the logs
|
// make sure that the access log handler is closed at the end, so it can render the logs
|
||||||
.doFinally { eventHandler.close() }
|
.doFinally { eventHandler.close() }
|
||||||
resp.addHeader(HttpHeaders.CONTENT_TYPE, "application/json")
|
addCorsHeadersIfSet(resp)
|
||||||
|
.addHeader(HttpHeaders.CONTENT_TYPE, "application/json")
|
||||||
.send(results)
|
.send(results)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -114,6 +114,7 @@ class ProxyServer(
|
|||||||
config.routes.forEach { routeConfig ->
|
config.routes.forEach { routeConfig ->
|
||||||
// TODO implement a manual handling of the routes and WS upgrade to have a better control over the connection and improve the access logging
|
// TODO implement a manual handling of the routes and WS upgrade to have a better control over the connection and improve the access logging
|
||||||
routes.post("/" + routeConfig.id, httpHandler.proxy(routeConfig))
|
routes.post("/" + routeConfig.id, httpHandler.proxy(routeConfig))
|
||||||
|
routes.options("/" + routeConfig.id, httpHandler.preflight())
|
||||||
if (config.websocketEnabled && wsHandler != null) {
|
if (config.websocketEnabled && wsHandler != null) {
|
||||||
routes.ws("/" + routeConfig.id, wsHandler.proxy(routeConfig))
|
routes.ws("/" + routeConfig.id, wsHandler.proxy(routeConfig))
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -83,6 +83,8 @@ class ProxyConfigReaderSpec extends Specification {
|
|||||||
act.port == 8080
|
act.port == 8080
|
||||||
act.preserveBatchOrder
|
act.preserveBatchOrder
|
||||||
act.routes.size() == 2
|
act.routes.size() == 2
|
||||||
|
act.corsOrigin == "*"
|
||||||
|
act.corsAllowedHeaders == "Content-Type"
|
||||||
with(act.routes[0]) {
|
with(act.routes[0]) {
|
||||||
id == "ethereum"
|
id == "ethereum"
|
||||||
blockchain == Chain.ETHEREUM
|
blockchain == Chain.ETHEREUM
|
||||||
|
|||||||
@@ -31,6 +31,7 @@ class ProxyServerSpec extends Specification {
|
|||||||
|
|
||||||
then:
|
then:
|
||||||
1 * routes.post("/test", _)
|
1 * routes.post("/test", _)
|
||||||
|
1 * routes.options("/test", _)
|
||||||
1 * routes.ws("/test", _)
|
1 * routes.ws("/test", _)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -3,6 +3,8 @@ proxy:
|
|||||||
host: 0.0.0.0
|
host: 0.0.0.0
|
||||||
port: 8080
|
port: 8080
|
||||||
preserve-batch-order: true
|
preserve-batch-order: true
|
||||||
|
cors-origin: "*"
|
||||||
|
cors-allowed-headers: "Content-Type"
|
||||||
routes:
|
routes:
|
||||||
- id: ethereum
|
- id: ethereum
|
||||||
blockchain: ethereum
|
blockchain: ethereum
|
||||||
|
|||||||
Reference in New Issue
Block a user