Skip to content
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package io.kafbat.ui.config;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.HttpHeaders;
Expand All @@ -15,14 +16,17 @@
@Configuration
public class CorsGlobalConfiguration {

@Autowired
private CorsProperties corsProperties;

@Bean
public WebFilter corsFilter() {
return (final ServerWebExchange ctx, final WebFilterChain chain) -> {
final ServerHttpRequest request = ctx.getRequest();

final ServerHttpResponse response = ctx.getResponse();
final HttpHeaders headers = response.getHeaders();
fillCorsHeader(headers, request);
fillCorsHeader(headers);

if (request.getMethod() == HttpMethod.OPTIONS) {
response.setStatusCode(HttpStatus.OK);
Expand All @@ -33,11 +37,11 @@ public WebFilter corsFilter() {
};
}

public static void fillCorsHeader(HttpHeaders responseHeaders, ServerHttpRequest request) {
responseHeaders.add("Access-Control-Allow-Origin", request.getHeaders().getOrigin());
responseHeaders.add("Access-Control-Allow-Credentials", "true");
responseHeaders.add("Access-Control-Allow-Methods", "GET, PUT, POST, DELETE, OPTIONS");
responseHeaders.add("Access-Control-Max-Age", "3600");
responseHeaders.add("Access-Control-Allow-Headers", "Content-Type");
public void fillCorsHeader(HttpHeaders responseHeaders) {
responseHeaders.add("Access-Control-Allow-Origin", corsProperties.getAllowedOrigins());
responseHeaders.add("Access-Control-Allow-Credentials", corsProperties.getAllowCredentials());
responseHeaders.add("Access-Control-Allow-Methods", corsProperties.getAllowedMethods());
responseHeaders.add("Access-Control-Max-Age", corsProperties.getMaxAge());
responseHeaders.add("Access-Control-Allow-Headers", corsProperties.getAllowedHeaders());
}
}
18 changes: 18 additions & 0 deletions api/src/main/java/io/kafbat/ui/config/CorsProperties.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
package io.kafbat.ui.config;

import lombok.Data;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.stereotype.Component;

@Component
@ConfigurationProperties(prefix = "cors")
@Data
public class CorsProperties {

private String allowedOrigins;
private String allowedMethods;
private String allowedHeaders;
private String allowCredentials;
private String maxAge;

}
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
import java.util.function.Consumer;
import java.util.stream.Collectors;
import java.util.stream.Stream;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.web.WebProperties;
import org.springframework.boot.autoconfigure.web.reactive.error.AbstractErrorWebExceptionHandler;
import org.springframework.boot.web.reactive.error.ErrorAttributes;
Expand All @@ -38,6 +39,9 @@
@Order(Ordered.HIGHEST_PRECEDENCE)
public class GlobalErrorWebExceptionHandler extends AbstractErrorWebExceptionHandler {

@Autowired
private CorsGlobalConfiguration corsGlobalConfiguration;

public GlobalErrorWebExceptionHandler(ErrorAttributes errorAttributes,
ApplicationContext applicationContext,
ServerCodecConfigurer codecConfigurer) {
Expand Down Expand Up @@ -151,9 +155,7 @@ private String requestId(ServerRequest request) {
}

private Consumer<HttpHeaders> headers(ServerRequest request) {
return (HttpHeaders headers) -> {
CorsGlobalConfiguration.fillCorsHeader(headers, request.exchange().getRequest());
};
return corsGlobalConfiguration::fillCorsHeader;
}

private BigDecimal currentTimestamp() {
Expand Down
7 changes: 7 additions & 0 deletions api/src/main/resources/application.yml
Original file line number Diff line number Diff line change
Expand Up @@ -19,3 +19,10 @@ logging:
reactor.netty.http.server.AccessLog: INFO
org.hibernate.validator: WARN

cors:
allowed-origins: "*"
allowed-methods: "GET, PUT, POST, DELETE, OPTIONS"
allowed-headers: "Content-Type"
allow-credentials: "true"
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

* for allow-origin can not be used simultaneously with allow-credentials set to true. I suggest keeping the configuration as it is right now for backward compatibility and using the new approach if either of the properties (cors.*) is set (not null) or introducing even a new properly like (cors.enabled). What do you think?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think allowed-origins should be null by default and if it is null we could pass request.getHeaders().getOrigin(). This will keep backward compatibility.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@aditya-baldwa hi, could you address this please?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hi @Haarolean, yes, will check on it

max-age: "3600"

39 changes: 39 additions & 0 deletions contract/src/main/resources/swagger/kafbat-ui-api.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -4426,3 +4426,42 @@ components:
type: object
additionalProperties:
type: string
cors:
type: object
properties:
allowedOrigins:
type: array
items:
type: string
description: >-
List of allowed origins for CORS.
If not provided, defaults to allowing all origins (`*`)
default: ["*"]
allowedMethods:
type: array
items:
type: string
description: >-
List of allowed HTTP methods for CORS
If not provided, defaults to `GET, POST, PUT, DELETE, OPTIONS`.
default: ["GET", "POST", "PUT", "DELETE", "OPTIONS"]
allowedHeaders:
type: array
items:
type: string
description: >-
List of allowed HTTP headers for CORS.
If not provided, defaults to allowing all headers (`*`).
default: ["*"]
allowCredentials:
type: boolean
description: >-
Whether to allow credentials in CORS requests.
If not provided, defaults to `true`
default: true
maxAge:
type: integer
description: >-
Maximum age (in seconds) for CORS preflight requests.
If not provided, defaults to `3600` seconds.
default: 3600
Loading