package com.firefly.server.http2;
import com.codahale.metrics.Meter;
import com.firefly.codec.http2.stream.HTTPConnection;
import com.firefly.utils.function.Action1;
import com.firefly.utils.function.Action2;
import com.firefly.utils.function.Action3;
import com.firefly.utils.io.IO;
import com.firefly.utils.lang.AbstractLifeCycle;
public class SimpleHTTPServer extends AbstractLifeCycle {
private HTTP2Server http2Server;
private SimpleHTTPServerConfiguration configuration;
private Action1<SimpleRequest> headerComplete;
private Action3<Integer, String, SimpleRequest> badMessage;
private Action1<SimpleRequest> earlyEof;
private Action1<HTTPConnection> acceptConnection;
private Meter requestMeter;
Action2<SimpleRequest, HTTPServerConnection> tunnel;
public SimpleHTTPServer() {
this(new SimpleHTTPServerConfiguration());
}
public SimpleHTTPServer(SimpleHTTPServerConfiguration configuration) {
this.configuration = configuration;
requestMeter = this.configuration.getTcpConfiguration().getMetrics()
.meter("http2.SimpleHTTPServer.request.count");
}
public SimpleHTTPServer acceptHTTPTunnelConnection(Action2<SimpleRequest, HTTPServerConnection> tunnel) {
this.tunnel = tunnel;
return this;
}
public SimpleHTTPServer headerComplete(Action1<SimpleRequest> headerComplete) {
this.headerComplete = headerComplete;
return this;
}
public SimpleHTTPServer earlyEof(Action1<SimpleRequest> earlyEof) {
this.earlyEof = earlyEof;
return this;
}
public SimpleHTTPServer badMessage(Action3<Integer, String, SimpleRequest> badMessage) {
this.badMessage = badMessage;
return this;
}
public SimpleHTTPServer acceptConnection(Action1<HTTPConnection> acceptConnection) {
this.acceptConnection = acceptConnection;
return this;
}
public void listen(String host, int port) {
configuration.setHost(host);
configuration.setPort(port);
listen();
}
public void listen() {
start();
}
@Override
protected void init() {
http2Server = new HTTP2Server(configuration.getHost(), configuration.getPort(), configuration,
new ServerHTTPHandler.Adapter().acceptHTTPTunnelConnection((request, response, out, connection) -> {
SimpleRequest r = new SimpleRequest(request, response, out);
request.setAttachment(r);
if (tunnel != null) {
tunnel.call(r, connection);
}
return true;
}).headerComplete((request, response, out, connection) -> {
SimpleRequest r = new SimpleRequest(request, response, out);
request.setAttachment(r);
if (headerComplete != null) {
headerComplete.call(r);
}
requestMeter.mark();
return false;
}).content((buffer, request, response, out, connection) -> {
SimpleRequest r = (SimpleRequest) request.getAttachment();
if (r.content != null) {
r.content.call(buffer);
} else {
r.requestBody.add(buffer);
}
return false;
}).contentComplete((request, response, out, connection) -> {
SimpleRequest r = (SimpleRequest) request.getAttachment();
if (r.contentComplete != null) {
r.contentComplete.call(r);
}
return false;
}).messageComplete((request, response, out, connection) -> {
SimpleRequest r = (SimpleRequest) request.getAttachment();
if (r.messageComplete != null) {
r.messageComplete.call(r);
}
if (!r.getResponse().isAsynchronous()) {
IO.close(r.getResponse());
}
return true;
}).badMessage((status, reason, request, response, out, connection) -> {
if (badMessage != null) {
if (request.getAttachment() != null) {
SimpleRequest r = (SimpleRequest) request.getAttachment();
badMessage.call(status, reason, r);
} else {
SimpleRequest r = new SimpleRequest(request, response, out);
request.setAttachment(r);
badMessage.call(status, reason, r);
}
}
}).earlyEOF((request, response, out, connection) -> {
if (earlyEof != null) {
if (request.getAttachment() != null) {
SimpleRequest r = (SimpleRequest) request.getAttachment();
earlyEof.call(r);
} else {
SimpleRequest r = new SimpleRequest(request, response, out);
request.setAttachment(r);
earlyEof.call(r);
}
}
}));
http2Server.start();
}
@Override
protected void destroy() {
http2Server.stop();
}
}