[
https://issues.apache.org/jira/browse/HTTPCORE-689?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=17435227#comment-17435227
]
Oleg Kalnichevski commented on HTTPCORE-689:
--------------------------------------------
[~andressolm96] The same example with just minor modifications works for me as
expected.
Oleg
{code:java}
if (args.length < 1) {
System.err.println("Please specify document root directory");
System.exit(1);
}
// Document root directory
final File docRoot = new File(args[0]);
int port = 8080;
if (args.length >= 2) {
port = Integer.parseInt(args[1]);
}
final URL resource1 =
AsyncFileServerExample.class.getResource("/test-server.p12");
final String storePassword = "nopassword";
final String keyPassword = "nopassword";
final SSLContext serverSslContext = SSLContextBuilder.create()
.loadKeyMaterial(resource1, storePassword.toCharArray(),
keyPassword.toCharArray())
.build();
final IOReactorConfig config = IOReactorConfig.custom()
.setSoTimeout(15, TimeUnit.SECONDS)
.setTcpNoDelay(true)
.build();
final HttpAsyncServer server = AsyncServerBootstrap.bootstrap()
.setIOReactorConfig(config)
.setTlsStrategy(new BasicServerTlsStrategy(serverSslContext,
new SSLSessionVerifier() {
@Override
public TlsDetails verify(final NamedEndpoint endpoint,
final SSLEngine sslEngine) throws SSLException {
return new TlsDetails(sslEngine.getSession(),
sslEngine.getApplicationProtocol());
}
}))
.register("*", new
AsyncServerRequestHandler<Message<HttpRequest, Void>>() {
@Override
public AsyncRequestConsumer<Message<HttpRequest, Void>>
prepare(
final HttpRequest request,
final EntityDetails entityDetails,
final HttpContext context) throws HttpException {
return new BasicRequestConsumer<>(entityDetails != null
? new NoopEntityConsumer() : null);
}
@Override
public void handle(
final Message<HttpRequest, Void> message,
final ResponseTrigger responseTrigger,
final HttpContext context) throws HttpException,
IOException {
final HttpRequest request = message.getHead();
final URI requestUri;
try {
requestUri = request.getUri();
} catch (final URISyntaxException ex) {
throw new ProtocolException(ex.getMessage(), ex);
}
final String path = requestUri.getPath();
final File file = new File(docRoot, path);
if (!file.exists()) {
final String msg = "File " + file.getPath() + " not
found";
println(msg);
responseTrigger.submitResponse(
AsyncResponseBuilder.create(HttpStatus.SC_NOT_FOUND)
.setEntity("<html><body><h1>" + msg
+ "</h1></body></html>", ContentType.TEXT_HTML)
.build(),
context);
} else if (!file.canRead() || file.isDirectory()) {
final String msg = "Cannot read file " +
file.getPath();
println(msg);
responseTrigger.submitResponse(AsyncResponseBuilder.create(HttpStatus.SC_FORBIDDEN)
.setEntity("<html><body><h1>" + msg
+ "</h1></body></html>", ContentType.TEXT_HTML)
.build(),
context);
} else {
final ContentType contentType;
final String filename =
file.getName().toLowerCase(Locale.ROOT);
if (filename.endsWith(".txt")) {
contentType = ContentType.TEXT_PLAIN;
} else if (filename.endsWith(".html") ||
filename.endsWith(".htm")) {
contentType = ContentType.TEXT_HTML;
} else if (filename.endsWith(".xml")) {
contentType = ContentType.TEXT_XML;
} else {
contentType = ContentType.DEFAULT_BINARY;
}
final HttpCoreContext coreContext =
HttpCoreContext.adapt(context);
final EndpointDetails endpoint =
coreContext.getEndpointDetails();
println(endpoint + " | serving file " +
file.getPath());
responseTrigger.submitResponse(
AsyncResponseBuilder.create(HttpStatus.SC_OK)
.setEntity(AsyncEntityProducers.create(file, contentType))
.build(),
context);
}
}
})
.create();
Runtime.getRuntime().addShutdownHook(new Thread() {
@Override
public void run() {
println("HTTP server shutting down");
server.close(CloseMode.GRACEFUL);
}
});
server.start();
final Future<ListenerEndpoint> future = server.listen(new
InetSocketAddress(port), URIScheme.HTTPS);
final ListenerEndpoint listenerEndpoint = future.get();
println("Listening on " + listenerEndpoint.getAddress());
server.awaitShutdown(TimeValue.MAX_VALUE);
}
static final void println(final String msg) {
System.out.println(HttpDateGenerator.INSTANCE.getCurrentDate() + " | "
+ msg);
}
{code}
{noformat}
$ curl -k https://localhost:8080/test.txt -v
% Total % Received % Xferd Average Speed Time Time Time Current
Dload Upload Total Spent Left Speed
0 0 0 0 0 0 0 0 --:--:-- --:--:-- --:--:-- 0*
Trying ::1:8080...
* Connected to localhost (::1) port 8080 (#0)
* ALPN, offering h2
* ALPN, offering http/1.1
* successfully set certificate verify locations:
* CAfile: C:/Program Files/Git/mingw64/ssl/certs/ca-bundle.crt
CApath: none
} [5 bytes data]
* TLSv1.3 (OUT), TLS handshake, Client hello (1):
} [512 bytes data]
* TLSv1.3 (IN), TLS handshake, Server hello (2):
{ [193 bytes data]
* TLSv1.3 (OUT), TLS change cipher, Change cipher spec (1):
} [1 bytes data]
* TLSv1.3 (OUT), TLS handshake, Client hello (1):
} [512 bytes data]
* TLSv1.3 (IN), TLS handshake, Server hello (2):
{ [155 bytes data]
* TLSv1.3 (IN), TLS handshake, Encrypted Extensions (8):
{ [28 bytes data]
* TLSv1.3 (IN), TLS handshake, Certificate (11):
{ [1985 bytes data]
* TLSv1.3 (IN), TLS handshake, CERT verify (15):
{ [264 bytes data]
* TLSv1.3 (IN), TLS handshake, Finished (20):
{ [52 bytes data]
* TLSv1.3 (OUT), TLS handshake, Finished (20):
} [52 bytes data]
* SSL connection using TLSv1.3 / TLS_AES_256_GCM_SHA384
* ALPN, server did not agree to a protocol
* Server certificate:
* subject: O=Apache Software Foundation; OU=HttpComponents Project; CN=Test
Server
* start date: Oct 11 15:56:37 2019 GMT
* expire date: Jul 26 15:56:37 2293 GMT
* issuer: O=Apache Software Foundation; OU=HttpComponents Project; CN=Test CA;
[email protected]
* SSL certificate verify result: self signed certificate in certificate chain
(19), continuing anyway.
} [5 bytes data]
> GET /test.txt HTTP/1.1
> Host: localhost:8080
> User-Agent: curl/7.71.1
> Accept: */*
>
{ [5 bytes data]
* TLSv1.3 (IN), TLS handshake, Newsession Ticket (4):
{ [50 bytes data]
* Mark bundle as not supporting multiuse
< HTTP/1.1 200 OK
< Date: Thu, 28 Oct 2021 07:51:19 GMT
< Server: Apache-HttpCore/5.1.3-SNAPSHOT (Java/11.0.9)
< Content-Length: 5
< Content-Type: text/plain; charset=ISO-8859-1
<
{ [5 bytes data]
100 5 100 5 0 0 31 0 --:--:-- --:--:-- --:--:--
31BLAH!
* Connection #0 to host localhost left intact
{noformat}
> HttpAsyncServer with TLsStrategy Error in BasicParseLine
> --------------------------------------------------------
>
> Key: HTTPCORE-689
> URL: https://issues.apache.org/jira/browse/HTTPCORE-689
> Project: HttpComponents HttpCore
> Issue Type: Bug
> Components: Examples, HttpCore
> Affects Versions: 5.1
> Environment: Mac OS 11.6 / Maven 3.8.1 / AdoptOpenJDK-11.0.11+9
> Reporter: Andres
> Priority: Major
>
> I've being followed the example in
> [https://github.com/apache/httpcomponents-core/blob/5.1.x/httpcore5/src/test/java/org/apache/hc/core5/http/examples/AsyncFileServerExample.java]
> This example is working as expected. However when I try to implement a
> SSLContext with the method:
> {code:java}
> final HttpAsyncServer server =
> AsyncServerBootstrap.bootstrap().setIOReactorConfig(config)
> .setTlsStrategy(new BasicServerTlsStrategy(sslContext))
> ...
> {code}
> After triggering a http request, the parseLine is failing with:
> {code:java}
> Exception has occurred:
> org.apache.hc.core5.http.ParseException"org.apache.hc.core5.http.ParseException:
> Invalid request line; error at offset 31:
> <[0x2b][0x2c][0x2d][0x2e]ß[0x30][0x31][0x32]Û[0x34][0x35]WåT¾±)âJ3ËÉk{Eµ>"
> {code}
> I'm not sure if the HTTPS (TLS) handshake is not working as expected in the
> non-blocking message transport classes, because SSLContext it's working fine
> in booking classes.
> Or could you provide an example to create a HttpAsyncServer with HTTPS (TLS)
--
This message was sent by Atlassian Jira
(v8.3.4#803005)
---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]