@Test
    void testWorkingWithAnnotatedService() throws Exception {
        final WebClient client = client();

        for (final String path : new String[] { "post", "options" }) {
            final AggregatedHttpResponse response = preflightRequest(client, "/cors4/" + path,
                                                                     "http://example.com", "POST");
            assertThat(response.status()).isEqualTo(HttpStatus.OK);
            assertThat(response.headers().get(HttpHeaderNames.ACCESS_CONTROL_ALLOW_ORIGIN))
                    .isEqualTo("http://example.com");
            assertThat(response.headers().get(HttpHeaderNames.ACCESS_CONTROL_ALLOW_METHODS))
                    .isEqualTo("GET,POST");
        }
    }
/configured",
            allowedRequestMethods = HttpMethod.GET
    )
    private static class MyAnnotatedService2 {
        @Get("/configured")
        public void configured() {}

        @Get("/not_configured")
        public void notConfigured() {}
    }

    @CorsDecorator(
            origins = "http://example.com",
            allowedRequestMethods = HttpMethod.GET,
            allowAllRequestHeaders = true
    )
    private static class MyAnnotatedService3 {
        @Get("/index")
        @StatusCode(200)
        public void index() {}
    }

    @CorsDecorator(
            originRegexes = "http:\\/\\/example.*",
            allowedRequestMethods = HttpMethod.GET
    )
    private static class MyAnnotatedService4 {
        @Get("/index")
        @StatusCode(200)
        public void index() {}
    }

    @CorsDecorator(
            origins = "http://armeria.com",
            originRegexes = { "http:\\/\\/line.*", "http:\\/\\/test.*" },
            allowedRequestMethods = HttpMethod.GET
    )
    private static class MyAnnotatedService5 {
        @Get("/index")
        @StatusCode(200)
        public void index() {}
    }

    @RegisterExtension
    static final ServerExtension server = new ServerExtension() {
        @Override
        protected void configure(ServerBuilder sb) throws Exception {
            final HttpService myService = new AbstractHttpService() {
                @Override
                protected HttpResponse doGet(ServiceRequestContext ctx, HttpRequest req) {
                    return HttpResponse.of(HttpStatus.OK);
                }

                @Override
                protected HttpResponse doPost(ServiceRequestContext ctx, HttpRequest req) {
                    return HttpResponse.of(HttpStatus.OK);
                }

                @Override
                protected HttpResponse doHead(ServiceRequestContext ctx, HttpRequest req) {
                    return HttpResponse.of(HttpStatus.OK);
                }

                @Override
                protected HttpResponse doOptions(ServiceRequestContext ctx, HttpRequest req) {
                    return HttpResponse.of(HttpStatus.OK);
                }
            };
            sb.service("/cors", myService.decorate(
                    CorsService.builder("http://example.com")
                               .allowRequestMethods(HttpMethod.POST, HttpMethod.GET)
                               .allowRequestHeaders("allow_request_header")
                               .exposeHeaders("expose_header_1", "expose_header_2")
                               .preflightResponseHeader("x-preflight-cors", "Hello CORS")
                               .andForOrigins("http://example2.com")
                               .allowRequestMethods(HttpMethod.GET)
                               .allowRequestHeaders(HttpHeaderNames.of("allow_request_header2"))
                               .exposeHeaders(HttpHeaderNames.of("expose_header_3"),
                                              HttpHeaderNames.of("expose_header_4"))
                               .maxAge(3600)
                               .and()
                               .newDecorator()));
            // Support short circuit.
            sb.service("/cors2", myService.decorate(
                    CorsService.builder("http://example.com")
                               .shortCircuit()
                               .allowRequestMethods(HttpMethod.POST, HttpMethod.GET)
                               .allowRequestHeaders(HttpHeaderNames.of("allow_request_header"))
                               .exposeHeaders(HttpHeaderNames.of("expose_header_1"),
                                              HttpHeaderNames.of("expose_header_2"))
                               .preflightResponseHeader("x-preflight-cors", "Hello CORS", "Hello CORS2")
                               .maxAge(3600)
                               .andForOrigins("http://example2.com")
                               .allowNullOrigin()
                               .allowRequestMethods(HttpMethod.GET)
                               .allowRequestHeaders(HttpHeaderNames.of("allow_request_header2"))
                               .exposeHeaders(HttpHeaderNames.of("expose_header_3"),
                                              HttpHeaderNames.of("expose_header_4"))
                               .maxAge(1800)
                               .and()
                               .newDecorator()));
            sb.service("/cors3", myService.decorate(
                    CorsService.builderForAnyOrigin()
                               .allowRequestMethods(HttpMethod.POST, HttpMethod.GET)
                               .allowRequestHeaders("allow_request_header")
                               .exposeHeaders("expose_header_1", "expose_header_2")
                               .preflightResponseHeader("x-preflight-cors", "Hello CORS")
                               .maxAge(3600)
                               .newDecorator()));
            final Object myAnnotatedService = new Object() {
                // We don't need to specify '@Options` annotation here to support a CORS preflight request.
                @Post("/post")
                @StatusCode(200)
                public void post() {}

                @Options("/options")
                @StatusCode(200)
                public void options() {}
            };
            sb.annotatedService("/cors4", myAnnotatedService,
                                CorsService.builder("http://example.com")
                                           .allowRequestMethods(HttpMethod.POST, HttpMethod.GET)
                                           .newDecorator());
            // No CORS decorator.
            sb.annotatedService("/cors5", myAnnotatedService);

            sb.annotatedService("/cors6", new Object() {

                @Get("/any/get")
                @CorsDecorator(
                        origins = "*", exposedHeaders = { "expose_header_1", "expose_header_2" },
                        allowedRequestHeaders = { "allow_request_1", "allow_request_2" },
                        allowedRequestMethods = HttpMethod.GET, maxAge = 3600,
                        preflightRequestHeaders = {
                                @AdditionalHeader(name = "x-preflight-cors",
                                                  value = { "Hello CORS", "Hello CORS2" })
                        })
                public HttpResponse anyoneGet() {
                    return HttpResponse.of(HttpStatus.OK);
                }

                @Post("/one/post")
                @CorsDecorator(
                        origins = "http://example.com",
                        exposedHeaders = { "expose_header_1", "expose_header_2" },
                        allowedRequestMethods = HttpMethod.POST, credentialsAllowed = true,
                        allowedRequestHeaders = { "allow_request_1", "allow_request_2" }, maxAge = 1800,
                        preflightRequestHeaders = {
                                @AdditionalHeader(name = "x-preflight-cors", value = "Hello CORS")
                        })
                public HttpResponse onePolicyPost() {
                    return HttpResponse.of(HttpStatus.OK);
                }

                @Get("/multi/get")
                @CorsDecorator(origins = "http://example.com", exposedHeaders = "expose_header_1",
                               allowedRequestMethods = HttpMethod.GET, credentialsAllowed = true)
                @CorsDecorator(origins = "http://example2.com", exposedHeaders = "expose_header_2",
                               allowedRequestMethods = HttpMethod.GET, credentialsAllowed = true)
                public HttpResponse multiGet() {
                    return HttpResponse.of(HttpStatus.OK);
                }
            });

            sb.annotatedService("/cors7", new MyAnnotatedService());

            sb.annotatedService("/cors8", new Object() {
                @Get("/movies")
                public void titles() {}

                @Post("/movies/{title}")
                public void addMovie(@Param String title) {}

                @Get("/movies/{title}/actors")
                public void actors(@Param String title) {}
            }, CorsService.builder("http://example.com")
                          // Note that configuring mappings for specific paths first because the
                          // policies will be visited in the configured order.
                          .route("glob:/*
core/src/test/java/com/linecorp/armeria/server/cors/HttpServerCorsTest.java