fix resolving endpoints, fix Unpooled.buffer(o) in flush, update to Netty 4.1.41
This commit is contained in:
parent
5c14695785
commit
833e502a7c
28 changed files with 931 additions and 357 deletions
|
@ -1,13 +1,13 @@
|
|||
group = org.xbib
|
||||
name = netty-http
|
||||
version = 4.1.39.2
|
||||
version = 4.1.41.0
|
||||
|
||||
# netty
|
||||
netty.version = 4.1.39.Final
|
||||
netty.version = 4.1.41.Final
|
||||
tcnative.version = 2.0.25.Final
|
||||
|
||||
# for netty-http-common
|
||||
xbib-net-url.version = 2.0.0
|
||||
xbib-net-url.version = 2.0.1
|
||||
|
||||
# for netty-http-server
|
||||
bouncycastle.version = 1.62
|
||||
|
|
|
@ -172,8 +172,8 @@ public class Request {
|
|||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "Request[url='" + url +
|
||||
"',version=" + httpVersion +
|
||||
return "Request[url=" + url +
|
||||
",version=" + httpVersion +
|
||||
",method=" + httpMethod +
|
||||
",headers=" + headers.entries() +
|
||||
",content=" + (content != null && content.readableBytes() >= 16 ?
|
||||
|
|
|
@ -102,7 +102,7 @@ abstract class BaseTransport implements Transport {
|
|||
flow.close();
|
||||
}
|
||||
channels.clear();
|
||||
requests.clear();
|
||||
// do not clear requests
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
package org.xbib.netty.http.client.test.htt2push;
|
||||
|
||||
import io.netty.handler.codec.http.HttpMethod;
|
||||
import org.junit.jupiter.api.Disabled;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.junit.jupiter.api.extension.ExtendWith;
|
||||
import org.xbib.netty.http.client.Client;
|
||||
|
@ -11,6 +12,7 @@ import java.io.IOException;
|
|||
import java.util.logging.Level;
|
||||
import java.util.logging.Logger;
|
||||
|
||||
@Disabled // /http2-push.io "connection refused"
|
||||
@ExtendWith(NettyHttpTestExtension.class)
|
||||
class Http2PushTest {
|
||||
|
||||
|
|
|
@ -0,0 +1,6 @@
|
|||
package org.xbib.netty.http.common;
|
||||
|
||||
public enum HttpMethod {
|
||||
|
||||
GET, HEAD, POST, PUT, DELETE, CONNECT, OPTIONS, TRACE, PATCH
|
||||
}
|
|
@ -1,4 +1,4 @@
|
|||
package org.xbib.netty.http.server.util;
|
||||
package org.xbib.netty.http.common.net;
|
||||
|
||||
/**
|
||||
* The network classes.
|
|
@ -1,4 +1,4 @@
|
|||
package org.xbib.netty.http.server.util;
|
||||
package org.xbib.netty.http.common.net;
|
||||
|
||||
/**
|
||||
* The TCP/IP network protocol versions.
|
|
@ -0,0 +1,39 @@
|
|||
package org.xbib.netty.http.common.util;
|
||||
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
import java.util.concurrent.Semaphore;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
@SuppressWarnings("serial")
|
||||
public class LimitedConcurrentHashMap<K, V> extends ConcurrentHashMap<K, V> {
|
||||
|
||||
private final Semaphore semaphore;
|
||||
|
||||
public LimitedConcurrentHashMap(int limit) {
|
||||
super(16, 0.75f);
|
||||
this.semaphore = new Semaphore(limit);
|
||||
}
|
||||
|
||||
@Override
|
||||
public V put(K key, V value) {
|
||||
try {
|
||||
if (semaphore.tryAcquire(1L, TimeUnit.SECONDS)) {
|
||||
return super.put(key, value);
|
||||
}
|
||||
} catch (InterruptedException e) {
|
||||
throw new IllegalArgumentException("size limit exceeded");
|
||||
}
|
||||
throw new IllegalArgumentException("size limit exceeded");
|
||||
}
|
||||
|
||||
@Override
|
||||
public V remove(Object key) {
|
||||
V v;
|
||||
try {
|
||||
v = super.remove(key);
|
||||
} finally {
|
||||
semaphore.release();
|
||||
}
|
||||
return v;
|
||||
}
|
||||
}
|
|
@ -3,11 +3,11 @@ package org.xbib.netty.http.common.util;
|
|||
import java.util.LinkedHashMap;
|
||||
|
||||
@SuppressWarnings("serial")
|
||||
public class LimitedMap<K, V> extends LinkedHashMap<K, V> {
|
||||
public class LimitedLinkedHashMap<K, V> extends LinkedHashMap<K, V> {
|
||||
|
||||
private final int limit;
|
||||
|
||||
public LimitedMap(int limit) {
|
||||
public LimitedLinkedHashMap(int limit) {
|
||||
super(16, 0.75f, true);
|
||||
this.limit = limit;
|
||||
}
|
|
@ -24,6 +24,7 @@ import java.util.Arrays;
|
|||
import java.util.Collections;
|
||||
import java.util.LinkedHashSet;
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
|
@ -99,10 +100,25 @@ public class Domain {
|
|||
return aliases;
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle server requests.
|
||||
* @param serverRequest the server request
|
||||
* @param serverResponse the server response
|
||||
* @throws IOException if handling server request fails
|
||||
*/
|
||||
public void handle(ServerRequest serverRequest, ServerResponse serverResponse) throws IOException {
|
||||
if (httpEndpointResolvers != null && !httpEndpointResolvers.isEmpty()) {
|
||||
if (httpEndpointResolvers != null) {
|
||||
boolean found = false;
|
||||
for (HttpEndpointResolver httpEndpointResolver : httpEndpointResolvers) {
|
||||
httpEndpointResolver.handle(serverRequest, serverResponse);
|
||||
List<HttpEndpoint> matchingEndpoints = httpEndpointResolver.matchingEndpointsFor(serverRequest);
|
||||
if (matchingEndpoints != null && !matchingEndpoints.isEmpty()) {
|
||||
httpEndpointResolver.handle(matchingEndpoints, serverRequest, serverResponse);
|
||||
found = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!found) {
|
||||
ServerResponse.write(serverResponse, HttpResponseStatus.NOT_IMPLEMENTED);
|
||||
}
|
||||
} else {
|
||||
ServerResponse.write(serverResponse, HttpResponseStatus.NOT_IMPLEMENTED);
|
||||
|
@ -143,6 +159,8 @@ public class Domain {
|
|||
private String keyPassword;
|
||||
|
||||
Builder(HttpAddress httpAddress, String serverName) {
|
||||
Objects.requireNonNull(httpAddress);
|
||||
Objects.requireNonNull(serverName);
|
||||
this.httpAddress = httpAddress;
|
||||
this.serverName = serverName;
|
||||
this.aliases = new LinkedHashSet<>();
|
||||
|
@ -154,31 +172,37 @@ public class Domain {
|
|||
}
|
||||
|
||||
public Builder setTrustManagerFactory(TrustManagerFactory trustManagerFactory) {
|
||||
Objects.requireNonNull(trustManagerFactory);
|
||||
this.trustManagerFactory = trustManagerFactory;
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder setTrustManagerKeyStore(KeyStore trustManagerKeyStore) {
|
||||
Objects.requireNonNull(trustManagerKeyStore);
|
||||
this.trustManagerKeyStore = trustManagerKeyStore;
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder setSslContextProvider(Provider sslContextProvider) {
|
||||
Objects.requireNonNull(sslContextProvider);
|
||||
this.sslContextProvider = sslContextProvider;
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder setSslProvider(SslProvider sslProvider) {
|
||||
Objects.requireNonNull(sslProvider);
|
||||
this.sslProvider = sslProvider;
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder setCiphers(Iterable<String> ciphers) {
|
||||
Objects.requireNonNull(ciphers);
|
||||
this.ciphers = ciphers;
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder setCipherSuiteFilter(CipherSuiteFilter cipherSuiteFilter) {
|
||||
Objects.requireNonNull(cipherSuiteFilter);
|
||||
this.cipherSuiteFilter = cipherSuiteFilter;
|
||||
return this;
|
||||
}
|
||||
|
@ -196,21 +220,26 @@ public class Domain {
|
|||
}
|
||||
|
||||
public Builder setKeyCertChainInputStream(InputStream keyCertChainInputStream) {
|
||||
Objects.requireNonNull(keyCertChainInputStream);
|
||||
this.keyCertChainInputStream = keyCertChainInputStream;
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder setKeyInputStream(InputStream keyInputStream) {
|
||||
Objects.requireNonNull(keyInputStream);
|
||||
this.keyInputStream = keyInputStream;
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder setKeyPassword(String keyPassword) {
|
||||
// null in keyPassword allowed, it means no password
|
||||
this.keyPassword = keyPassword;
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder setKeyCert(InputStream keyCertChainInputStream, InputStream keyInputStream) {
|
||||
Objects.requireNonNull(keyCertChainInputStream);
|
||||
Objects.requireNonNull(keyInputStream);
|
||||
setKeyCertChainInputStream(keyCertChainInputStream);
|
||||
setKeyInputStream(keyInputStream);
|
||||
return this;
|
||||
|
@ -218,6 +247,9 @@ public class Domain {
|
|||
|
||||
public Builder setKeyCert(InputStream keyCertChainInputStream, InputStream keyInputStream,
|
||||
String keyPassword) {
|
||||
Objects.requireNonNull(keyCertChainInputStream);
|
||||
Objects.requireNonNull(keyInputStream);
|
||||
Objects.requireNonNull(keyPassword);
|
||||
setKeyCertChainInputStream(keyCertChainInputStream);
|
||||
setKeyInputStream(keyInputStream);
|
||||
setKeyPassword(keyPassword);
|
||||
|
@ -239,31 +271,56 @@ public class Domain {
|
|||
* @return this builder
|
||||
*/
|
||||
public Builder addAlias(String alias) {
|
||||
Objects.requireNonNull(alias);
|
||||
aliases.add(alias);
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder addEndpointResolver(HttpEndpointResolver httpEndpointResolver) {
|
||||
Objects.requireNonNull(httpEndpointResolver);
|
||||
this.httpEndpointResolvers.add(httpEndpointResolver);
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder singleEndpoint(String path, Service service) {
|
||||
Objects.requireNonNull(path);
|
||||
Objects.requireNonNull(service);
|
||||
addEndpointResolver(HttpEndpointResolver.builder()
|
||||
.addEndpoint(HttpEndpoint.builder().setPath(path).addFilter(service).build()).build());
|
||||
.addEndpoint(HttpEndpoint.builder()
|
||||
.setPath(path)
|
||||
.build())
|
||||
.setDispatcher((endpoint, req, resp) -> service.handle(req, resp))
|
||||
.build());
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder singleEndpoint(String prefix, String path, Service service) {
|
||||
Objects.requireNonNull(prefix);
|
||||
Objects.requireNonNull(path);
|
||||
Objects.requireNonNull(service);
|
||||
addEndpointResolver(HttpEndpointResolver.builder()
|
||||
.addEndpoint(HttpEndpoint.builder().setPrefix(prefix).setPath(path).addFilter(service).build()).build());
|
||||
.addEndpoint(HttpEndpoint.builder()
|
||||
.setPrefix(prefix)
|
||||
.setPath(path)
|
||||
.build())
|
||||
.setDispatcher((endpoint, req, resp) -> service.handle(req, resp))
|
||||
.build());
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder singleEndpoint(String prefix, String path, Service service, String... methods) {
|
||||
public Builder singleEndpoint(String prefix, String path, Service service,
|
||||
String... methods) {
|
||||
Objects.requireNonNull(prefix);
|
||||
Objects.requireNonNull(path);
|
||||
Objects.requireNonNull(service);
|
||||
addEndpointResolver(HttpEndpointResolver.builder()
|
||||
.addEndpoint(HttpEndpoint.builder().setPrefix(prefix).setPath(path).addFilter(service)
|
||||
.setMethods(Arrays.asList(methods)).build()).build());
|
||||
.addEndpoint(HttpEndpoint.builder()
|
||||
.setPrefix(prefix)
|
||||
.setPath(path)
|
||||
.setMethods(Arrays.asList(methods))
|
||||
.build())
|
||||
.setDispatcher((endpoint, req, resp) -> service.handle(req, resp))
|
||||
.build());
|
||||
return this;
|
||||
}
|
||||
|
||||
|
|
|
@ -55,5 +55,4 @@ public interface ServerRequest {
|
|||
InetSocketAddress getLocalAddress();
|
||||
|
||||
InetSocketAddress getRemoteAddress();
|
||||
|
||||
}
|
||||
|
|
|
@ -4,33 +4,40 @@ import org.xbib.net.Pair;
|
|||
import org.xbib.net.QueryParameters;
|
||||
import org.xbib.net.path.PathMatcher;
|
||||
import org.xbib.net.path.PathNormalizer;
|
||||
import org.xbib.netty.http.common.HttpMethod;
|
||||
import org.xbib.netty.http.server.ServerRequest;
|
||||
import org.xbib.netty.http.server.ServerResponse;
|
||||
import org.xbib.netty.http.server.endpoint.service.Service;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Comparator;
|
||||
import java.util.EnumSet;
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
public class HttpEndpoint implements Endpoint<HttpEndpointDescriptor> {
|
||||
|
||||
private static final PathMatcher pathMatcher = new PathMatcher();
|
||||
public static final EnumSet<HttpMethod> DEFAULT_METHODS =
|
||||
EnumSet.of(HttpMethod.GET, HttpMethod.HEAD);
|
||||
|
||||
private static final List<String> DEFAULT_METHODS = Arrays.asList("GET", "HEAD");
|
||||
private static final PathMatcher pathMatcher = new PathMatcher();
|
||||
|
||||
private final String prefix;
|
||||
|
||||
private final String path;
|
||||
|
||||
private final List<String> methods;
|
||||
private final EnumSet<HttpMethod> methods;
|
||||
|
||||
private final List<String> contentTypes;
|
||||
|
||||
private final List<Service> filters;
|
||||
|
||||
private HttpEndpoint(String prefix, String path, List<String> methods, List<String> contentTypes, List<Service> filters) {
|
||||
private HttpEndpoint(String prefix, String path,
|
||||
EnumSet<HttpMethod> methods,
|
||||
List<String> contentTypes,
|
||||
List<Service> filters) {
|
||||
this.prefix = PathNormalizer.normalize(prefix);
|
||||
this.path = PathNormalizer.normalize(path);
|
||||
this.methods = methods;
|
||||
|
@ -80,6 +87,7 @@ public class HttpEndpoint implements Endpoint<HttpEndpointDescriptor> {
|
|||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void handle(ServerRequest serverRequest, ServerResponse serverResponse) throws IOException {
|
||||
serverRequest.setContext(pathMatcher.tokenizePath(getPrefix()));
|
||||
for (Service service : filters) {
|
||||
|
@ -92,7 +100,7 @@ public class HttpEndpoint implements Endpoint<HttpEndpointDescriptor> {
|
|||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "Endpoint[prefix=" + prefix + ",path=" + path + ",methods=" + methods + ",contentTypes=" + contentTypes + " --> " + filters +"]";
|
||||
return "Endpoint[prefix=" + prefix + ",path=" + path + ",methods=" + methods + ",contentTypes=" + contentTypes + ",filters=" + filters +"]";
|
||||
}
|
||||
|
||||
static class EndpointPathComparator implements Comparator<HttpEndpoint> {
|
||||
|
@ -115,7 +123,7 @@ public class HttpEndpoint implements Endpoint<HttpEndpointDescriptor> {
|
|||
|
||||
private String path;
|
||||
|
||||
private List<String> methods;
|
||||
private EnumSet<HttpMethod> methods;
|
||||
|
||||
private List<String> contentTypes;
|
||||
|
||||
|
@ -124,55 +132,62 @@ public class HttpEndpoint implements Endpoint<HttpEndpointDescriptor> {
|
|||
Builder() {
|
||||
this.prefix = "/";
|
||||
this.path = "/**";
|
||||
this.methods = new ArrayList<>();
|
||||
this.methods = DEFAULT_METHODS;
|
||||
this.contentTypes = new ArrayList<>();
|
||||
this.filters = new ArrayList<>();
|
||||
}
|
||||
|
||||
public Builder setPrefix(String prefix) {
|
||||
Objects.requireNonNull(prefix);
|
||||
this.prefix = prefix;
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder setPath(String path) {
|
||||
Objects.requireNonNull(path);
|
||||
this.path = path;
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder setMethods(List<String> methods) {
|
||||
public Builder setMethods(EnumSet<HttpMethod> methods) {
|
||||
Objects.requireNonNull(methods);
|
||||
this.methods = methods;
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder addMethod(String method) {
|
||||
methods.add(method);
|
||||
public Builder setMethods(List<String> methods) {
|
||||
Objects.requireNonNull(methods);
|
||||
this.methods = methods.stream()
|
||||
.map(HttpMethod::valueOf)
|
||||
.collect(Collectors.toCollection(() -> EnumSet.noneOf(HttpMethod.class)));
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder setContentTypes(List<String> contentTypes) {
|
||||
Objects.requireNonNull(contentTypes);
|
||||
this.contentTypes = contentTypes;
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder addContentType(String contentType) {
|
||||
Objects.requireNonNull(contentType);
|
||||
this.contentTypes.add(contentType);
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder setFilters(List<Service> filters) {
|
||||
Objects.requireNonNull(filters);
|
||||
this.filters = filters;
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder addFilter(Service filter) {
|
||||
Objects.requireNonNull(filter);
|
||||
this.filters.add(filter);
|
||||
return this;
|
||||
}
|
||||
|
||||
public HttpEndpoint build() {
|
||||
if (methods.isEmpty()) {
|
||||
methods = DEFAULT_METHODS;
|
||||
}
|
||||
return new HttpEndpoint(prefix, path, methods, contentTypes, filters);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
package org.xbib.netty.http.server.endpoint;
|
||||
|
||||
import org.xbib.netty.http.common.HttpMethod;
|
||||
import org.xbib.netty.http.server.transport.HttpServerRequest;
|
||||
|
||||
import static io.netty.handler.codec.http.HttpHeaderNames.CONTENT_TYPE;
|
||||
|
@ -8,13 +9,13 @@ public class HttpEndpointDescriptor implements EndpointDescriptor, Comparable<Ht
|
|||
|
||||
private final String path;
|
||||
|
||||
private final String method;
|
||||
private final HttpMethod method;
|
||||
|
||||
private final String contentType;
|
||||
|
||||
public HttpEndpointDescriptor(HttpServerRequest serverRequest) {
|
||||
this.path = extractPath(serverRequest.getRequestURI());
|
||||
this.method = serverRequest.getMethod().name();
|
||||
this.method = Enum.valueOf(HttpMethod.class, serverRequest.getMethod().name());
|
||||
this.contentType = serverRequest.getHeaders().get(CONTENT_TYPE);
|
||||
}
|
||||
|
||||
|
@ -22,7 +23,7 @@ public class HttpEndpointDescriptor implements EndpointDescriptor, Comparable<Ht
|
|||
return path;
|
||||
}
|
||||
|
||||
public String getMethod() {
|
||||
public HttpMethod getMethod() {
|
||||
return method;
|
||||
}
|
||||
|
||||
|
|
|
@ -1,7 +1,6 @@
|
|||
package org.xbib.netty.http.server.endpoint;
|
||||
|
||||
import io.netty.handler.codec.http.HttpResponseStatus;
|
||||
import org.xbib.netty.http.common.util.LimitedMap;
|
||||
import org.xbib.netty.http.common.util.LimitedConcurrentHashMap;
|
||||
import org.xbib.netty.http.server.ServerRequest;
|
||||
import org.xbib.netty.http.server.ServerResponse;
|
||||
import org.xbib.netty.http.server.annotation.Endpoint;
|
||||
|
@ -13,6 +12,7 @@ import java.util.ArrayList;
|
|||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
import java.util.logging.Level;
|
||||
import java.util.logging.Logger;
|
||||
import java.util.stream.Collectors;
|
||||
|
@ -21,60 +21,52 @@ public class HttpEndpointResolver {
|
|||
|
||||
private static final Logger logger = Logger.getLogger(HttpEndpointResolver.class.getName());
|
||||
|
||||
private final HttpEndpoint defaultEndpoint;
|
||||
private static final int DEFAULT_LIMIT = 1024;
|
||||
|
||||
private final List<HttpEndpoint> endpoints;
|
||||
|
||||
private final EndpointDispatcher endpointDispatcher;
|
||||
|
||||
private final LimitedMap<HttpEndpointDescriptor, List<HttpEndpoint>> endpointDescriptors;
|
||||
private final Map<HttpEndpointDescriptor, List<HttpEndpoint>> endpointDescriptors;
|
||||
|
||||
private HttpEndpointResolver(HttpEndpoint defaultEndpoint,
|
||||
List<HttpEndpoint> endpoints,
|
||||
private HttpEndpointResolver(List<HttpEndpoint> endpoints,
|
||||
EndpointDispatcher endpointDispatcher,
|
||||
int limit) {
|
||||
this.defaultEndpoint = defaultEndpoint == null ? createDefaultEndpoint() : defaultEndpoint;
|
||||
Objects.requireNonNull(endpointDispatcher);
|
||||
this.endpoints = endpoints;
|
||||
this.endpointDispatcher = endpointDispatcher;
|
||||
this.endpointDescriptors = new LimitedMap<>(limit);
|
||||
this.endpointDescriptors = new LimitedConcurrentHashMap<>(limit);
|
||||
}
|
||||
|
||||
public void handle(ServerRequest serverRequest, ServerResponse serverResponse) throws IOException {
|
||||
/**
|
||||
* Find matching endpoints for a server request.
|
||||
* @param serverRequest the server request
|
||||
* @return a
|
||||
*/
|
||||
public List<HttpEndpoint> matchingEndpointsFor(ServerRequest serverRequest) {
|
||||
HttpEndpointDescriptor httpEndpointDescriptor = serverRequest.getEndpointDescriptor();
|
||||
endpointDescriptors.putIfAbsent(httpEndpointDescriptor, endpoints.stream()
|
||||
.filter(endpoint -> endpoint.matches(httpEndpointDescriptor))
|
||||
.sorted(new HttpEndpoint.EndpointPathComparator(httpEndpointDescriptor.getPath()))
|
||||
.collect(Collectors.toList()));
|
||||
List<HttpEndpoint> matchingEndpoints = endpointDescriptors.get(httpEndpointDescriptor);
|
||||
return endpointDescriptors.get(httpEndpointDescriptor);
|
||||
}
|
||||
|
||||
public void handle(List<HttpEndpoint> matchingEndpoints,
|
||||
ServerRequest serverRequest, ServerResponse serverResponse) throws IOException {
|
||||
Objects.requireNonNull(matchingEndpoints);
|
||||
if (logger.isLoggable(Level.FINE)) {
|
||||
logger.log(Level.FINE, () -> "endpoint = " + httpEndpointDescriptor +
|
||||
" matching endpoints = " + matchingEndpoints);
|
||||
logger.log(Level.FINE, () ->
|
||||
"endpoint = " + serverRequest.getEndpointDescriptor() +
|
||||
" matching endpoints = " + matchingEndpoints.size() + " --> " + matchingEndpoints);
|
||||
}
|
||||
if (matchingEndpoints.isEmpty()) {
|
||||
if (defaultEndpoint != null) {
|
||||
defaultEndpoint.resolveUriTemplate(serverRequest);
|
||||
defaultEndpoint.handle(serverRequest, serverResponse);
|
||||
if (endpointDispatcher != null) {
|
||||
endpointDispatcher.dispatch(defaultEndpoint, serverRequest, serverResponse);
|
||||
}
|
||||
} else {
|
||||
ServerResponse.write(serverResponse, HttpResponseStatus.NOT_IMPLEMENTED);
|
||||
}
|
||||
} else {
|
||||
for (HttpEndpoint endpoint : matchingEndpoints) {
|
||||
endpoint.resolveUriTemplate(serverRequest);
|
||||
endpoint.handle(serverRequest, serverResponse);
|
||||
if (serverResponse.getStatus() != null) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (endpointDispatcher != null) {
|
||||
for (HttpEndpoint endpoint : matchingEndpoints) {
|
||||
endpointDispatcher.dispatch(endpoint, serverRequest, serverResponse);
|
||||
if (serverResponse.getStatus() != null) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
for (HttpEndpoint endpoint : matchingEndpoints) {
|
||||
endpoint.resolveUriTemplate(serverRequest);
|
||||
endpoint.handle(serverRequest, serverResponse);
|
||||
endpointDispatcher.dispatch(endpoint, serverRequest, serverResponse);
|
||||
if (serverResponse.getStatus() != null) {
|
||||
logger.log(Level.FINEST, () -> "endpoint " + endpoint + " status = " + serverResponse.getStatus());
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -83,17 +75,6 @@ public class HttpEndpointResolver {
|
|||
return endpointDescriptors;
|
||||
}
|
||||
|
||||
private HttpEndpoint createDefaultEndpoint() {
|
||||
return HttpEndpoint.builder()
|
||||
.setPath("/**")
|
||||
.addMethod("GET")
|
||||
.addMethod("HEAD")
|
||||
.addFilter((req, resp) -> {
|
||||
ServerResponse.write(resp, HttpResponseStatus.NOT_FOUND,
|
||||
"application/octet-stream","no endpoint configured");
|
||||
}).build();
|
||||
}
|
||||
|
||||
public static Builder builder() {
|
||||
return new Builder();
|
||||
}
|
||||
|
@ -104,32 +85,26 @@ public class HttpEndpointResolver {
|
|||
|
||||
private String prefix;
|
||||
|
||||
private HttpEndpoint defaultEndpoint;
|
||||
|
||||
private List<HttpEndpoint> endpoints;
|
||||
|
||||
private EndpointDispatcher endpointDispatcher;
|
||||
|
||||
Builder() {
|
||||
this.limit = 1024;
|
||||
this.limit = DEFAULT_LIMIT;
|
||||
this.endpoints = new ArrayList<>();
|
||||
}
|
||||
|
||||
public Builder setLimit(int limit) {
|
||||
this.limit = limit;
|
||||
this.limit = limit > 0 ? limit < 1024 * DEFAULT_LIMIT ? limit : DEFAULT_LIMIT : DEFAULT_LIMIT;
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder setPrefix(String prefix) {
|
||||
Objects.requireNonNull(prefix);
|
||||
this.prefix = prefix;
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder setDefaultEndpoint(HttpEndpoint endpoint) {
|
||||
this.defaultEndpoint = endpoint;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add endpoint.
|
||||
*
|
||||
|
@ -137,12 +112,19 @@ public class HttpEndpointResolver {
|
|||
* @return this builder
|
||||
*/
|
||||
public Builder addEndpoint(HttpEndpoint endpoint) {
|
||||
if (endpoint.getPrefix().equals("/") && prefix != null && !prefix.isEmpty()) {
|
||||
HttpEndpoint thisEndpoint = HttpEndpoint.builder(endpoint).setPrefix(prefix).build();
|
||||
logger.log(Level.FINE, "adding endpoint = " + thisEndpoint);
|
||||
endpoints.add(thisEndpoint);
|
||||
Objects.requireNonNull(endpoint);
|
||||
if (prefix != null && !prefix.isEmpty()) {
|
||||
HttpEndpoint prefixedEndpoint = HttpEndpoint.builder(endpoint)
|
||||
.setPrefix(prefix + endpoint.getPrefix())
|
||||
.build();
|
||||
if (logger.isLoggable(Level.FINE)) {
|
||||
logger.log(Level.FINE, () -> "prefix " + prefix + ": adding endpoint = " + prefixedEndpoint);
|
||||
}
|
||||
endpoints.add(prefixedEndpoint);
|
||||
} else {
|
||||
logger.log(Level.FINE, "adding endpoint = " + endpoint);
|
||||
if (logger.isLoggable(Level.FINE)) {
|
||||
logger.log(Level.FINE, () -> "adding endpoint = " + endpoint);
|
||||
}
|
||||
endpoints.add(endpoint);
|
||||
}
|
||||
return this;
|
||||
|
@ -155,6 +137,7 @@ public class HttpEndpointResolver {
|
|||
* @return this builder
|
||||
*/
|
||||
public Builder addEndpoint(Object classWithAnnotatedMethods) {
|
||||
Objects.requireNonNull(classWithAnnotatedMethods);
|
||||
for (Class<?> clazz = classWithAnnotatedMethods.getClass(); clazz != null; clazz = clazz.getSuperclass()) {
|
||||
for (Method method : clazz.getDeclaredMethods()) {
|
||||
Endpoint endpoint = method.getAnnotation(Endpoint.class);
|
||||
|
@ -174,12 +157,13 @@ public class HttpEndpointResolver {
|
|||
}
|
||||
|
||||
public Builder setDispatcher(EndpointDispatcher endpointDispatcher) {
|
||||
Objects.requireNonNull(endpointDispatcher);
|
||||
this.endpointDispatcher = endpointDispatcher;
|
||||
return this;
|
||||
}
|
||||
|
||||
public HttpEndpointResolver build() {
|
||||
return new HttpEndpointResolver(defaultEndpoint, endpoints, endpointDispatcher, limit);
|
||||
return new HttpEndpointResolver(endpoints, endpointDispatcher, limit);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -7,16 +7,27 @@ import java.io.IOException;
|
|||
import java.net.URL;
|
||||
import java.net.URLConnection;
|
||||
import java.time.Instant;
|
||||
import java.util.logging.Level;
|
||||
import java.util.logging.Logger;
|
||||
|
||||
public class ClassLoaderService extends ResourceService {
|
||||
|
||||
private static final Logger logger = Logger.getLogger(ClassLoaderService.class.getName());
|
||||
|
||||
private final Class<?> clazz;
|
||||
|
||||
private final String prefix;
|
||||
|
||||
private final String indexFileName;
|
||||
|
||||
public ClassLoaderService(Class<?> clazz, String prefix) {
|
||||
this(clazz, prefix, "index.html");
|
||||
}
|
||||
|
||||
public ClassLoaderService(Class<?> clazz, String prefix, String indexFileName) {
|
||||
this.clazz = clazz;
|
||||
this.prefix = prefix;
|
||||
this.indexFileName = indexFileName;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -50,11 +61,24 @@ public class ClassLoaderService extends ResourceService {
|
|||
private final long length;
|
||||
|
||||
ClassLoaderResource(ServerRequest serverRequest) throws IOException {
|
||||
this.resourcePath = serverRequest.getEffectiveRequestPath().substring(1);
|
||||
this.url = clazz.getResource(prefix + "/" + resourcePath);
|
||||
URLConnection urlConnection = url.openConnection();
|
||||
this.lastModified = Instant.ofEpochMilli(urlConnection.getLastModified());
|
||||
this.length = urlConnection.getContentLength();
|
||||
String effectivePath = serverRequest.getEffectiveRequestPath();
|
||||
this.resourcePath = effectivePath.startsWith("/") ? effectivePath.substring(1) : effectivePath;
|
||||
String path = prefix.endsWith("/") ? prefix : prefix + "/";
|
||||
path = resourcePath.startsWith("/") ? path + resourcePath.substring(1) : path + resourcePath;
|
||||
this.url = clazz.getResource(path);
|
||||
if (url != null) {
|
||||
URLConnection urlConnection = url.openConnection();
|
||||
this.lastModified = Instant.ofEpochMilli(urlConnection.getLastModified());
|
||||
this.length = urlConnection.getContentLength();
|
||||
if (logger.isLoggable(Level.FINER)) {
|
||||
logger.log(Level.FINER, "success: path=[" + path +
|
||||
"] -> url=" + url + " lastModified=" + lastModified + "length=" + length);
|
||||
}
|
||||
} else {
|
||||
this.lastModified = Instant.now();
|
||||
this.length = 0;
|
||||
logger.log(Level.FINER, "fail: resource not found, url=" + url);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -76,5 +100,15 @@ public class ClassLoaderService extends ResourceService {
|
|||
public long getLength() {
|
||||
return length;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isDirectory() {
|
||||
return resourcePath.endsWith("/");
|
||||
}
|
||||
|
||||
@Override
|
||||
public String indexFileName() {
|
||||
return indexFileName;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -13,14 +13,15 @@ public class FileService extends ResourceService {
|
|||
|
||||
private final Path prefix;
|
||||
|
||||
private final String indexFileName;
|
||||
|
||||
public FileService(Path prefix) {
|
||||
this(prefix, "index.html");
|
||||
}
|
||||
|
||||
public FileService(Path prefix, String indexFileName) {
|
||||
this.prefix = prefix;
|
||||
if (!Files.exists(prefix)) {
|
||||
throw new IllegalArgumentException("prefix: " + prefix + " (does not exist)");
|
||||
}
|
||||
if (!Files.isDirectory(prefix)) {
|
||||
throw new IllegalArgumentException("prefix: " + prefix + " (not a directory)");
|
||||
}
|
||||
this.indexFileName = indexFileName;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -49,16 +50,26 @@ public class FileService extends ResourceService {
|
|||
|
||||
private final URL url;
|
||||
|
||||
private final boolean isDirectory;
|
||||
|
||||
private final Instant lastModified;
|
||||
|
||||
private final long length;
|
||||
|
||||
ChunkedFileResource(ServerRequest serverRequest) throws IOException {
|
||||
this.resourcePath = serverRequest.getEffectiveRequestPath().substring(1);
|
||||
String effectivePath = serverRequest.getEffectiveRequestPath();
|
||||
this.resourcePath = effectivePath.startsWith("/") ? effectivePath.substring(1) : effectivePath;
|
||||
Path path = prefix.resolve(resourcePath);
|
||||
this.url = path.toUri().toURL();
|
||||
this.lastModified = Files.getLastModifiedTime(path).toInstant();
|
||||
this.length = Files.size(path);
|
||||
boolean isExists = Files.exists(path);
|
||||
this.isDirectory = Files.isDirectory(path);
|
||||
if (isExists) {
|
||||
this.lastModified = Files.getLastModifiedTime(path).toInstant();
|
||||
this.length = Files.size(path);
|
||||
} else {
|
||||
this.lastModified = Instant.now();
|
||||
this.length = 0;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -71,6 +82,16 @@ public class FileService extends ResourceService {
|
|||
return url;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isDirectory() {
|
||||
return isDirectory;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String indexFileName() {
|
||||
return indexFileName;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Instant getLastModified() {
|
||||
return lastModified;
|
||||
|
|
|
@ -12,4 +12,8 @@ public interface Resource {
|
|||
Instant getLastModified();
|
||||
|
||||
long getLength();
|
||||
|
||||
boolean isDirectory();
|
||||
|
||||
String indexFileName();
|
||||
}
|
||||
|
|
|
@ -24,6 +24,7 @@ import java.nio.channels.ReadableByteChannel;
|
|||
import java.nio.channels.SeekableByteChannel;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
import java.nio.file.Paths;
|
||||
import java.time.Instant;
|
||||
import java.util.ArrayList;
|
||||
|
@ -50,6 +51,23 @@ public abstract class ResourceService implements Service {
|
|||
protected abstract boolean isRangeResponseEnabled();
|
||||
|
||||
private void handleResource(ServerRequest serverRequest, ServerResponse serverResponse, Resource resource) {
|
||||
if (resource.isDirectory()) {
|
||||
if (!resource.getResourcePath().endsWith("/")) {
|
||||
// external redirect to
|
||||
serverResponse.withHeader(HttpHeaderNames.LOCATION, resource.getResourcePath() + "/");
|
||||
ServerResponse.write(serverResponse, HttpResponseStatus.MOVED_PERMANENTLY);
|
||||
return;
|
||||
} else if (resource.indexFileName() != null) {
|
||||
// external redirect to default index file in this directory
|
||||
serverResponse.withHeader(HttpHeaderNames.LOCATION, resource.indexFileName());
|
||||
ServerResponse.write(serverResponse, HttpResponseStatus.MOVED_PERMANENTLY);
|
||||
return;
|
||||
} else {
|
||||
// send forbidden, we do not allow directory access
|
||||
ServerResponse.write(serverResponse, HttpResponseStatus.FORBIDDEN);
|
||||
return;
|
||||
}
|
||||
}
|
||||
HttpHeaders headers = serverRequest.getHeaders();
|
||||
String contentType = MimeTypeUtils.guessFromPath(resource.getResourcePath(), false);
|
||||
long maxAgeSeconds = 24 * 3600;
|
||||
|
@ -187,7 +205,9 @@ public abstract class ResourceService implements Service {
|
|||
|
||||
private void send(URL url, String contentType,
|
||||
ServerRequest serverRequest, ServerResponse serverResponse) {
|
||||
if (serverRequest.getMethod() == HttpMethod.HEAD) {
|
||||
if (url == null) {
|
||||
ServerResponse.write(serverResponse, HttpResponseStatus.NOT_FOUND);
|
||||
} else if (serverRequest.getMethod() == HttpMethod.HEAD) {
|
||||
ServerResponse.write(serverResponse, HttpResponseStatus.OK, contentType);
|
||||
} else {
|
||||
if ("file".equals(url.getProtocol())) {
|
||||
|
@ -211,15 +231,19 @@ public abstract class ResourceService implements Service {
|
|||
|
||||
private void send(URL url, HttpResponseStatus httpResponseStatus, String contentType,
|
||||
ServerRequest serverRequest, ServerResponse serverResponse, long offset, long size) {
|
||||
if (serverRequest.getMethod() == HttpMethod.HEAD) {
|
||||
if (url == null) {
|
||||
ServerResponse.write(serverResponse, HttpResponseStatus.NOT_FOUND);
|
||||
} else if (serverRequest.getMethod() == HttpMethod.HEAD) {
|
||||
ServerResponse.write(serverResponse, HttpResponseStatus.OK, contentType);
|
||||
} else {
|
||||
if ("file".equals(url.getProtocol())) {
|
||||
Path path = null;
|
||||
try {
|
||||
send((FileChannel) Files.newByteChannel(Paths.get(url.toURI())), httpResponseStatus,
|
||||
path = Paths.get(url.toURI());
|
||||
send((FileChannel) Files.newByteChannel(path), httpResponseStatus,
|
||||
contentType, serverResponse, offset, size);
|
||||
} catch (URISyntaxException | IOException e) {
|
||||
logger.log(Level.SEVERE, e.getMessage(), e);
|
||||
logger.log(Level.SEVERE, e.getMessage() + " path=" + path, e);
|
||||
ServerResponse.write(serverResponse, HttpResponseStatus.NOT_FOUND);
|
||||
}
|
||||
} else {
|
||||
|
@ -240,26 +264,46 @@ public abstract class ResourceService implements Service {
|
|||
|
||||
private void send(FileChannel fileChannel, HttpResponseStatus httpResponseStatus, String contentType,
|
||||
ServerResponse serverResponse, long offset, long size) throws IOException {
|
||||
MappedByteBuffer mappedByteBuffer = fileChannel.map(FileChannel.MapMode.READ_ONLY, offset, size);
|
||||
serverResponse.withStatus(httpResponseStatus)
|
||||
.withContentType(contentType)
|
||||
.write(Unpooled.wrappedBuffer(mappedByteBuffer));
|
||||
if (fileChannel == null) {
|
||||
ServerResponse.write(serverResponse, HttpResponseStatus.NOT_FOUND);
|
||||
} else {
|
||||
MappedByteBuffer mappedByteBuffer = null;
|
||||
try {
|
||||
mappedByteBuffer = fileChannel.map(FileChannel.MapMode.READ_ONLY, offset, size);
|
||||
} catch (IOException e) {
|
||||
// resource is not a file that can be mapped
|
||||
ServerResponse.write(serverResponse, HttpResponseStatus.NOT_FOUND);
|
||||
}
|
||||
if (mappedByteBuffer != null) {
|
||||
serverResponse.withStatus(httpResponseStatus)
|
||||
.withContentType(contentType)
|
||||
.write(Unpooled.wrappedBuffer(mappedByteBuffer));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void send(InputStream inputStream, HttpResponseStatus httpResponseStatus, String contentType,
|
||||
ServerResponse serverResponse) throws IOException {
|
||||
try (ReadableByteChannel channel = Channels.newChannel(inputStream)) {
|
||||
serverResponse.withStatus(httpResponseStatus)
|
||||
.withContentType(contentType)
|
||||
.write(new ChunkedNioStream(channel));
|
||||
if (inputStream == null) {
|
||||
ServerResponse.write(serverResponse, HttpResponseStatus.NOT_FOUND);
|
||||
} else {
|
||||
try (ReadableByteChannel channel = Channels.newChannel(inputStream)) {
|
||||
serverResponse.withStatus(httpResponseStatus)
|
||||
.withContentType(contentType)
|
||||
.write(new ChunkedNioStream(channel));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void send(InputStream inputStream, HttpResponseStatus httpResponseStatus, String contentType,
|
||||
ServerResponse serverResponse, long offset, long size) throws IOException {
|
||||
serverResponse.withStatus(httpResponseStatus)
|
||||
.withContentType(contentType)
|
||||
.write(Unpooled.wrappedBuffer(readBuffer(inputStream, offset, size)));
|
||||
if (inputStream == null) {
|
||||
ServerResponse.write(serverResponse, HttpResponseStatus.NOT_FOUND);
|
||||
} else {
|
||||
serverResponse.withStatus(httpResponseStatus)
|
||||
.withContentType(contentType)
|
||||
.write(Unpooled.wrappedBuffer(readBuffer(inputStream, offset, size)));
|
||||
}
|
||||
}
|
||||
|
||||
private static ByteBuffer readBuffer(URL url, long offset, long size) throws IOException, URISyntaxException {
|
||||
|
|
|
@ -61,7 +61,6 @@ public class HttpServerRequest implements ServerRequest {
|
|||
|
||||
HttpServerRequest(Server server, FullHttpRequest fullHttpRequest,
|
||||
ChannelHandlerContext ctx) {
|
||||
// server not required yet
|
||||
this.httpRequest = fullHttpRequest.retainedDuplicate();
|
||||
this.ctx = ctx;
|
||||
this.httpEndpointDescriptor = new HttpEndpointDescriptor(this);
|
||||
|
@ -70,7 +69,9 @@ public class HttpServerRequest implements ServerRequest {
|
|||
void handleParameters() throws IOException {
|
||||
try {
|
||||
HttpParameters httpParameters = new HttpParameters();
|
||||
this.url = URL.builder().path(httpRequest.uri()).build();
|
||||
this.url = URL.builder()
|
||||
.path(httpRequest.uri()) // creates path, query params, fragment
|
||||
.build();
|
||||
QueryParameters queryParameters = url.getQueryParams();
|
||||
ByteBuf byteBuf = httpRequest.content();
|
||||
if (APPLICATION_FORM_URL_ENCODED.equals(HttpUtil.getMimeType(httpRequest)) && byteBuf != null) {
|
||||
|
|
|
@ -38,8 +38,6 @@ public class HttpServerResponse implements ServerResponse {
|
|||
|
||||
private static final Logger logger = Logger.getLogger(HttpServerResponse.class.getName());
|
||||
|
||||
private static final ByteBuf EMPTY = Unpooled.buffer(0);
|
||||
|
||||
private final Server server;
|
||||
|
||||
private final ServerRequest serverRequest;
|
||||
|
@ -113,7 +111,7 @@ public class HttpServerResponse implements ServerResponse {
|
|||
|
||||
@Override
|
||||
public void flush() {
|
||||
write((ByteBuf) null);
|
||||
write(Unpooled.buffer(0));
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -130,6 +128,7 @@ public class HttpServerResponse implements ServerResponse {
|
|||
|
||||
@Override
|
||||
public void write(ByteBuf byteBuf) {
|
||||
Objects.requireNonNull(byteBuf);
|
||||
if (httpResponseStatus == null) {
|
||||
httpResponseStatus = HttpResponseStatus.OK;
|
||||
}
|
||||
|
@ -139,9 +138,7 @@ public class HttpServerResponse implements ServerResponse {
|
|||
}
|
||||
if (httpResponseStatus.code() >= 200 && httpResponseStatus.code() != 204) {
|
||||
if (!headers.contains(HttpHeaderNames.CONTENT_LENGTH) && !headers.contains(HttpHeaderNames.TRANSFER_ENCODING)) {
|
||||
if (byteBuf != null) {
|
||||
headers.add(HttpHeaderNames.CONTENT_LENGTH, Long.toString(byteBuf.readableBytes()));
|
||||
}
|
||||
headers.add(HttpHeaderNames.CONTENT_LENGTH, Long.toString(byteBuf.readableBytes()));
|
||||
}
|
||||
}
|
||||
if (serverRequest != null && "close".equalsIgnoreCase(serverRequest.getHeaders().get(HttpHeaderNames.CONNECTION)) &&
|
||||
|
@ -154,11 +151,7 @@ public class HttpServerResponse implements ServerResponse {
|
|||
headers.add(HttpHeaderNames.SERVER, ServerName.getServerName());
|
||||
if (ctx.channel().isWritable()) {
|
||||
FullHttpResponse fullHttpResponse;
|
||||
if (byteBuf != null) {
|
||||
fullHttpResponse = new DefaultFullHttpResponse(HttpVersion.HTTP_1_1, httpResponseStatus, byteBuf, headers, trailingHeaders);
|
||||
} else {
|
||||
fullHttpResponse = new DefaultFullHttpResponse(HttpVersion.HTTP_1_1, httpResponseStatus, EMPTY, headers, trailingHeaders);
|
||||
}
|
||||
fullHttpResponse = new DefaultFullHttpResponse(HttpVersion.HTTP_1_1, httpResponseStatus, byteBuf, headers, trailingHeaders);
|
||||
if (serverRequest != null && serverRequest.getSequenceId() != null) {
|
||||
HttpPipelinedResponse httpPipelinedResponse = new HttpPipelinedResponse(fullHttpResponse,
|
||||
ctx.channel().newPromise(), serverRequest.getSequenceId());
|
||||
|
|
|
@ -1,97 +0,0 @@
|
|||
package org.xbib.netty.http.server.test;
|
||||
|
||||
import io.netty.handler.codec.http.HttpVersion;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.junit.jupiter.api.extension.ExtendWith;
|
||||
import org.xbib.netty.http.client.Client;
|
||||
import org.xbib.netty.http.client.Request;
|
||||
import org.xbib.netty.http.common.HttpAddress;
|
||||
import org.xbib.netty.http.server.Server;
|
||||
import org.xbib.netty.http.server.Domain;
|
||||
import org.xbib.netty.http.server.endpoint.service.FileService;
|
||||
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
import java.nio.file.Paths;
|
||||
import java.util.concurrent.atomic.AtomicBoolean;
|
||||
import java.util.logging.Level;
|
||||
import java.util.logging.Logger;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
import static org.junit.jupiter.api.Assertions.assertTrue;
|
||||
|
||||
@ExtendWith(NettyHttpTestExtension.class)
|
||||
class FileServiceTest {
|
||||
|
||||
private static final Logger logger = Logger.getLogger(FileServiceTest.class.getName());
|
||||
|
||||
@Test
|
||||
void testFileServiceHttp1() throws Exception {
|
||||
Path vartmp = Paths.get("/var/tmp/");
|
||||
HttpAddress httpAddress = HttpAddress.http1("localhost", 8008);
|
||||
Domain domain = Domain.builder(httpAddress)
|
||||
.singleEndpoint("/static", "/**", new FileService(vartmp))
|
||||
.build();
|
||||
Server server = Server.builder(domain)
|
||||
.build();
|
||||
Client client = Client.builder()
|
||||
.build();
|
||||
final AtomicBoolean success = new AtomicBoolean(false);
|
||||
try {
|
||||
Files.write(vartmp.resolve("test.txt"), "Hello Jörg".getBytes(StandardCharsets.UTF_8));
|
||||
server.accept();
|
||||
Request request = Request.get().setVersion(HttpVersion.HTTP_1_1)
|
||||
.url(server.getServerConfig().getAddress().base().resolve("/static/test.txt"))
|
||||
.build()
|
||||
.setResponseListener(resp -> {
|
||||
assertEquals("Hello Jörg", resp.getBodyAsString(StandardCharsets.UTF_8));
|
||||
success.set(true);
|
||||
});
|
||||
logger.log(Level.INFO, request.toString());
|
||||
client.execute(request).get();
|
||||
logger.log(Level.INFO, "request complete");
|
||||
} finally {
|
||||
server.shutdownGracefully();
|
||||
client.shutdownGracefully();
|
||||
Files.delete(vartmp.resolve("test.txt"));
|
||||
logger.log(Level.INFO, "server and client shut down");
|
||||
}
|
||||
assertTrue(success.get());
|
||||
}
|
||||
|
||||
@Test
|
||||
void testFileServiceHttp2() throws Exception {
|
||||
Path vartmp = Paths.get("/var/tmp/");
|
||||
HttpAddress httpAddress = HttpAddress.http2("localhost", 8008);
|
||||
Domain domain = Domain.builder(httpAddress)
|
||||
.singleEndpoint("/static", "/**", new FileService(vartmp))
|
||||
.build();
|
||||
Server server = Server.builder(domain)
|
||||
.build();
|
||||
Client client = Client.builder()
|
||||
.build();
|
||||
final AtomicBoolean success = new AtomicBoolean(false);
|
||||
try {
|
||||
Files.write(vartmp.resolve("test.txt"), "Hello Jörg".getBytes(StandardCharsets.UTF_8));
|
||||
server.accept();
|
||||
Request request = Request.get()
|
||||
.setVersion(HttpVersion.valueOf("HTTP/2.0"))
|
||||
.url(server.getServerConfig().getAddress().base().resolve("/static/test.txt"))
|
||||
.build()
|
||||
.setResponseListener(resp -> {
|
||||
assertEquals("Hello Jörg", resp.getBodyAsString(StandardCharsets.UTF_8));
|
||||
success.set(true);
|
||||
});
|
||||
logger.log(Level.INFO, request.toString());
|
||||
client.execute(request).get();
|
||||
logger.log(Level.INFO, "request complete");
|
||||
} finally {
|
||||
server.shutdownGracefully();
|
||||
client.shutdownGracefully();
|
||||
Files.delete(vartmp.resolve("test.txt"));
|
||||
logger.log(Level.INFO, "server and client shut down");
|
||||
}
|
||||
assertTrue(success.get());
|
||||
}
|
||||
}
|
|
@ -0,0 +1,89 @@
|
|||
package org.xbib.netty.http.server.test;
|
||||
|
||||
import io.netty.handler.codec.http.HttpResponseStatus;
|
||||
import io.netty.handler.codec.http.HttpVersion;
|
||||
import static org.junit.jupiter.api.Assertions.assertTrue;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.junit.jupiter.api.extension.ExtendWith;
|
||||
import org.xbib.netty.http.client.Client;
|
||||
import org.xbib.netty.http.client.Request;
|
||||
import org.xbib.netty.http.client.listener.ResponseListener;
|
||||
import org.xbib.netty.http.common.HttpAddress;
|
||||
import org.xbib.netty.http.common.HttpParameters;
|
||||
import org.xbib.netty.http.common.HttpResponse;
|
||||
import org.xbib.netty.http.server.Domain;
|
||||
import org.xbib.netty.http.server.Server;
|
||||
import java.util.concurrent.atomic.AtomicBoolean;
|
||||
import java.util.logging.Level;
|
||||
import java.util.logging.Logger;
|
||||
|
||||
@ExtendWith(NettyHttpTestExtension.class)
|
||||
class FlushTest {
|
||||
|
||||
private static final Logger logger = Logger.getLogger(FlushTest.class.getName());
|
||||
|
||||
/**
|
||||
* This test checks the flush() operation of the server response.
|
||||
* Flush uses Unpooled.buffer(0), and requires a fresh instance each call.
|
||||
* If a static Unpooled.buffer(0) is used, a retry will fail -
|
||||
* and the second "302 Found" will never be sent because of a server hang.
|
||||
* @throws Exception exception
|
||||
*/
|
||||
@Test
|
||||
void testFlush() throws Exception {
|
||||
HttpAddress httpAddress = HttpAddress.http1("localhost", 8008);
|
||||
Domain domain = Domain.builder(httpAddress)
|
||||
.singleEndpoint("/flush", "/**", (req, resp) -> {
|
||||
HttpParameters parameters = req.getParameters();
|
||||
logger.log(Level.INFO, "got request " + parameters.toString() + ", sending 302 Found");
|
||||
resp.withStatus(HttpResponseStatus.FOUND).flush();
|
||||
})
|
||||
.build();
|
||||
Server server = Server.builder(domain)
|
||||
.enableDebug()
|
||||
.build();
|
||||
Client client = Client.builder()
|
||||
.build();
|
||||
final AtomicBoolean success1 = new AtomicBoolean(false);
|
||||
final AtomicBoolean success2 = new AtomicBoolean(false);
|
||||
try {
|
||||
server.accept();
|
||||
|
||||
// first request to trigger flush()
|
||||
|
||||
ResponseListener<HttpResponse> responseListener1 = (resp) -> {
|
||||
logger.log(Level.INFO, "got response = " + resp.getStatus());
|
||||
if (resp.getStatus().getCode() == HttpResponseStatus.FOUND.code()) {
|
||||
success1.set(true);
|
||||
}
|
||||
};
|
||||
Request getRequest = Request.get().setVersion(HttpVersion.HTTP_1_1)
|
||||
.url(server.getServerConfig().getAddress().base().resolve("/flush"))
|
||||
.addParameter("a", "b")
|
||||
.build()
|
||||
.setResponseListener(responseListener1);
|
||||
client.execute(getRequest).get();
|
||||
|
||||
// second request to trigger flush()
|
||||
|
||||
ResponseListener<HttpResponse> responseListener2 = (resp) -> {
|
||||
logger.log(Level.INFO, "got response = " + resp.getStatus());
|
||||
if (resp.getStatus().getCode() == HttpResponseStatus.FOUND.code()) {
|
||||
success2.set(true);
|
||||
}
|
||||
};
|
||||
getRequest = Request.get().setVersion(HttpVersion.HTTP_1_1)
|
||||
.url(server.getServerConfig().getAddress().base().resolve("/flush"))
|
||||
.addParameter("a", "b")
|
||||
.build()
|
||||
.setResponseListener(responseListener2);
|
||||
client.execute(getRequest).get();
|
||||
} finally {
|
||||
server.shutdownGracefully();
|
||||
client.shutdownGracefully();
|
||||
logger.log(Level.INFO, "server and client shut down");
|
||||
}
|
||||
assertTrue(success1.get());
|
||||
assertTrue(success2.get());
|
||||
}
|
||||
}
|
|
@ -105,7 +105,7 @@ class SecureHttp2Test {
|
|||
break;
|
||||
}
|
||||
}
|
||||
transport.get();
|
||||
transport.get(60, TimeUnit.SECONDS);
|
||||
} finally {
|
||||
client.shutdownGracefully();
|
||||
server.shutdownGracefully();
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
package org.xbib.netty.http.server.test;
|
||||
package org.xbib.netty.http.server.test.endpoint;
|
||||
|
||||
import io.netty.handler.codec.http.HttpResponseStatus;
|
||||
import io.netty.handler.codec.http.HttpVersion;
|
||||
|
@ -10,6 +10,7 @@ import org.xbib.netty.http.common.HttpAddress;
|
|||
import org.xbib.netty.http.server.Server;
|
||||
import org.xbib.netty.http.server.Domain;
|
||||
import org.xbib.netty.http.server.endpoint.service.ClassLoaderService;
|
||||
import org.xbib.netty.http.server.test.NettyHttpTestExtension;
|
||||
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.util.concurrent.atomic.AtomicInteger;
|
||||
|
@ -24,16 +25,14 @@ class ClassloaderServiceTest {
|
|||
private static final Logger logger = Logger.getLogger(ClassloaderServiceTest.class.getName());
|
||||
|
||||
@Test
|
||||
void testSimpleClassloader() throws Exception {
|
||||
void testClassloaderFileResource() throws Exception {
|
||||
HttpAddress httpAddress = HttpAddress.http1("localhost", 8008);
|
||||
Domain domain = Domain.builder(httpAddress)
|
||||
.singleEndpoint("/classloader", "/**",
|
||||
new ClassLoaderService(ClassloaderServiceTest.class, "/cl"))
|
||||
.build();
|
||||
Server server = Server.builder(domain)
|
||||
.enableDebug()
|
||||
.build();
|
||||
server.logDiagnostics(Level.INFO);
|
||||
Client client = Client.builder()
|
||||
.build();
|
||||
int max = 1;
|
||||
|
@ -41,12 +40,52 @@ class ClassloaderServiceTest {
|
|||
try {
|
||||
server.accept();
|
||||
Request request = Request.get().setVersion(HttpVersion.HTTP_1_1)
|
||||
.url(server.getServerConfig().getAddress().base().resolve("/classloader/test.txt"))
|
||||
.url(server.getServerConfig().getAddress().base()
|
||||
.resolve("/classloader/test.txt"))
|
||||
.build()
|
||||
.setResponseListener(resp -> {
|
||||
if (resp.getStatus().getCode() == HttpResponseStatus.OK.code()) {
|
||||
assertEquals("Hello Jörg", resp.getBodyAsString(StandardCharsets.UTF_8));
|
||||
count.incrementAndGet();
|
||||
} else {
|
||||
logger.log(Level.WARNING, resp.getStatus().getMessage());
|
||||
}
|
||||
});
|
||||
for (int i = 0; i < max; i++) {
|
||||
client.execute(request).get();
|
||||
}
|
||||
} finally {
|
||||
server.shutdownGracefully();
|
||||
client.shutdownGracefully();
|
||||
logger.log(Level.INFO, "server and client shut down");
|
||||
}
|
||||
assertEquals(max, count.get());
|
||||
}
|
||||
|
||||
@Test
|
||||
void testClassloaderDirectoryResource() throws Exception {
|
||||
HttpAddress httpAddress = HttpAddress.http1("localhost", 8008);
|
||||
Domain domain = Domain.builder(httpAddress)
|
||||
.singleEndpoint("/classloader", "/**",
|
||||
new ClassLoaderService(ClassloaderServiceTest.class, "/cl"))
|
||||
.build();
|
||||
Server server = Server.builder(domain)
|
||||
.build();
|
||||
Client client = Client.builder()
|
||||
.build();
|
||||
int max = 1;
|
||||
final AtomicInteger count = new AtomicInteger(0);
|
||||
try {
|
||||
server.accept();
|
||||
Request request = Request.get().setVersion(HttpVersion.HTTP_1_1)
|
||||
.url(server.getServerConfig().getAddress().base()
|
||||
.resolve("/classloader"))
|
||||
.build()
|
||||
.setResponseListener(resp -> {
|
||||
if (resp.getStatus().getCode() == HttpResponseStatus.NOT_FOUND.code()) {
|
||||
count.incrementAndGet();
|
||||
} else {
|
||||
logger.log(Level.WARNING, resp.getStatus().getMessage());
|
||||
}
|
||||
});
|
||||
for (int i = 0; i < max; i++) {
|
|
@ -1,4 +1,4 @@
|
|||
package org.xbib.netty.http.server.test;
|
||||
package org.xbib.netty.http.server.test.endpoint;
|
||||
|
||||
import io.netty.handler.codec.http.HttpResponseStatus;
|
||||
import io.netty.handler.codec.http.HttpVersion;
|
||||
|
@ -14,6 +14,7 @@ import org.xbib.netty.http.server.endpoint.HttpEndpointResolver;
|
|||
import org.xbib.netty.http.server.Domain;
|
||||
import org.xbib.netty.http.server.endpoint.service.FileService;
|
||||
import org.xbib.netty.http.server.endpoint.service.Service;
|
||||
import org.xbib.netty.http.server.test.NettyHttpTestExtension;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
|
@ -41,7 +42,8 @@ class EndpointTest {
|
|||
HttpEndpointResolver httpEndpointResolver = HttpEndpointResolver.builder()
|
||||
.addEndpoint(HttpEndpoint.builder().setPath("/**").build())
|
||||
.setDispatcher((endpoint, req, resp) -> {
|
||||
logger.log(Level.FINE, "dispatching endpoint = " + endpoint + " req = " + req);
|
||||
logger.log(Level.FINE, "dispatching endpoint = " + endpoint +
|
||||
" req = " + req + " req context path = " + req.getContextPath());
|
||||
service.handle(req, resp);
|
||||
})
|
||||
.build();
|
||||
|
@ -81,7 +83,8 @@ class EndpointTest {
|
|||
HttpEndpointResolver httpEndpointResolver = HttpEndpointResolver.builder()
|
||||
.addEndpoint(HttpEndpoint.builder().setPrefix("/").setPath("/**").build())
|
||||
.setDispatcher((endpoint, req, resp) -> {
|
||||
logger.log(Level.FINE, "dispatching endpoint = " + endpoint + " req = " + req);
|
||||
logger.log(Level.FINE, "dispatching endpoint = " + endpoint +
|
||||
" req = " + req + " req context path = " + req.getContextPath());
|
||||
service.handle(req, resp);
|
||||
})
|
||||
.build();
|
||||
|
@ -113,16 +116,82 @@ class EndpointTest {
|
|||
assertTrue(success.get());
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
void testSimplePathEndpoints() throws Exception {
|
||||
Path vartmp = Paths.get("/var/tmp/");
|
||||
Service service = new FileService(vartmp);
|
||||
HttpAddress httpAddress = HttpAddress.http1("localhost", 8008);
|
||||
HttpEndpointResolver httpEndpointResolver = HttpEndpointResolver.builder()
|
||||
.addEndpoint(HttpEndpoint.builder().setPrefix("/static").setPath("/**").build())
|
||||
.addEndpoint(HttpEndpoint.builder().setPrefix("/static1").setPath("/**").build())
|
||||
.addEndpoint(HttpEndpoint.builder().setPrefix("/static2").setPath("/**").build())
|
||||
.addEndpoint(HttpEndpoint.builder().setPrefix("/static3").setPath("/**").build())
|
||||
.setDispatcher((endpoint, req, resp) -> {
|
||||
logger.log(Level.FINE, "dispatching endpoint = " + endpoint +
|
||||
" req = " + req + " req context path = " + req.getContextPath());
|
||||
service.handle(req, resp);
|
||||
})
|
||||
.build();
|
||||
Domain domain = Domain.builder(httpAddress)
|
||||
.addEndpointResolver(httpEndpointResolver)
|
||||
.build();
|
||||
Server server = Server.builder(domain)
|
||||
.build();
|
||||
Client client = Client.builder()
|
||||
.build();
|
||||
final AtomicBoolean success1 = new AtomicBoolean(false);
|
||||
final AtomicBoolean success2 = new AtomicBoolean(false);
|
||||
final AtomicBoolean success3 = new AtomicBoolean(false);
|
||||
try {
|
||||
Files.write(vartmp.resolve("test1.txt"), "Hello Jörg 1".getBytes(StandardCharsets.UTF_8));
|
||||
Files.write(vartmp.resolve("test2.txt"), "Hello Jörg 2".getBytes(StandardCharsets.UTF_8));
|
||||
Files.write(vartmp.resolve("test3.txt"), "Hello Jörg 3".getBytes(StandardCharsets.UTF_8));
|
||||
server.accept();
|
||||
Request request = Request.get().setVersion(HttpVersion.HTTP_1_1)
|
||||
.url(server.getServerConfig().getAddress().base().resolve("/static1/test1.txt"))
|
||||
.build()
|
||||
.setResponseListener(resp -> {
|
||||
assertEquals("Hello Jörg 1", resp.getBodyAsString(StandardCharsets.UTF_8));
|
||||
success1.set(true);
|
||||
});
|
||||
client.execute(request).get();
|
||||
Request request1 = Request.get().setVersion(HttpVersion.HTTP_1_1)
|
||||
.url(server.getServerConfig().getAddress().base().resolve("/static2/test2.txt"))
|
||||
.build()
|
||||
.setResponseListener(resp -> {
|
||||
assertEquals("Hello Jörg 2",resp.getBodyAsString(StandardCharsets.UTF_8));
|
||||
success2.set(true);
|
||||
});
|
||||
client.execute(request1).get();
|
||||
Request request2 = Request.get().setVersion(HttpVersion.HTTP_1_1)
|
||||
.url(server.getServerConfig().getAddress().base().resolve("/static3/test3.txt"))
|
||||
.build()
|
||||
.setResponseListener(resp -> {
|
||||
assertEquals("Hello Jörg 3", resp.getBodyAsString(StandardCharsets.UTF_8));
|
||||
success3.set(true);
|
||||
});
|
||||
client.execute(request2).get();
|
||||
} finally {
|
||||
server.shutdownGracefully();
|
||||
client.shutdownGracefully();
|
||||
Files.delete(vartmp.resolve("test1.txt"));
|
||||
Files.delete(vartmp.resolve("test2.txt"));
|
||||
Files.delete(vartmp.resolve("test3.txt"));
|
||||
logger.log(Level.INFO, "server and client shut down");
|
||||
}
|
||||
assertTrue(success1.get());
|
||||
assertTrue(success2.get());
|
||||
assertTrue(success3.get());
|
||||
}
|
||||
|
||||
@Test
|
||||
void testQueryEndpoints() throws Exception {
|
||||
Path vartmp = Paths.get("/var/tmp/");
|
||||
Service service = new FileService(vartmp);
|
||||
HttpAddress httpAddress = HttpAddress.http1("localhost", 8008);
|
||||
HttpEndpointResolver httpEndpointResolver = HttpEndpointResolver.builder()
|
||||
.addEndpoint(HttpEndpoint.builder().setPrefix("/static1").setPath("/**").build())
|
||||
.addEndpoint(HttpEndpoint.builder().setPrefix("/static2").setPath("/**").build())
|
||||
.addEndpoint(HttpEndpoint.builder().setPrefix("/static3").setPath("/**").build())
|
||||
.setDispatcher((endpoint, req, resp) -> {
|
||||
logger.log(Level.FINE, "dispatching endpoint = " + endpoint + " req = " + req);
|
||||
service.handle(req, resp);
|
||||
|
@ -135,100 +204,21 @@ class EndpointTest {
|
|||
.build();
|
||||
Client client = Client.builder()
|
||||
.build();
|
||||
final AtomicBoolean success = new AtomicBoolean(false);
|
||||
final AtomicBoolean success1 = new AtomicBoolean(false);
|
||||
final AtomicBoolean success2 = new AtomicBoolean(false);
|
||||
final AtomicBoolean success3 = new AtomicBoolean(false);
|
||||
try {
|
||||
Files.write(vartmp.resolve("test.txt"), "Hello Jörg".getBytes(StandardCharsets.UTF_8));
|
||||
Files.write(vartmp.resolve("test1.txt"), "Hello Jörg 1".getBytes(StandardCharsets.UTF_8));
|
||||
Files.write(vartmp.resolve("test2.txt"), "Hello Jörg 2".getBytes(StandardCharsets.UTF_8));
|
||||
Files.write(vartmp.resolve("test3.txt"), "Hello Jörg 3".getBytes(StandardCharsets.UTF_8));
|
||||
server.accept();
|
||||
Request request = Request.get().setVersion(HttpVersion.HTTP_1_1)
|
||||
.url(server.getServerConfig().getAddress().base().resolve("/static/test.txt"))
|
||||
.build()
|
||||
.setResponseListener(resp -> {
|
||||
assertEquals("Hello Jörg", resp.getBodyAsString(StandardCharsets.UTF_8));
|
||||
success.set(true);
|
||||
});
|
||||
client.execute(request).get();
|
||||
Request request1 = Request.get().setVersion(HttpVersion.HTTP_1_1)
|
||||
.url(server.getServerConfig().getAddress().base().resolve("/static1/test1.txt"))
|
||||
.build()
|
||||
.setResponseListener(resp -> {
|
||||
assertEquals("Hello Jörg 1",resp.getBodyAsString(StandardCharsets.UTF_8));
|
||||
success1.set(true);
|
||||
});
|
||||
client.execute(request1).get();
|
||||
Request request2 = Request.get().setVersion(HttpVersion.HTTP_1_1)
|
||||
.url(server.getServerConfig().getAddress().base().resolve("/static2/test2.txt"))
|
||||
.build()
|
||||
.setResponseListener(resp -> {
|
||||
assertEquals("Hello Jörg 2", resp.getBodyAsString(StandardCharsets.UTF_8));
|
||||
success2.set(true);
|
||||
});
|
||||
client.execute(request2).get();
|
||||
} finally {
|
||||
server.shutdownGracefully();
|
||||
client.shutdownGracefully();
|
||||
Files.delete(vartmp.resolve("test.txt"));
|
||||
Files.delete(vartmp.resolve("test1.txt"));
|
||||
Files.delete(vartmp.resolve("test2.txt"));
|
||||
logger.log(Level.INFO, "server and client shut down");
|
||||
}
|
||||
assertTrue(success.get());
|
||||
assertTrue(success1.get());
|
||||
assertTrue(success2.get());
|
||||
}
|
||||
|
||||
@Test
|
||||
void testQueryAndFragmentEndpoints() throws Exception {
|
||||
Path vartmp = Paths.get("/var/tmp/");
|
||||
Service service = new FileService(vartmp);
|
||||
HttpAddress httpAddress = HttpAddress.http1("localhost", 8008);
|
||||
HttpEndpointResolver httpEndpointResolver = HttpEndpointResolver.builder()
|
||||
.addEndpoint(HttpEndpoint.builder().setPrefix("/static").setPath("/**").build())
|
||||
.addEndpoint(HttpEndpoint.builder().setPrefix("/static1").setPath("/**").build())
|
||||
.addEndpoint(HttpEndpoint.builder().setPrefix("/static2").setPath("/**").build())
|
||||
.setDispatcher((endpoint, req, resp) -> {
|
||||
logger.log(Level.FINE, "dispatching endpoint = " + endpoint + " req = " + req +
|
||||
" fragment=" + req.getURL().getFragment());
|
||||
service.handle(req, resp);
|
||||
})
|
||||
.build();
|
||||
Domain domain = Domain.builder(httpAddress)
|
||||
.addEndpointResolver(httpEndpointResolver)
|
||||
.build();
|
||||
Server server = Server.builder(domain)
|
||||
.build();
|
||||
Client client = Client.builder()
|
||||
.build();
|
||||
final AtomicBoolean success = new AtomicBoolean(false);
|
||||
final AtomicBoolean success1 = new AtomicBoolean(false);
|
||||
final AtomicBoolean success2 = new AtomicBoolean(false);
|
||||
try {
|
||||
Files.write(vartmp.resolve("test.txt"), "Hello Jörg".getBytes(StandardCharsets.UTF_8));
|
||||
Files.write(vartmp.resolve("test1.txt"), "Hello Jörg 1".getBytes(StandardCharsets.UTF_8));
|
||||
Files.write(vartmp.resolve("test2.txt"), "Hello Jörg 2".getBytes(StandardCharsets.UTF_8));
|
||||
server.accept();
|
||||
Request request = Request.get().setVersion(HttpVersion.HTTP_1_1)
|
||||
.url(server.getServerConfig().getAddress().base().resolve("/static/test.txt"))
|
||||
.url(server.getServerConfig().getAddress().base()
|
||||
.resolve("/static1/test1.txt"))
|
||||
.addParameter("a", "b")
|
||||
.build()
|
||||
.setResponseListener(resp -> {
|
||||
if (resp.getStatus().getCode() == HttpResponseStatus.OK.code()) {
|
||||
assertEquals("Hello Jörg", resp.getBodyAsString(StandardCharsets.UTF_8));
|
||||
success.set(true);
|
||||
} else {
|
||||
logger.log(Level.WARNING, resp.getStatus().getReasonPhrase());
|
||||
}
|
||||
});
|
||||
client.execute(request).get();
|
||||
Request request1 = Request.get().setVersion(HttpVersion.HTTP_1_1)
|
||||
.url(server.getServerConfig().getAddress().base()
|
||||
.resolve("/static1/test1.txt").mutator().fragment("frag").build())
|
||||
.build()
|
||||
.setResponseListener(resp -> {
|
||||
if (resp.getStatus().getCode() == HttpResponseStatus.OK.code()) {
|
||||
assertEquals("Hello Jörg 1", resp.getBodyAsString(StandardCharsets.UTF_8));
|
||||
success1.set(true);
|
||||
} else {
|
||||
|
@ -239,44 +229,157 @@ class EndpointTest {
|
|||
Request request2 = Request.get().setVersion(HttpVersion.HTTP_1_1)
|
||||
.url(server.getServerConfig().getAddress().base()
|
||||
.resolve("/static2/test2.txt"))
|
||||
.content("{\"a\":\"b\"}","application/json")
|
||||
.build()
|
||||
.setResponseListener(resp -> {
|
||||
if (resp.getStatus().getCode() == HttpResponseStatus.OK.code()) {
|
||||
assertEquals("Hello Jörg 2",resp.getBodyAsString(StandardCharsets.UTF_8));
|
||||
if (resp.getStatus().getCode() == HttpResponseStatus.OK.code()) {
|
||||
assertEquals("Hello Jörg 2", resp.getBodyAsString(StandardCharsets.UTF_8));
|
||||
success2.set(true);
|
||||
} else {
|
||||
logger.log(Level.WARNING, resp.getStatus().getReasonPhrase());
|
||||
}
|
||||
});
|
||||
client.execute(request2).get();
|
||||
Request request3 = Request.get().setVersion(HttpVersion.HTTP_1_1)
|
||||
.url(server.getServerConfig().getAddress().base()
|
||||
.resolve("/static3/test3.txt"))
|
||||
.content("{\"a\":\"b\"}","application/json")
|
||||
.build()
|
||||
.setResponseListener(resp -> {
|
||||
if (resp.getStatus().getCode() == HttpResponseStatus.OK.code()) {
|
||||
assertEquals("Hello Jörg 3",resp.getBodyAsString(StandardCharsets.UTF_8));
|
||||
success3.set(true);
|
||||
} else {
|
||||
logger.log(Level.WARNING, resp.getStatus().getReasonPhrase());
|
||||
}
|
||||
});
|
||||
client.execute(request3).get();
|
||||
} finally {
|
||||
server.shutdownGracefully();
|
||||
client.shutdownGracefully();
|
||||
Files.delete(vartmp.resolve("test.txt"));
|
||||
logger.log(Level.INFO, "server and client shut down");
|
||||
Files.delete(vartmp.resolve("test1.txt"));
|
||||
Files.delete(vartmp.resolve("test2.txt"));
|
||||
logger.log(Level.INFO, "server and client shut down");
|
||||
Files.delete(vartmp.resolve("test3.txt"));
|
||||
}
|
||||
assertTrue(success.get());
|
||||
assertTrue(success1.get());
|
||||
assertTrue(success2.get());
|
||||
assertTrue(success3.get());
|
||||
}
|
||||
|
||||
@Test
|
||||
void testMultiResolver() throws Exception {
|
||||
Path vartmp = Paths.get("/var/tmp/");
|
||||
Service service1 = new FileService(vartmp);
|
||||
Service service2 = new FileService(vartmp);
|
||||
Service service3 = new FileService(vartmp);
|
||||
HttpAddress httpAddress = HttpAddress.http1("localhost", 8008);
|
||||
HttpEndpointResolver httpEndpointResolver1 = HttpEndpointResolver.builder()
|
||||
.addEndpoint(HttpEndpoint.builder().setPrefix("/static1").setPath("/**").build())
|
||||
.setDispatcher((endpoint, req, resp) -> {
|
||||
logger.log(Level.FINE, "dispatching endpoint = " + endpoint + " context path = " + req.getContextPath());
|
||||
service1.handle(req, resp);
|
||||
})
|
||||
.build();
|
||||
HttpEndpointResolver httpEndpointResolver2 = HttpEndpointResolver.builder()
|
||||
.addEndpoint(HttpEndpoint.builder().setPrefix("/static2").setPath("/**").build())
|
||||
.setDispatcher((endpoint, req, resp) -> {
|
||||
logger.log(Level.FINE, "dispatching endpoint = " + endpoint + " context path = " + req.getContextPath());
|
||||
service2.handle(req, resp);
|
||||
})
|
||||
.build();
|
||||
HttpEndpointResolver httpEndpointResolver3 = HttpEndpointResolver.builder()
|
||||
.addEndpoint(HttpEndpoint.builder().setPrefix("/static3").setPath("/**").build())
|
||||
.setDispatcher((endpoint, req, resp) -> {
|
||||
logger.log(Level.FINE, "dispatching endpoint = " + endpoint + " context path = " + req.getContextPath());
|
||||
service3.handle(req, resp);
|
||||
})
|
||||
.build();
|
||||
Domain domain = Domain.builder(httpAddress)
|
||||
.addEndpointResolver(httpEndpointResolver1)
|
||||
.addEndpointResolver(httpEndpointResolver2)
|
||||
.addEndpointResolver(httpEndpointResolver3)
|
||||
.build();
|
||||
Server server = Server.builder(domain)
|
||||
.build();
|
||||
Client client = Client.builder()
|
||||
.build();
|
||||
final AtomicBoolean success1 = new AtomicBoolean(false);
|
||||
final AtomicBoolean success2 = new AtomicBoolean(false);
|
||||
final AtomicBoolean success3 = new AtomicBoolean(false);
|
||||
try {
|
||||
Files.write(vartmp.resolve("test1.txt"), "Hello Jörg 1".getBytes(StandardCharsets.UTF_8));
|
||||
Files.write(vartmp.resolve("test2.txt"), "Hello Jörg 2".getBytes(StandardCharsets.UTF_8));
|
||||
Files.write(vartmp.resolve("test3.txt"), "Hello Jörg 3".getBytes(StandardCharsets.UTF_8));
|
||||
server.accept();
|
||||
Request request1 = Request.get().setVersion(HttpVersion.HTTP_1_1)
|
||||
.url(server.getServerConfig().getAddress().base()
|
||||
.resolve("/static1/test1.txt"))
|
||||
.addParameter("a", "b")
|
||||
.build()
|
||||
.setResponseListener(resp -> {
|
||||
if (resp.getStatus().getCode() == HttpResponseStatus.OK.code()) {
|
||||
assertEquals("Hello Jörg 1", resp.getBodyAsString(StandardCharsets.UTF_8));
|
||||
success1.set(true);
|
||||
} else {
|
||||
logger.log(Level.WARNING, resp.getStatus().getReasonPhrase());
|
||||
}
|
||||
});
|
||||
client.execute(request1).get();
|
||||
Request request2 = Request.get().setVersion(HttpVersion.HTTP_1_1)
|
||||
.url(server.getServerConfig().getAddress().base()
|
||||
.resolve("/static2/test2.txt"))
|
||||
.build()
|
||||
.setResponseListener(resp -> {
|
||||
if (resp.getStatus().getCode() == HttpResponseStatus.OK.code()) {
|
||||
assertEquals("Hello Jörg 2", resp.getBodyAsString(StandardCharsets.UTF_8));
|
||||
success2.set(true);
|
||||
} else {
|
||||
logger.log(Level.WARNING, resp.getStatus().getReasonPhrase());
|
||||
}
|
||||
});
|
||||
client.execute(request2).get();
|
||||
Request request3 = Request.get().setVersion(HttpVersion.HTTP_1_1)
|
||||
.url(server.getServerConfig().getAddress().base()
|
||||
.resolve("/static3/test3.txt"))
|
||||
.content("{\"a\":\"b\"}","application/json")
|
||||
.build()
|
||||
.setResponseListener(resp -> {
|
||||
if (resp.getStatus().getCode() == HttpResponseStatus.OK.code()) {
|
||||
assertEquals("Hello Jörg 3",resp.getBodyAsString(StandardCharsets.UTF_8));
|
||||
success3.set(true);
|
||||
} else {
|
||||
logger.log(Level.WARNING, resp.getStatus().getReasonPhrase());
|
||||
}
|
||||
});
|
||||
client.execute(request3).get();
|
||||
} finally {
|
||||
server.shutdownGracefully();
|
||||
client.shutdownGracefully();
|
||||
logger.log(Level.INFO, "server and client shut down");
|
||||
Files.delete(vartmp.resolve("test1.txt"));
|
||||
Files.delete(vartmp.resolve("test2.txt"));
|
||||
Files.delete(vartmp.resolve("test3.txt"));
|
||||
}
|
||||
assertTrue(success1.get());
|
||||
assertTrue(success2.get());
|
||||
assertTrue(success3.get());
|
||||
}
|
||||
|
||||
@Test
|
||||
void testMassiveEndpoints() throws IOException {
|
||||
int max = 1024;
|
||||
int max = 1024; // the default limit, must work
|
||||
HttpAddress httpAddress = HttpAddress.http1("localhost", 8008);
|
||||
HttpEndpointResolver.Builder endpointResolverBuilder = HttpEndpointResolver.builder()
|
||||
.setPrefix("/static");
|
||||
for (int i = 0; i < max; i++) {
|
||||
endpointResolverBuilder.addEndpoint(HttpEndpoint.builder()
|
||||
.setPath("/" + i + "/**")
|
||||
.addFilter((req, resp) -> ServerResponse.write(resp, HttpResponseStatus.OK))
|
||||
.build());
|
||||
}
|
||||
Domain domain = Domain.builder(httpAddress)
|
||||
.addEndpointResolver(endpointResolverBuilder.build())
|
||||
.addEndpointResolver(endpointResolverBuilder
|
||||
.setDispatcher((endpoint,req, resp) -> ServerResponse.write(resp, HttpResponseStatus.OK))
|
||||
.build())
|
||||
.build();
|
||||
Server server = Server.builder(domain)
|
||||
.build();
|
||||
|
@ -305,4 +408,45 @@ class EndpointTest {
|
|||
}
|
||||
assertEquals(max, count.get());
|
||||
}
|
||||
|
||||
@Test
|
||||
void testMassiveEndpointResolvers() throws IOException {
|
||||
int max = 1024; // the default limit, must work
|
||||
HttpAddress httpAddress = HttpAddress.http1("localhost", 8008);
|
||||
HttpEndpointResolver.Builder endpointResolverBuilder = HttpEndpointResolver.builder()
|
||||
.setPrefix("/static");
|
||||
Domain.Builder domainBuilder = Domain.builder(httpAddress);
|
||||
for (int i = 0; i < max; i++) {
|
||||
domainBuilder.addEndpointResolver(endpointResolverBuilder.addEndpoint(HttpEndpoint.builder()
|
||||
.setPath("/" + i + "/**").build())
|
||||
.setDispatcher((endpoint,req, resp) -> ServerResponse.write(resp, HttpResponseStatus.OK))
|
||||
.build());
|
||||
}
|
||||
Server server = Server.builder(domainBuilder.build())
|
||||
.build();
|
||||
Client client = Client.builder()
|
||||
.build();
|
||||
final AtomicInteger count = new AtomicInteger(0);
|
||||
try {
|
||||
server.accept();
|
||||
for (int i = 0; i < max; i++) {
|
||||
Request request = Request.get().setVersion(HttpVersion.HTTP_1_1)
|
||||
.url(server.getServerConfig().getAddress().base().resolve("/static/" + i + "/test.txt"))
|
||||
.build()
|
||||
.setResponseListener(resp -> {
|
||||
if (resp.getStatus().getCode() == HttpResponseStatus.OK.code()) {
|
||||
count.incrementAndGet();
|
||||
} else {
|
||||
logger.log(Level.WARNING, resp.getStatus().getReasonPhrase());
|
||||
}
|
||||
});
|
||||
client.execute(request).get();
|
||||
}
|
||||
} finally {
|
||||
server.shutdownGracefully();
|
||||
client.shutdownGracefully();
|
||||
logger.log(Level.INFO, "server and client shut down");
|
||||
}
|
||||
assertEquals(max, count.get());
|
||||
}
|
||||
}
|
|
@ -0,0 +1,210 @@
|
|||
package org.xbib.netty.http.server.test.endpoint;
|
||||
|
||||
import io.netty.handler.codec.http.HttpResponseStatus;
|
||||
import io.netty.handler.codec.http.HttpVersion;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.junit.jupiter.api.extension.ExtendWith;
|
||||
import org.xbib.netty.http.client.Client;
|
||||
import org.xbib.netty.http.client.Request;
|
||||
import org.xbib.netty.http.common.HttpAddress;
|
||||
import org.xbib.netty.http.server.Server;
|
||||
import org.xbib.netty.http.server.Domain;
|
||||
import org.xbib.netty.http.server.endpoint.service.FileService;
|
||||
import org.xbib.netty.http.server.test.NettyHttpTestExtension;
|
||||
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
import java.nio.file.Paths;
|
||||
import java.util.concurrent.atomic.AtomicBoolean;
|
||||
import java.util.logging.Level;
|
||||
import java.util.logging.Logger;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
import static org.junit.jupiter.api.Assertions.assertTrue;
|
||||
|
||||
@ExtendWith(NettyHttpTestExtension.class)
|
||||
class FileServiceTest {
|
||||
|
||||
private static final Logger logger = Logger.getLogger(FileServiceTest.class.getName());
|
||||
|
||||
@Test
|
||||
void testFileServiceHttp1() throws Exception {
|
||||
Path vartmp = Paths.get("/var/tmp/");
|
||||
HttpAddress httpAddress = HttpAddress.http1("localhost", 8008);
|
||||
Domain domain = Domain.builder(httpAddress)
|
||||
.singleEndpoint("/static", "/**", new FileService(vartmp))
|
||||
.build();
|
||||
Server server = Server.builder(domain)
|
||||
.build();
|
||||
Client client = Client.builder()
|
||||
.build();
|
||||
final AtomicBoolean success = new AtomicBoolean(false);
|
||||
try {
|
||||
Files.write(vartmp.resolve("test.txt"), "Hello Jörg".getBytes(StandardCharsets.UTF_8));
|
||||
server.accept();
|
||||
Request request = Request.get()
|
||||
.setVersion(HttpVersion.HTTP_1_1)
|
||||
.url(server.getServerConfig().getAddress().base().resolve("/static/test.txt"))
|
||||
.build()
|
||||
.setResponseListener(resp -> {
|
||||
assertEquals("Hello Jörg", resp.getBodyAsString(StandardCharsets.UTF_8));
|
||||
success.set(true);
|
||||
});
|
||||
client.execute(request).get();
|
||||
} finally {
|
||||
server.shutdownGracefully();
|
||||
client.shutdownGracefully();
|
||||
Files.delete(vartmp.resolve("test.txt"));
|
||||
logger.log(Level.INFO, "server and client shut down");
|
||||
}
|
||||
assertTrue(success.get());
|
||||
}
|
||||
|
||||
@Test
|
||||
void testFileServiceHttp2() throws Exception {
|
||||
Path vartmp = Paths.get("/var/tmp/");
|
||||
HttpAddress httpAddress = HttpAddress.http2("localhost", 8008);
|
||||
Domain domain = Domain.builder(httpAddress)
|
||||
.singleEndpoint("/static", "/**", new FileService(vartmp))
|
||||
.build();
|
||||
Server server = Server.builder(domain)
|
||||
.build();
|
||||
Client client = Client.builder()
|
||||
.build();
|
||||
final AtomicBoolean success = new AtomicBoolean(false);
|
||||
try {
|
||||
Files.write(vartmp.resolve("test.txt"), "Hello Jörg".getBytes(StandardCharsets.UTF_8));
|
||||
server.accept();
|
||||
Request request = Request.get()
|
||||
.setVersion(HttpVersion.valueOf("HTTP/2.0"))
|
||||
.url(server.getServerConfig().getAddress().base().resolve("/static/test.txt"))
|
||||
.build()
|
||||
.setResponseListener(resp -> {
|
||||
assertEquals("Hello Jörg", resp.getBodyAsString(StandardCharsets.UTF_8));
|
||||
success.set(true);
|
||||
});
|
||||
client.execute(request).get();
|
||||
} finally {
|
||||
server.shutdownGracefully();
|
||||
client.shutdownGracefully();
|
||||
Files.delete(vartmp.resolve("test.txt"));
|
||||
logger.log(Level.INFO, "server and client shut down");
|
||||
}
|
||||
assertTrue(success.get());
|
||||
}
|
||||
|
||||
@Test
|
||||
void testIndexFileHttp1() throws Exception {
|
||||
Path vartmp = Paths.get("/var/tmp");
|
||||
Path vartmpforward = vartmp.resolve("forward_test");
|
||||
Files.createDirectories(vartmpforward);
|
||||
Files.write(vartmpforward.resolve("test.txt"), "Hello Jörg".getBytes(StandardCharsets.UTF_8));
|
||||
HttpAddress httpAddress = HttpAddress.http1("localhost", 8008);
|
||||
Domain domain = Domain.builder(httpAddress)
|
||||
.singleEndpoint("/static", "/**", new FileService(vartmp, "test.txt"))
|
||||
.build();
|
||||
Server server = Server.builder(domain)
|
||||
.build();
|
||||
Client client = Client.builder()
|
||||
.build();
|
||||
final AtomicBoolean success = new AtomicBoolean(false);
|
||||
try {
|
||||
server.accept();
|
||||
Request request = Request.get().setVersion(HttpVersion.HTTP_1_1)
|
||||
.url(server.getServerConfig().getAddress().base().resolve("/static/forward_test"))
|
||||
.build()
|
||||
.setResponseListener(resp -> {
|
||||
if (resp.getStatus().getCode() == HttpResponseStatus.OK.code()) {
|
||||
assertEquals("Hello Jörg", resp.getBodyAsString(StandardCharsets.UTF_8));
|
||||
success.set(true);
|
||||
}
|
||||
});
|
||||
client.execute(request).get();
|
||||
} finally {
|
||||
server.shutdownGracefully();
|
||||
client.shutdownGracefully();
|
||||
Files.delete(vartmpforward.resolve("test.txt"));
|
||||
Files.delete(vartmpforward);
|
||||
logger.log(Level.INFO, "server and client shut down");
|
||||
}
|
||||
assertTrue(success.get());
|
||||
}
|
||||
|
||||
@Test
|
||||
void testIndexFileHttp2() throws Exception {
|
||||
Path vartmp = Paths.get("/var/tmp");
|
||||
Path vartmpforward = vartmp.resolve("forward_test");
|
||||
Files.createDirectories(vartmpforward);
|
||||
Files.write(vartmpforward.resolve("test.txt"), "Hello Jörg".getBytes(StandardCharsets.UTF_8));
|
||||
HttpAddress httpAddress = HttpAddress.http2("localhost", 8008);
|
||||
Domain domain = Domain.builder(httpAddress)
|
||||
.singleEndpoint("/static", "/**", new FileService(vartmp, "test.txt"))
|
||||
.build();
|
||||
Server server = Server.builder(domain)
|
||||
.build();
|
||||
Client client = Client.builder()
|
||||
.build();
|
||||
final AtomicBoolean success = new AtomicBoolean(false);
|
||||
try {
|
||||
server.accept();
|
||||
Request request = Request.get()
|
||||
.setVersion(HttpVersion.valueOf("HTTP/2.0"))
|
||||
.url(server.getServerConfig().getAddress().base().resolve("/static/forward_test"))
|
||||
.build()
|
||||
.setResponseListener(resp -> {
|
||||
if (resp.getStatus().getCode() == HttpResponseStatus.OK.code()) {
|
||||
assertEquals("Hello Jörg", resp.getBodyAsString(StandardCharsets.UTF_8));
|
||||
success.set(true);
|
||||
}
|
||||
});
|
||||
client.execute(request).get();
|
||||
// client waits for settings, we wait too
|
||||
Thread.sleep(1000L);
|
||||
} finally {
|
||||
server.shutdownGracefully();
|
||||
client.shutdownGracefully();
|
||||
Files.delete(vartmpforward.resolve("test.txt"));
|
||||
Files.delete(vartmpforward);
|
||||
logger.log(Level.INFO, "server and client shut down");
|
||||
}
|
||||
assertTrue(success.get());
|
||||
}
|
||||
|
||||
@Test
|
||||
void testIndexFileParamsHttp1() throws Exception {
|
||||
Path vartmp = Paths.get("/var/tmp");
|
||||
Path vartmpforward = vartmp.resolve("forward_test");
|
||||
Files.createDirectories(vartmpforward);
|
||||
Files.write(vartmpforward.resolve("test.txt"), "Hello Jörg".getBytes(StandardCharsets.UTF_8));
|
||||
HttpAddress httpAddress = HttpAddress.http1("localhost", 8008);
|
||||
Domain domain = Domain.builder(httpAddress)
|
||||
.singleEndpoint("/static", "/**",
|
||||
new FileService(vartmp, "test.txt"))
|
||||
.build();
|
||||
Server server = Server.builder(domain)
|
||||
.build();
|
||||
Client client = Client.builder()
|
||||
.build();
|
||||
final AtomicBoolean success = new AtomicBoolean(false);
|
||||
try {
|
||||
server.accept();
|
||||
Request request = Request.get().setVersion(HttpVersion.HTTP_1_1)
|
||||
.url(server.getServerConfig().getAddress().base().resolve("/static/forward_test?a=b"))
|
||||
.build()
|
||||
.setResponseListener(resp -> {
|
||||
if (resp.getStatus().getCode() == HttpResponseStatus.OK.code()) {
|
||||
assertEquals("Hello Jörg", resp.getBodyAsString(StandardCharsets.UTF_8));
|
||||
success.set(true);
|
||||
}
|
||||
});
|
||||
client.execute(request).get();
|
||||
} finally {
|
||||
server.shutdownGracefully();
|
||||
client.shutdownGracefully();
|
||||
Files.delete(vartmpforward.resolve("test.txt"));
|
||||
Files.delete(vartmpforward);
|
||||
}
|
||||
assertTrue(success.get());
|
||||
}
|
||||
}
|
|
@ -1,4 +1,4 @@
|
|||
package org.xbib.netty.http.server.test;
|
||||
package org.xbib.netty.http.server.test.endpoint;
|
||||
|
||||
import io.netty.handler.codec.http.HttpVersion;
|
||||
import org.junit.jupiter.api.Disabled;
|
||||
|
@ -10,6 +10,7 @@ import org.xbib.netty.http.common.HttpAddress;
|
|||
import org.xbib.netty.http.server.Server;
|
||||
import org.xbib.netty.http.server.Domain;
|
||||
import org.xbib.netty.http.server.endpoint.service.FileService;
|
||||
import org.xbib.netty.http.server.test.NettyHttpTestExtension;
|
||||
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.nio.file.Files;
|
||||
|
@ -27,7 +28,6 @@ class SecureFileServiceTest {
|
|||
|
||||
private static final Logger logger = Logger.getLogger(SecureFileServiceTest.class.getName());
|
||||
|
||||
@Disabled
|
||||
@Test
|
||||
void testSecureFileServerHttp1() throws Exception {
|
||||
Path vartmp = Paths.get("/var/tmp/");
|
||||
|
@ -39,12 +39,10 @@ class SecureFileServiceTest {
|
|||
.build())
|
||||
.setChildThreadCount(8)
|
||||
.build();
|
||||
//server.logDiagnostics(Level.INFO);
|
||||
Client client = Client.builder()
|
||||
.setJdkSslProvider()
|
||||
.trustInsecure()
|
||||
.build();
|
||||
//client.logDiagnostics(Level.INFO);
|
||||
final AtomicBoolean success = new AtomicBoolean(false);
|
||||
try {
|
||||
Files.write(vartmp.resolve("test.txt"), "Hello Jörg".getBytes(StandardCharsets.UTF_8));
|
||||
|
@ -57,14 +55,11 @@ class SecureFileServiceTest {
|
|||
assertEquals("Hello Jörg", resp.getBodyAsString(StandardCharsets.UTF_8));
|
||||
success.set(true);
|
||||
});
|
||||
logger.log(Level.INFO, request.toString());
|
||||
client.execute(request).get();
|
||||
logger.log(Level.INFO, "request complete");
|
||||
} finally {
|
||||
server.shutdownGracefully();
|
||||
client.shutdownGracefully();
|
||||
Files.delete(vartmp.resolve("test.txt"));
|
||||
logger.log(Level.INFO, "server and client shut down");
|
||||
}
|
||||
assertTrue(success.get());
|
||||
}
|
||||
|
@ -105,7 +100,6 @@ class SecureFileServiceTest {
|
|||
server.shutdownGracefully();
|
||||
client.shutdownGracefully();
|
||||
Files.delete(vartmp.resolve("test.txt"));
|
||||
logger.log(Level.INFO, "server and client shut down");
|
||||
}
|
||||
assertTrue(success.get());
|
||||
}
|
||||
|
@ -134,20 +128,18 @@ class SecureFileServiceTest {
|
|||
server.accept();
|
||||
Request request = Request.get()
|
||||
.setVersion(HttpVersion.HTTP_1_1)
|
||||
.url(server.getServerConfig().getAddress().base().resolve("/static/test.txt"))
|
||||
.url(server.getServerConfig().getAddress().base()
|
||||
.resolve("/static/test.txt"))
|
||||
.build()
|
||||
.setResponseListener(resp -> {
|
||||
assertEquals("Hello Jörg", resp.getBodyAsString(StandardCharsets.UTF_8));
|
||||
success.set(true);
|
||||
});
|
||||
logger.log(Level.INFO, request.toString());
|
||||
client.execute(request).get();
|
||||
logger.log(Level.INFO, "request complete");
|
||||
} finally {
|
||||
server.shutdownGracefully();
|
||||
client.shutdownGracefully();
|
||||
Files.delete(vartmp.resolve("test.txt"));
|
||||
logger.log(Level.INFO, "server and client shut down");
|
||||
}
|
||||
assertTrue(success.get());
|
||||
}
|
|
@ -19,7 +19,6 @@ import io.netty.handler.codec.http.HttpVersion;
|
|||
import io.netty.handler.codec.http.LastHttpContent;
|
||||
import io.netty.handler.codec.http.QueryStringDecoder;
|
||||
import org.junit.jupiter.api.AfterAll;
|
||||
import org.junit.jupiter.api.Disabled;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.junit.jupiter.api.TestInstance;
|
||||
import org.junit.jupiter.api.extension.ExtendWith;
|
||||
|
@ -49,8 +48,6 @@ import static org.junit.jupiter.api.Assertions.assertNotNull;
|
|||
import static org.junit.jupiter.api.Assertions.assertThrows;
|
||||
import static org.junit.jupiter.api.Assertions.assertTrue;
|
||||
|
||||
/** flaky */
|
||||
@Disabled
|
||||
@TestInstance(TestInstance.Lifecycle.PER_CLASS)
|
||||
@ExtendWith(NettyHttpTestExtension.class)
|
||||
class HttpPipeliningHandlerTest {
|
||||
|
@ -72,7 +69,7 @@ class HttpPipeliningHandlerTest {
|
|||
EmbeddedChannel embeddedChannel = new EmbeddedChannel(new HttpPipeliningHandler(10000),
|
||||
handler);
|
||||
for (int i = 0; i < 5; i++) {
|
||||
embeddedChannel.writeInbound(createHttpRequest("/" + String.valueOf(i)));
|
||||
embeddedChannel.writeInbound(createHttpRequest("/" + i));
|
||||
}
|
||||
for (String url : waitingRequests.keySet()) {
|
||||
finishRequest(url);
|
||||
|
@ -90,7 +87,7 @@ class HttpPipeliningHandlerTest {
|
|||
EmbeddedChannel embeddedChannel = new EmbeddedChannel(new HttpPipeliningHandler(10000),
|
||||
handler);
|
||||
for (int i = 0; i < 5; i++) {
|
||||
embeddedChannel.writeInbound(createHttpRequest("/" + String.valueOf(i)));
|
||||
embeddedChannel.writeInbound(createHttpRequest("/" + i));
|
||||
}
|
||||
List<String> urls = new ArrayList<>(waitingRequests.keySet());
|
||||
Collections.shuffle(urls);
|
||||
|
|
Loading…
Reference in a new issue