-
Notifications
You must be signed in to change notification settings - Fork 38
/
CorsServer.java
93 lines (75 loc) · 3.58 KB
/
CorsServer.java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
/*
* Copyright 2016 Lomig Mégard
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package ch.megard.akka.http.cors.javadsl;
import akka.actor.typed.ActorSystem;
import akka.actor.typed.javadsl.Behaviors;
import akka.http.javadsl.Http;
import akka.http.javadsl.ServerBinding;
import akka.http.javadsl.model.StatusCodes;
import akka.http.javadsl.server.ExceptionHandler;
import akka.http.javadsl.server.RejectionHandler;
import akka.http.javadsl.server.Route;
import java.util.NoSuchElementException;
import java.util.concurrent.CompletionStage;
import java.util.function.Function;
import java.util.function.Supplier;
import static akka.http.javadsl.server.Directives.*;
import static ch.megard.akka.http.cors.javadsl.CorsDirectives.cors;
import static ch.megard.akka.http.cors.javadsl.CorsDirectives.corsRejectionHandler;
/**
* Example of a Java HTTP server using the CORS directive.
*/
public class CorsServer {
public static void main(String[] args) throws Exception {
final ActorSystem<Void> system = ActorSystem.create(Behaviors.empty(), "cors-server");
final CorsServer app = new CorsServer();
final CompletionStage<ServerBinding> futureBinding =
Http.get(system).newServerAt("localhost", 8080).bind(app.createRoute());
futureBinding.whenComplete((binding, exception) -> {
if (binding != null) {
system.log().info("Server online at http://localhost:8080/\nPress RETURN to stop...");
} else {
system.log().error("Failed to bind HTTP endpoint, terminating system", exception);
system.terminate();
}
});
System.in.read(); // let it run until user presses return
futureBinding
.thenCompose(ServerBinding::unbind)
.thenAccept(unbound -> system.terminate());
}
private Route createRoute() {
// Your CORS settings are loaded from `application.conf`
// Your rejection handler
final RejectionHandler rejectionHandler = corsRejectionHandler().withFallback(RejectionHandler.defaultHandler());
// Your exception handler
final ExceptionHandler exceptionHandler = ExceptionHandler.newBuilder()
.match(NoSuchElementException.class, ex -> complete(StatusCodes.NOT_FOUND, ex.getMessage()))
.build();
// Combining the two handlers only for convenience
final Function<Supplier<Route>, Route> handleErrors = inner -> allOf(
s -> handleExceptions(exceptionHandler, s),
s -> handleRejections(rejectionHandler, s),
inner
);
// Note how rejections and exceptions are handled *before* the CORS directive (in the inner route).
// This is required to have the correct CORS headers in the response even when an error occurs.
return handleErrors.apply(() -> cors(() -> handleErrors.apply(() -> concat(
path("ping", () -> complete("pong")),
path("pong", () -> failWith(new NoSuchElementException("pong not found, try with ping")))
))));
}
}