fix module deps, simpler server API without exposing netty classes

This commit is contained in:
Jörg Prante 2021-04-23 22:29:14 +02:00
parent de0c798c45
commit 6680d54868
15 changed files with 78 additions and 56 deletions

View file

@ -1,6 +1,6 @@
group = org.xbib
name = netty-http
version = 4.1.63.0
version = 4.1.63.1
gradle.wrapper.version = 6.6.1
netty.version = 4.1.63.Final

View file

@ -38,7 +38,7 @@ artifacts {
}
tasks.withType(JavaCompile) {
options.compilerArgs << '-Xlint:all'
options.compilerArgs << '-Xlint:all,-exports'
}
javadoc {

View file

@ -11,8 +11,8 @@ module org.xbib.netty.http.client {
exports org.xbib.netty.http.client.pool;
exports org.xbib.netty.http.client.retry;
exports org.xbib.netty.http.client.transport;
requires org.xbib.netty.http.client.api;
requires org.xbib.netty.http.common;
requires transitive org.xbib.netty.http.client.api;
requires transitive org.xbib.netty.http.common;
requires org.xbib.net.url;
requires io.netty.handler.proxy;
requires java.logging;

View file

@ -5,5 +5,8 @@ module org.xbib.netty.http.server.api {
requires org.xbib.netty.http.common;
requires org.xbib.net.url;
requires io.netty.buffer;
requires io.netty.handler;
requires io.netty.transport;
requires io.netty.codec.http;
requires io.netty.codec.http2;
}

View file

@ -8,6 +8,7 @@ import org.xbib.net.URL;
import org.xbib.netty.http.common.HttpParameters;
import javax.net.ssl.SSLSession;
import java.net.InetSocketAddress;
import java.nio.charset.Charset;
import java.util.List;
import java.util.Map;
@ -31,6 +32,8 @@ public interface ServerRequest {
HttpHeaders getHeaders();
String getHeader(String name);
HttpParameters getParameters();
String getContextPath();
@ -45,6 +48,8 @@ public interface ServerRequest {
ByteBuf getContent();
String getContent(Charset charset);
ByteBufInputStream getInputStream();
SSLSession getSession();

View file

@ -2,7 +2,6 @@ package org.xbib.netty.http.server.api;
import io.netty.buffer.ByteBuf;
import io.netty.buffer.ByteBufOutputStream;
import io.netty.handler.codec.http.HttpResponseStatus;
import io.netty.handler.stream.ChunkedInput;
import org.xbib.netty.http.common.cookie.Cookie;
import java.io.Flushable;
@ -41,7 +40,7 @@ public interface ServerResponse extends Flushable {
interface Builder {
Builder setStatus(HttpResponseStatus httpResponseStatus);
Builder setStatus(int statusCode);
Builder setContentType(CharSequence contentType);

View file

@ -13,10 +13,15 @@ module org.xbib.netty.http.server {
exports org.xbib.netty.http.server.protocol.http1;
exports org.xbib.netty.http.server.protocol.http2;
exports org.xbib.netty.http.server.util;
requires org.xbib.netty.http.server.api;
requires org.xbib.netty.http.common;
requires transitive org.xbib.netty.http.server.api;
requires transitive org.xbib.netty.http.common;
requires org.xbib.net.url;
requires java.logging;
requires io.netty.buffer;
requires io.netty.common;
requires io.netty.handler;
requires io.netty.transport;
requires io.netty.codec.http;
requires io.netty.codec.http2;
provides org.xbib.netty.http.server.api.ServerProtocolProvider with Http1, Http2;
}

View file

@ -168,7 +168,7 @@ public class HttpServerDomain implements Domain<HttpEndpointResolver> {
}
} else {
if (serverResponseBuilder != null) {
serverResponseBuilder.setStatus(HttpResponseStatus.NOT_FOUND)
serverResponseBuilder.setStatus(HttpResponseStatus.NOT_FOUND.code())
.setContentType("text/plain;charset=utf-8")
.build().write("no endpoint found to match request");
}
@ -178,7 +178,7 @@ public class HttpServerDomain implements Domain<HttpEndpointResolver> {
@Override
public void handleAfterError(ServerRequest.Builder serverRequestBuilder, ServerResponse.Builder serverResponseBuilder, Throwable throwable) {
logger.log(Level.SEVERE, throwable.getMessage(), throwable);
serverResponseBuilder.setStatus(HttpResponseStatus.INTERNAL_SERVER_ERROR)
serverResponseBuilder.setStatus(HttpResponseStatus.INTERNAL_SERVER_ERROR.code())
.setContentType("text/plain;charset=utf-8")
.build().write(ExceptionFormatter.format(throwable));
}

View file

@ -129,11 +129,21 @@ public class HttpServerRequest implements ServerRequest {
return httpRequest.headers();
}
@Override
public String getHeader(String name) {
return httpRequest.headers().get(name);
}
@Override
public ByteBuf getContent() {
return httpRequest.content();
}
@Override
public String getContent(Charset charset) {
return httpRequest.content().toString(charset);
}
@Override
public ByteBufInputStream getInputStream() {
return new ByteBufInputStream(httpRequest.content(), true);

View file

@ -159,6 +159,10 @@ public final class Server implements AutoCloseable {
serverConfig.getAddress(), domainNameMapping));
}
public void loop() throws IOException, InterruptedException {
accept().channel().closeFuture().sync();
}
@Override
public void close() {
try {

View file

@ -6,7 +6,6 @@ import io.netty.handler.codec.http.HttpHeaders;
import io.netty.handler.codec.http.HttpMethod;
import io.netty.handler.codec.http.HttpResponseStatus;
import io.netty.handler.stream.ChunkedNioStream;
import io.netty.util.AsciiString;
import org.xbib.netty.http.common.util.DateTimeUtil;
import org.xbib.netty.http.server.api.Filter;
import org.xbib.netty.http.server.api.FilterConfig;
@ -41,9 +40,6 @@ public abstract class ResourceService implements Filter {
private static final Logger logger = Logger.getLogger(ResourceService.class.getName());
public void initialize(FilterConfig filterConfig) {
}
@Override
public void handle(ServerRequest serverRequest, ServerResponse serverResponse) throws IOException {
handleCachedResource(serverRequest, serverResponse, createResource(serverRequest, serverResponse));
@ -68,7 +64,7 @@ public abstract class ResourceService implements Filter {
// external redirect to
serverResponse.getBuilder()
.setHeader(HttpHeaderNames.LOCATION, resource.getResourcePath() + "/")
.setStatus( HttpResponseStatus.MOVED_PERMANENTLY)
.setStatus( HttpResponseStatus.MOVED_PERMANENTLY.code())
.build()
.flush();
return;
@ -76,14 +72,14 @@ public abstract class ResourceService implements Filter {
// external redirect to default index file in this directory
serverResponse.getBuilder()
.setHeader(HttpHeaderNames.LOCATION, resource.indexFileName())
.setStatus( HttpResponseStatus.MOVED_PERMANENTLY)
.setStatus( HttpResponseStatus.MOVED_PERMANENTLY.code())
.build()
.flush();
return;
} else {
// send forbidden, we do not allow directory access
serverResponse.getBuilder()
.setStatus(HttpResponseStatus.FORBIDDEN)
.setStatus(HttpResponseStatus.FORBIDDEN.code())
.build().flush();
return;
}
@ -95,7 +91,7 @@ public abstract class ResourceService implements Filter {
}
HttpHeaders headers = serverRequest.getHeaders();
String contentType = MimeTypeUtils.guessFromPath(resource.getResourcePath(), false);
long expirationMillis = System.currentTimeMillis() + 1000 * getMaxAgeSeconds();
long expirationMillis = System.currentTimeMillis() + 1000L * getMaxAgeSeconds();
if (isCacheResponseEnabled()) {
serverResponse.getBuilder()
.setHeader(HttpHeaderNames.EXPIRES, DateTimeUtil.formatRfc1123(expirationMillis))
@ -109,14 +105,14 @@ public abstract class ResourceService implements Filter {
if (ifUnmodifiedSinceInstant != null &&
ifUnmodifiedSinceInstant.plusMillis(1000L).isAfter(lastModifiedInstant)) {
serverResponse.getBuilder()
.setStatus(HttpResponseStatus.PRECONDITION_FAILED)
.setStatus(HttpResponseStatus.PRECONDITION_FAILED.code())
.build().flush();
return;
}
String ifMatch = headers.get(HttpHeaderNames.IF_MATCH);
if (ifMatch != null && !matches(ifMatch, eTag)) {
serverResponse.getBuilder()
.setStatus(HttpResponseStatus.PRECONDITION_FAILED)
.setStatus(HttpResponseStatus.PRECONDITION_FAILED.code())
.build().flush();
return;
}
@ -125,7 +121,7 @@ public abstract class ResourceService implements Filter {
serverResponse.getBuilder()
.setHeader(HttpHeaderNames.ETAG, eTag)
.setHeader(HttpHeaderNames.EXPIRES, DateTimeUtil.formatRfc1123(expirationMillis))
.setStatus(HttpResponseStatus.NOT_MODIFIED)
.setStatus(HttpResponseStatus.NOT_MODIFIED.code())
.build().flush();
return;
}
@ -135,7 +131,7 @@ public abstract class ResourceService implements Filter {
serverResponse.getBuilder()
.setHeader(HttpHeaderNames.ETAG, eTag)
.setHeader(HttpHeaderNames.EXPIRES, DateTimeUtil.formatRfc1123(expirationMillis))
.setStatus(HttpResponseStatus.NOT_MODIFIED)
.setStatus(HttpResponseStatus.NOT_MODIFIED.code())
.build().flush();
return;
}
@ -167,7 +163,7 @@ public abstract class ResourceService implements Filter {
if (!range.matches("^bytes=\\d*-\\d*(,\\d*-\\d*)*$")) {
serverResponse.getBuilder()
.setHeader(HttpHeaderNames.CONTENT_RANGE, "bytes */" + length)
.setStatus(HttpResponseStatus.REQUESTED_RANGE_NOT_SATISFIABLE)
.setStatus(HttpResponseStatus.REQUESTED_RANGE_NOT_SATISFIABLE.code())
.build().flush();
return;
}
@ -195,7 +191,7 @@ public abstract class ResourceService implements Filter {
if (start > end) {
serverResponse.getBuilder()
.setHeader(HttpHeaderNames.CONTENT_RANGE, "bytes */" + length)
.setStatus(HttpResponseStatus.REQUESTED_RANGE_NOT_SATISFIABLE)
.setStatus(HttpResponseStatus.REQUESTED_RANGE_NOT_SATISFIABLE.code())
.build().flush();
return;
}
@ -231,7 +227,7 @@ public abstract class ResourceService implements Filter {
}
}
serverResponse.getBuilder()
.setStatus(HttpResponseStatus.OK)
.setStatus(HttpResponseStatus.OK.code())
.setContentType(contentType)
.build()
.write(CharBuffer.wrap(sb), StandardCharsets.ISO_8859_1);
@ -253,11 +249,11 @@ public abstract class ResourceService implements Filter {
ServerRequest serverRequest, ServerResponse serverResponse) throws IOException {
if (url == null) {
serverResponse.getBuilder()
.setStatus( HttpResponseStatus.NOT_FOUND)
.setStatus( HttpResponseStatus.NOT_FOUND.code())
.build().flush();
} else if (serverRequest.getMethod() == HttpMethod.HEAD) {
serverResponse.getBuilder()
.setStatus( HttpResponseStatus.OK)
.setStatus( HttpResponseStatus.OK.code())
.setContentType(contentType)
.build().flush();
} else {
@ -267,7 +263,7 @@ public abstract class ResourceService implements Filter {
} catch (URISyntaxException | IOException e) {
logger.log(Level.SEVERE, e.getMessage(), e);
serverResponse.getBuilder()
.setStatus( HttpResponseStatus.NOT_FOUND)
.setStatus( HttpResponseStatus.NOT_FOUND.code())
.build().flush();
}
} else {
@ -276,7 +272,7 @@ public abstract class ResourceService implements Filter {
} catch (IOException e) {
logger.log(Level.SEVERE, e.getMessage(), e);
serverResponse.getBuilder()
.setStatus( HttpResponseStatus.NOT_FOUND)
.setStatus( HttpResponseStatus.NOT_FOUND.code())
.build().flush();
}
}
@ -287,11 +283,11 @@ public abstract class ResourceService implements Filter {
ServerRequest serverRequest, ServerResponse serverResponse, long offset, long size) throws IOException {
if (url == null) {
serverResponse.getBuilder()
.setStatus( HttpResponseStatus.NOT_FOUND)
.setStatus( HttpResponseStatus.NOT_FOUND.code())
.build().flush();
} else if (serverRequest.getMethod() == HttpMethod.HEAD) {
serverResponse.getBuilder()
.setStatus( HttpResponseStatus.OK)
.setStatus( HttpResponseStatus.OK.code())
.setContentType(contentType)
.build().flush();
} else {
@ -304,7 +300,7 @@ public abstract class ResourceService implements Filter {
} catch (URISyntaxException | IOException e) {
logger.log(Level.SEVERE, e.getMessage() + " path=" + path, e);
serverResponse.getBuilder()
.setStatus( HttpResponseStatus.NOT_FOUND)
.setStatus( HttpResponseStatus.NOT_FOUND.code())
.build().flush();
}
} else {
@ -313,7 +309,7 @@ public abstract class ResourceService implements Filter {
} catch (IOException e) {
logger.log(Level.SEVERE, e.getMessage(), e);
serverResponse.getBuilder()
.setStatus( HttpResponseStatus.NOT_FOUND)
.setStatus( HttpResponseStatus.NOT_FOUND.code())
.build().flush();
}
}
@ -329,7 +325,7 @@ public abstract class ResourceService implements Filter {
ServerResponse serverResponse, long offset, long size) throws IOException {
if (fileChannel == null) {
serverResponse.getBuilder()
.setStatus( HttpResponseStatus.NOT_FOUND)
.setStatus( HttpResponseStatus.NOT_FOUND.code())
.build().flush();
} else {
MappedByteBuffer mappedByteBuffer = null;
@ -338,12 +334,12 @@ public abstract class ResourceService implements Filter {
} catch (IOException e) {
// resource is not a file that can be mapped
serverResponse.getBuilder()
.setStatus(HttpResponseStatus.NOT_FOUND)
.setStatus(HttpResponseStatus.NOT_FOUND.code())
.build().flush();
}
if (mappedByteBuffer != null) {
serverResponse.getBuilder()
.setStatus(httpResponseStatus)
.setStatus(httpResponseStatus.code())
.setContentType(contentType)
.build()
.write(Unpooled.wrappedBuffer(mappedByteBuffer));
@ -355,12 +351,12 @@ public abstract class ResourceService implements Filter {
ServerResponse serverResponse) throws IOException {
if (inputStream == null) {
serverResponse.getBuilder()
.setStatus(HttpResponseStatus.NOT_FOUND)
.setStatus(HttpResponseStatus.NOT_FOUND.code())
.build().flush();
} else {
try (ReadableByteChannel channel = Channels.newChannel(inputStream)) {
serverResponse.getBuilder()
.setStatus(HttpResponseStatus.OK)
.setStatus(HttpResponseStatus.OK.code())
.setContentType(contentType)
.build()
.write(new ChunkedNioStream(channel));
@ -372,11 +368,11 @@ public abstract class ResourceService implements Filter {
ServerResponse serverResponse, long offset, long size) throws IOException {
if (inputStream == null) {
serverResponse.getBuilder()
.setStatus(HttpResponseStatus.NOT_FOUND)
.setStatus(HttpResponseStatus.NOT_FOUND.code())
.build().flush();
} else {
serverResponse.getBuilder()
.setStatus(httpResponseStatus)
.setStatus(httpResponseStatus.code())
.setContentType(contentType)
.build()
.write(Unpooled.wrappedBuffer(readBuffer(inputStream, offset, size)));

View file

@ -45,21 +45,21 @@ public class Http1Transport extends BaseTransport {
}
case MISSING_HOST_HEADER: {
HttpServerResponse.builder(ctx)
.setStatus(HttpResponseStatus.BAD_REQUEST)
.setStatus(HttpResponseStatus.BAD_REQUEST.code())
.setContentType("text/plain")
.build()
.write("missing 'Host' header");
}
case EXPECTATION_FAILED: {
HttpServerResponse.builder(ctx)
.setStatus(HttpResponseStatus.EXPECTATION_FAILED)
.setStatus(HttpResponseStatus.EXPECTATION_FAILED.code())
.build()
.flush();
break;
}
case UNSUPPORTED_HTTP_VERSION: {
HttpServerResponse.builder(ctx)
.setStatus(HttpResponseStatus.BAD_REQUEST)
.setStatus(HttpResponseStatus.BAD_REQUEST.code())
.setContentType("text/plain")
.build()
.write("unsupported HTTP version");

View file

@ -64,7 +64,7 @@ public class HttpServerResponse implements ServerResponse {
this.ctx = builder.ctx;
this.headers = builder.headers;
this.trailingHeaders = builder.trailingHeaders;
this.httpResponseStatus = builder.httpResponseStatus;
this.httpResponseStatus = HttpResponseStatus.valueOf(builder.statusCode);
this.shouldClose = builder.shouldClose;
this.shouldAddServerName = builder.shouldAddServerName;
this.sequenceId = builder.sequenceId;
@ -201,7 +201,7 @@ public class HttpServerResponse implements ServerResponse {
private final HttpHeaders trailingHeaders;
private HttpResponseStatus httpResponseStatus;
private int statusCode;
private boolean shouldClose;
@ -217,15 +217,15 @@ public class HttpServerResponse implements ServerResponse {
private Builder(ChannelHandlerContext ctx) {
this.ctx = ctx;
this.httpResponseStatus = HttpResponseStatus.OK;
this.statusCode = HttpResponseStatus.OK.code();
this.headers = new DefaultHttpHeaders();
this.trailingHeaders = new DefaultHttpHeaders();
this.contentType = HttpHeaderValues.APPLICATION_OCTET_STREAM;
}
@Override
public Builder setStatus(HttpResponseStatus httpResponseStatus) {
this.httpResponseStatus = httpResponseStatus;
public Builder setStatus(int statusCode) {
this.statusCode = statusCode;
return this;
}

View file

@ -62,7 +62,7 @@ public class Http2ServerResponse implements ServerResponse {
this.ctx = builder.ctx;
this.headers = builder.headers;
this.trailingHeaders = builder.trailingHeaders;
this.httpResponseStatus = builder.httpResponseStatus;
this.httpResponseStatus = HttpResponseStatus.valueOf(builder.statusCode);
this.shouldClose = builder.shouldClose;
this.shouldAddServerName = builder.shouldAddServerName;
this.sequenceId = builder.sequenceId;
@ -204,7 +204,7 @@ public class Http2ServerResponse implements ServerResponse {
private final Http2Headers trailingHeaders;
private HttpResponseStatus httpResponseStatus;
private int statusCode;
private boolean shouldClose;
@ -220,15 +220,15 @@ public class Http2ServerResponse implements ServerResponse {
private Builder(ChannelHandlerContext ctx) {
this.ctx = ctx;
this.httpResponseStatus = HttpResponseStatus.OK;
this.statusCode = HttpResponseStatus.OK.code();
this.headers = new DefaultHttp2Headers();
this.trailingHeaders = new DefaultHttp2Headers();
this.contentType = HttpHeaderValues.APPLICATION_OCTET_STREAM;
}
@Override
public Builder setStatus(HttpResponseStatus httpResponseStatus) {
this.httpResponseStatus = httpResponseStatus;
public Builder setStatus(int statusCode) {
this.statusCode = statusCode;
return this;
}

View file

@ -54,21 +54,21 @@ public class Http2Transport extends BaseTransport {
}
case MISSING_HOST_HEADER: {
serverResponseBuilder
.setStatus(HttpResponseStatus.BAD_REQUEST)
.setStatus(HttpResponseStatus.BAD_REQUEST.code())
.setContentType("text/plain")
.build()
.write("missing 'Host' header");
}
case EXPECTATION_FAILED: {
serverResponseBuilder
.setStatus(HttpResponseStatus.EXPECTATION_FAILED)
.setStatus(HttpResponseStatus.EXPECTATION_FAILED.code())
.build()
.flush();
break;
}
case UNSUPPORTED_HTTP_VERSION: {
serverResponseBuilder
.setStatus(HttpResponseStatus.BAD_REQUEST)
.setStatus(HttpResponseStatus.BAD_REQUEST.code())
.setContentType("text/plain")
.build()
.write("unsupported HTTP version");