Configuring CORS
Table of contents
- Allowing any origin
- Allowing specific origins
- Applying different policies for different origins
- Applying a policy to the specific paths
- Configuring CORS via annotation
Armeria provides a way to configure Cross-origin resource sharing (CORS) policy for specific origins or
any origin via CorsServiceBuilder
. For more information about CORS,
visit Wikipedia's CORS page.
Allowing any origin
To configure CORS Service allowing any origin (*), use CorsService.builderForAnyOrigin()
, e.g.
import com.linecorp.armeria.common.HttpMethod;
import com.linecorp.armeria.server.HttpService;
import com.linecorp.armeria.server.ServerBuilder;
import com.linecorp.armeria.server.cors.CorsService;
HttpService myService = (ctx, req) -> ...;
Function<? super HttpService, CorsService> corsService =
CorsService.builderForAnyOrigin()
.allowCredentials()
.allowRequestMethods(HttpMethod.POST, HttpMethod.GET)
.allowRequestHeaders("allow_request_header")
.exposeHeaders("expose_header_1", "expose_header_2")
.preflightResponseHeader("x-preflight-cors", "Hello CORS")
.newDecorator();
ServerBuilder sb = Server.builder()
.service("/message", myService.decorate(corsService));
Allowing specific origins
To configure CORS Service allowing specific origins, use CorsService.builder()
, e.g.
HttpService myService = (ctx, req) -> ...;
Function<? super HttpService, CorsService> corsService =
CorsService.builder("http://example.com")
.allowCredentials()
.allowNullOrigin() // 'Origin: null' will be accepted.
.allowRequestMethods(HttpMethod.POST, HttpMethod.GET)
.allowRequestHeaders("allow_request_header")
.exposeHeaders("expose_header_1", "expose_header_2")
.preflightResponseHeader("x-preflight-cors", "Hello CORS")
.newDecorator();
ServerBuilder sb = Server.builder()
.service("/message", myService.decorate(corsService));
Applying different policies for different origins
To configure different policies for different groups of origins, use andForOrigins()
or andForOrigin()
method which creates a new ChainedCorsPolicyBuilder
with the specific origins.
Call and()
to return to CorsServiceBuilder
once you are done with building a policy, e.g.
HttpService myService = (ctx, req) -> ...;
Function<? super HttpService, CorsService> corsService =
CorsService.builder("http://example.com")
.allowCredentials()
.allowNullOrigin() // 'Origin: null' will be accepted.
.allowRequestMethods(HttpMethod.POST, HttpMethod.GET)
.allowRequestHeaders("allow_request_header")
.exposeHeaders("expose_header_1", "expose_header_2")
.preflightResponseHeader("x-preflight-cors", "Hello CORS")
.maxAge(3600)
.andForOrigins("http://example2.com")
.allowCredentials()
.allowRequestMethods(HttpMethod.GET)
.allowRequestHeaders("allow_request_header2")
.exposeHeaders("expose_header_3", "expose_header_4")
.and()
.newDecorator();
ServerBuilder sb = Server.builder()
.service("/message", myService.decorate(corsService));
You can also directly add a CorsPolicy
created by a CorsPolicyBuilder
, e.g.
import com.linecorp.armeria.server.cors.CorsPolicyBuilder;
HttpService myService = (ctx, req) -> ...;
Function<? super HttpService, CorsService> corsService =
CorsService.builder("http://example.com")
.allowCredentials()
.allowNullOrigin() // 'Origin: null' will be accepted.
.allowRequestMethods(HttpMethod.POST, HttpMethod.GET)
.allowRequestHeaders("allow_request_header")
.exposeHeaders("expose_header_1", "expose_header_2")
.preflightResponseHeader("x-preflight-cors", "Hello CORS")
.maxAge(3600)
.addPolicy(CorsPolicy.builder("http://example2.com")
.allowCredentials()
.allowRequestMethods(HttpMethod.GET)
.allowRequestHeaders("allow_request_header2")
.exposeHeaders("expose_header_3", "expose_header_4")
.build())
.newDecorator();
ServerBuilder sb = Server.builder()
.service("/message", myService.decorate(corsService));
Applying a policy to the specific paths
To configure a policy to the specific paths, you can use route()
methods in the
CorsServiceBuilder
and ChainedCorsPolicyBuilder
. They can help you to adjust the scope that
a policy is applied to, e.g.
HttpService myService = (ctx, req) -> ...;
Function<? super HttpService, CorsService> corsService =
CorsService.builder("http://example.com")
// CORS policy will be applied for the path that starts with '/message/web/api/'.
.route("prefix:/message/web/api/")
.allowRequestMethods(HttpMethod.POST, HttpMethod.GET)
.newDecorator();
ServerBuilder sb = Server.builder()
.service("/message", myService.decorate(corsService));
Configuring CORS via annotation
You can also configure CORS for Annotated services using the
@CorsDecorator
annotation, e.g.
import com.linecorp.armeria.server.annotation.AdditionalHeader;
import com.linecorp.armeria.server.annotation.Get;
import com.linecorp.armeria.server.annotation.decorator.CorsDecorator;
Object annotatedService = new Object() {
@Get("/get")
@CorsDecorator(origins = "http://example.com", credentialsAllowed = true,
nullOriginAllowed = true, exposedHeaders = "expose_header",
allowedRequestMethods = HttpMethod.GET, allowedRequestHeaders = "allow_header",
preflightResponseHeaders = {
@AdditionalHeader(name = "preflight_header", value = "preflight_value")
})
// In case you want to configure different CORS policies for different origins.
@CorsDecorator(origins = "http://example2.com", credentialsAllowed = true)
public HttpResponse get() {
return HttpResponse.of(HttpStatus.OK);
}
@Post("/post")
// In case you want to allow any origin (*):
@CorsDecorator(origins = "*", exposedHeaders = "expose_header")
// You can not add a policy after adding the decorator allowing any origin (*).
public HttpResponse post() {
return HttpResponse.of(HttpStatus.OK)
}
};
Server s = Server.builder()
.annotatedService("/example", annotatedService)
.build();
You can also use @CorsDecorator
at the class level to apply the decorator to all service methods in the class.
Note that the @CorsDecorator
annotation specified at the method level takes precedence over what's specified
at the class level:
// This decorator will be ignored for the path "/post".
@CorsDecorator(origins = "http://example.com", credentialsAllowed = true)
class MyAnnotatedService {
@Get("/get")
public HttpResponse get() {
return HttpResponse.of(HttpStatus.OK);
}
@Post("/post")
@CorsDecorator(origins = "http://example2.com", credentialsAllowed = true)
public HttpResponse post() {
return HttpResponse.of(HttpStatus.OK);
}
}
If you want to allow a CORS policy to the specific paths, you can use pathPatterns
property:
// This policy will be applied only to the paths matched by the pattern.
@CorsDecorator(origins = "http://example.com", pathPatterns = "glob:/**/web/api", credentialsAllowed = true)
class MyAnnotatedService {
...
}