mirror of
https://github.com/BlueMap-Minecraft/BlueMap.git
synced 2024-11-22 10:35:16 +01:00
Implement abillity to handle Http-Requests asyncrounously
This commit is contained in:
parent
22ed75c513
commit
1be7dd5746
@ -6,18 +6,28 @@
|
||||
import java.net.InetAddress;
|
||||
import java.net.InetSocketAddress;
|
||||
import java.net.SocketAddress;
|
||||
import java.nio.channels.Channel;
|
||||
import java.nio.channels.SelectableChannel;
|
||||
import java.nio.channels.SelectionKey;
|
||||
import java.nio.channels.SocketChannel;
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
import java.util.concurrent.Executor;
|
||||
|
||||
public class HttpConnection implements SelectionConsumer {
|
||||
|
||||
private final HttpRequestHandler requestHandler;
|
||||
private final Executor responseHandlerExecutor;
|
||||
private HttpRequest request;
|
||||
private CompletableFuture<HttpResponse> futureResponse;
|
||||
private HttpResponse response;
|
||||
|
||||
public HttpConnection(HttpRequestHandler requestHandler) {
|
||||
this(requestHandler, Runnable::run); //run synchronously
|
||||
}
|
||||
|
||||
public HttpConnection(HttpRequestHandler requestHandler, Executor responseHandlerExecutor) {
|
||||
this.requestHandler = requestHandler;
|
||||
this.responseHandlerExecutor = responseHandlerExecutor;
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -48,10 +58,22 @@ public void accept(SelectionKey selectionKey) {
|
||||
}
|
||||
|
||||
// process request
|
||||
if (response == null) {
|
||||
this.response = requestHandler.handle(request);
|
||||
if (futureResponse == null) {
|
||||
futureResponse = CompletableFuture.supplyAsync(
|
||||
() -> requestHandler.handle(request),
|
||||
responseHandlerExecutor
|
||||
);
|
||||
futureResponse.thenAccept(response -> {
|
||||
try {
|
||||
response.read(channel); // do an initial read to trigger response sending intent
|
||||
this.response = response;
|
||||
} catch (IOException e) {
|
||||
handleIOException(channel, e);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
if (response == null) return;
|
||||
if (!selectionKey.isValid()) return;
|
||||
|
||||
// send response
|
||||
@ -63,16 +85,24 @@ public void accept(SelectionKey selectionKey) {
|
||||
// reset to accept new request
|
||||
request.clear();
|
||||
response.close();
|
||||
futureResponse = null;
|
||||
response = null;
|
||||
selectionKey.interestOps(SelectionKey.OP_READ);
|
||||
|
||||
} catch (IOException e) {
|
||||
Logger.global.logDebug("Failed to process selection: " + e);
|
||||
try {
|
||||
channel.close();
|
||||
} catch (IOException e2) {
|
||||
Logger.global.logWarning("Failed to close channel" + e2);
|
||||
}
|
||||
handleIOException(channel, e);
|
||||
}
|
||||
}
|
||||
|
||||
private void handleIOException(Channel channel, IOException e) {
|
||||
request.clear();
|
||||
response = null;
|
||||
|
||||
Logger.global.logDebug("Failed to process selection: " + e);
|
||||
try {
|
||||
channel.close();
|
||||
} catch (IOException e2) {
|
||||
Logger.global.logWarning("Failed to close channel" + e2);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -57,7 +57,7 @@ public HttpResponse(HttpStatusCode statusCode) {
|
||||
this.headers = new HashMap<>();
|
||||
}
|
||||
|
||||
public boolean read(WritableByteChannel channel) throws IOException {
|
||||
public synchronized boolean read(WritableByteChannel channel) throws IOException {
|
||||
if (complete) return true;
|
||||
|
||||
// send headers
|
||||
|
@ -13,6 +13,10 @@ public HttpServer(HttpRequestHandler requestHandler) throws IOException {
|
||||
@Override
|
||||
public SelectionConsumer createConnectionHandler() {
|
||||
return new HttpConnection(requestHandler);
|
||||
|
||||
// Enable async request handling ...
|
||||
// TODO: maybe find a better/separate executor than using bluemap's common thread-pool
|
||||
//return new HttpConnection(requestHandler, BlueMap.THREAD_POOL);
|
||||
}
|
||||
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user