quarkusio / quarkus-http Goto Github PK
View Code? Open in Web Editor NEWLicense: Apache License 2.0
License: Apache License 2.0
Is it possible in this time to add a 451 status code? here's my scenario.
Scenario:
As a consultant that create an application for a legal system, we may want to submit a status code of 451 for API calls that isn't allowed at this time due to a governance policy/restriction. For a better status code, I'm proposing this one.
I'm seeing that a 401 Unauthorized doesn't seem right for my use-case. Let me know for any suggestion.
NOTE: Seeing that this is supported in Spring Framework, existing Legal-based APIs that want to migrate to Quarkus could have a breaking change or will use another inappropriate code for this use-case.
The Vert.x Undertow Engine creates its own Vert.x instance using Vertx.vertx()
.
The Vert.x Quarkus extension creates another one.
That's 2, we need one.
When implementing a class like this:
public class UuidDecoder implements Decoder.TextStream<UUID>, Decoder, Decoder.Binary<UUID>, Decoder.Text<UUID> {
public UuidDecoder() {
System.out.println("OK!");
}
@Override
public void init(EndpointConfig config) {
}
@Override
public void destroy() {
}
@Override
public UUID decode(Reader reader) throws DecodeException, IOException {
return UUID.fromString(CharStreams.toString(reader));
}
@Override
public UUID decode(ByteBuffer bytes) throws DecodeException {
return UUID.fromString(new String(bytes.array()));
}
@Override
public boolean willDecode(ByteBuffer bytes) {
try {
UUID.fromString(new String(bytes.array()));
return true;
} catch (IllegalArgumentException e) {
return false;
}
}
@Override
public UUID decode(String s) throws DecodeException {
return UUID.fromString(s);
}
@Override
public boolean willDecode(String s) {
try {
UUID.fromString(s);
return true;
} catch (IllegalArgumentException e) {
return false;
}
}
}
And using it like this:
@ServerEndpoint(value = "/api/ws/search/{id}", decoders = UuidDecoder.class)
public class SearchResource {
}
Only the binary encoder/decoder is registered, since EncodingFactory
checks for interface implementations using else-if.
See https://stackoverflow.com/questions/60134388/how-to-use-custom-encoder-and-decoder-in-quarkus
I'll submit a PR to fix this.
When implementing a class like this:
public class UuidDecoder implements Decoder.Text<UUID> {
public UuidDecoder() {
System.out.println("OK!");
}
@Override
public void init(EndpointConfig config) {
}
@Override
public void destroy() {
}
@Override
public UUID decode(String s) throws DecodeException {
return UUID.fromString(s);
}
@Override
public boolean willDecode(String s) {
try {
UUID.fromString(s);
return true;
} catch (IllegalArgumentException e) {
return false;
}
}
}
And using it like this:
@ServerEndpoint(value = "/api/ws/search/{id}", decoders = UuidDecoder.class)
public class SearchResource {
}
The decoder isn't registered and the application fails with:
14:14:58,113 ERROR [io.qua.dev.DevModeMain] Failed to start Quarkus: java.lang.ExceptionInInitializerError
at java.base/java.lang.J9VMInternals.ensureError(J9VMInternals.java:193)
at java.base/java.lang.J9VMInternals.recordInitializationFailure(J9VMInternals.java:182)
at java.base/java.lang.Class.forNameImpl(Native Method)
at java.base/java.lang.Class.forName(Class.java:417)
at io.quarkus.runner.RuntimeRunner.run(RuntimeRunner.java:153)
at io.quarkus.dev.DevModeMain.doStart(DevModeMain.java:178)
at io.quarkus.dev.DevModeMain.start(DevModeMain.java:96)
at io.quarkus.dev.DevModeMain.main(DevModeMain.java:67)
Caused by: java.lang.RuntimeException: Failed to start quarkus
at io.quarkus.runner.ApplicationImpl.<clinit>(ApplicationImpl.zig:390)
... 6 more
Caused by: java.lang.RuntimeException: java.lang.RuntimeException: javax.websocket.DeploymentException: UT003028: Could not find decoder for type class java.util.UUID on method public void org.siretch.kafka.entrypoint.SearchResource.onOpen(javax.websocket.Session,java.util.UUID)
at io.quarkus.undertow.runtime.UndertowDeploymentRecorder.bootServletContainer(UndertowDeploymentRecorder.java:445)
at io.quarkus.deployment.steps.UndertowBuildStep$build32.deploy_0(UndertowBuildStep$build32.zig:171)
at io.quarkus.deployment.steps.UndertowBuildStep$build32.deploy(UndertowBuildStep$build32.zig:196)
at io.quarkus.runner.ApplicationImpl.<clinit>(ApplicationImpl.zig:376)
... 6 more
Caused by: java.lang.RuntimeException: javax.websocket.DeploymentException: UT003028: Could not find decoder for type class java.util.UUID on method public void org.siretch.kafka.entrypoint.SearchResource.onOpen(javax.websocket.Session,java.util.UUID)
at io.undertow.websockets.jsr.Bootstrap.handleDeployment(Bootstrap.java:101)
at io.undertow.servlet.core.DeploymentManagerImpl.handleExtensions(DeploymentManagerImpl.java:278)
at io.undertow.servlet.core.DeploymentManagerImpl.deploy(DeploymentManagerImpl.java:155)
at io.quarkus.undertow.runtime.UndertowDeploymentRecorder.bootServletContainer(UndertowDeploymentRecorder.java:434)
... 9 more
Caused by: javax.websocket.DeploymentException: UT003028: Could not find decoder for type class java.util.UUID on method public void org.siretch.kafka.entrypoint.SearchResource.onOpen(javax.websocket.Session,java.util.UUID)
at io.undertow.websockets.jsr.annotated.AnnotatedEndpointFactory$BoundPathParameters.<init>(AnnotatedEndpointFactory.java:399)
at io.undertow.websockets.jsr.annotated.AnnotatedEndpointFactory.createBoundPathParameters(AnnotatedEndpointFactory.java:258)
at io.undertow.websockets.jsr.annotated.AnnotatedEndpointFactory.create(AnnotatedEndpointFactory.java:100)
at io.undertow.websockets.jsr.ServerWebSocketContainer.addEndpointInternal(ServerWebSocketContainer.java:681)
at io.undertow.websockets.jsr.ServerWebSocketContainer.addEndpoint(ServerWebSocketContainer.java:654)
at io.undertow.websockets.jsr.Bootstrap.handleDeployment(Bootstrap.java:95)
... 12 more
See https://stackoverflow.com/questions/60134388/how-to-use-custom-encoder-and-decoder-in-quarkus
I'll submit a PR to fix this.
Describe the bug
Server (or Client) sends WebSocket Ping. Other end should Pong automatically but does not.
This prevents proper management of slow/dead consumers etc.
Quarkus 1.4.2
To Reproduce
Modified websockets-quickstart attached.
At https://github.com/quarkusio/quarkus-http/blob/main/core/src/main/java/io/undertow/server/handlers/ProxyPeerAddressHandler.java#L118, the following method extract the left-most IP address in case X-Forwarded-For
contains a comma-separated list of addresses:
private String mostRecent(String header) {
int index = header.indexOf(',');
if (index == -1) {
return header;
} else {
return header.substring(0, index);
}
}
Based on the method name (mostRecent
), my understanding is that it's actually the right-most address that should be used in this case.
Judging from information contained in the following links, the X-Forwarded-For
header is a real hornet's nest:
This code is obviously not going to solve the complexity around this header, but at least it should return the actually most recent address in the path.
For the record, I ran into this while trying to get Keycloak display the IP address of HTTP clients, when sitting behind Cloudflare.
In this case, Cloudflare guarantees that the right-most value in X-Forwarded-For
can be trusted as they append the origin IP address at the end of the list (https://developers.cloudflare.com/fundamentals/reference/http-request-headers/#x-forwarded-for).
Hello, I am not a specialist in this question, but It seemed I have a problem because Quarkus does not support SNI extension in SSL. Although I tested it with HTTP rest-client and there were no problems.
Details:
*I have a the same problem, the same message and the same difference between rest's logs and websocket's logs:
*** ClientHello, TLSv1.2
RandomCookie: GMT: 1571238552 bytes = { 125, 241, 169, 6, 39, 103, 208, 112, 16, 73, 146, 115, 185, 122, 155, 35, 69, 225, 103, 209, 161, 159, 5, 137, 54, 165, 78, 99 }
Session ID: {}
Cipher Suites: [TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256, TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256, TLS_RSA_WITH_AES_128_CBC_SHA256, TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA256, TLS_ECDH_RSA_WITH_AES_128_CBC_SHA256, TLS_DHE_RSA_WITH_AES_128_CBC_SHA256, TLS_DHE_DSS_WITH_AES_128_CBC_SHA256, TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA, TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA, TLS_RSA_WITH_AES_128_CBC_SHA, TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA, TLS_ECDH_RSA_WITH_AES_128_CBC_SHA, TLS_DHE_RSA_WITH_AES_128_CBC_SHA, TLS_DHE_DSS_WITH_AES_128_CBC_SHA, TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256, TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256, TLS_RSA_WITH_AES_128_GCM_SHA256, TLS_ECDH_ECDSA_WITH_AES_128_GCM_SHA256, TLS_ECDH_RSA_WITH_AES_128_GCM_SHA256, TLS_DHE_RSA_WITH_AES_128_GCM_SHA256, TLS_DHE_DSS_WITH_AES_128_GCM_SHA256, TLS_ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA, TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA, SSL_RSA_WITH_3DES_EDE_CBC_SHA, TLS_ECDH_ECDSA_WITH_3DES_EDE_CBC_SHA, TLS_ECDH_RSA_WITH_3DES_EDE_CBC_SHA, SSL_DHE_RSA_WITH_3DES_EDE_CBC_SHA, SSL_DHE_DSS_WITH_3DES_EDE_CBC_SHA, TLS_EMPTY_RENEGOTIATION_INFO_SCSV]
Compression Methods: { 0 }
Extension elliptic_curves, curve names: {secp256r1, secp384r1, secp521r1, sect283k1, sect283r1, sect409k1, sect409r1, sect571k1, sect571r1, secp256k1}
Extension ec_point_formats, formats: [uncompressed]
Extension signature_algorithms, signature_algorithms: SHA512withECDSA, SHA512withRSA, SHA384withECDSA, SHA384withRSA, SHA256withECDSA, SHA256withRSA, SHA256withDSA, SHA1withECDSA, SHA1withRSA, SHA1withDSA
***
vs
*** ClientHello, TLSv1.2
RandomCookie: GMT: 1571238202 bytes = { 191, 255, 75, 40, 82, 20, 198, 108, 27, 89, 101, 152, 184, 97, 12, 203, 201, 86, 244, 33, 33, 22, 183, 124, 59, 107, 104, 109 }
Session ID: {}
Cipher Suites: [TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256, TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256, TLS_RSA_WITH_AES_128_CBC_SHA256, TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA256, TLS_ECDH_RSA_WITH_AES_128_CBC_SHA256, TLS_DHE_RSA_WITH_AES_128_CBC_SHA256, TLS_DHE_DSS_WITH_AES_128_CBC_SHA256, TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA, TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA, TLS_RSA_WITH_AES_128_CBC_SHA, TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA, TLS_ECDH_RSA_WITH_AES_128_CBC_SHA, TLS_DHE_RSA_WITH_AES_128_CBC_SHA, TLS_DHE_DSS_WITH_AES_128_CBC_SHA, TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256, TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256, TLS_RSA_WITH_AES_128_GCM_SHA256, TLS_ECDH_ECDSA_WITH_AES_128_GCM_SHA256, TLS_ECDH_RSA_WITH_AES_128_GCM_SHA256, TLS_DHE_RSA_WITH_AES_128_GCM_SHA256, TLS_DHE_DSS_WITH_AES_128_GCM_SHA256, TLS_ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA, TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA, SSL_RSA_WITH_3DES_EDE_CBC_SHA, TLS_ECDH_ECDSA_WITH_3DES_EDE_CBC_SHA, TLS_ECDH_RSA_WITH_3DES_EDE_CBC_SHA, SSL_DHE_RSA_WITH_3DES_EDE_CBC_SHA, SSL_DHE_DSS_WITH_3DES_EDE_CBC_SHA, TLS_EMPTY_RENEGOTIATION_INFO_SCSV]
Compression Methods: { 0 }
Extension elliptic_curves, curve names: {secp256r1, secp384r1, secp521r1, sect283k1, sect283r1, sect409k1, sect409r1, sect571k1, sect571r1, secp256k1}
Extension ec_point_formats, formats: [uncompressed]
Extension signature_algorithms, signature_algorithms: SHA512withECDSA, SHA512withRSA, SHA384withECDSA, SHA384withRSA, SHA256withECDSA, SHA256withRSA, SHA256withDSA, SHA1withECDSA, SHA1withRSA, SHA1withDSA
Extension server_name, server_name: [type=host_name (0), value=myhost.com]
***
I decided to find where this extension is set in vertex (because HTTP rest-client works):
But in websockets-jsr I can't see any mentions of SNI and SSLEngine is created without host and port:
But I decided to check how things are going here: https://github.com/undertow-io/undertow/
And found that they suggest some SNISSLContextSpi
Could you help with an answer if it is a bug, or not?
I use OpenShift. URLs in routes do not have ports. They look like https://domain-a.corp.org
. So in java URL object port is -1. But netty does not support this .
Caused by: java.lang.IllegalArgumentException: port out of range:-1
at java.net.InetSocketAddress.checkPort(InetSocketAddress.java:143)
at java.net.InetSocketAddress.createUnresolved(InetSocketAddress.java:254)
at io.netty.bootstrap.Bootstrap.connect(Bootstrap.java:123)
at io.undertow.websockets.jsr.WebsocketConnectionBuilder.connect(WebsocketConnectionBuilder.java:202)
at io.undertow.websockets.jsr.ServerWebSocketContainer.connectToServerInternal(ServerWebSocketContainer.java:543)
at io.undertow.websockets.jsr.ServerWebSocketContainer.connectToServerInternal(ServerWebSocketContainer.java:520)
at io.undertow.websockets.jsr.ServerWebSocketContainer.connectToServer(ServerWebSocketContainer.java:279)
at mapackage.TestWebSocketService.connect(TestWebSocketService.java:32)
I found some mapping in undertow(original):
But it seems in quarkus there is no similar code
Related to the discussion we are having on OIDC authentication for websockets doesn't work in 1.13.*
, getUserPrincipal
is not yet implemented which is a useful functionality. This is the comment I left originally there:
Playing around with the code, inside VertxWebSocketHttpExchange
we do have access to the original RoutingContext
in the class attribute exchange
.
Upon closer inspection, I can see the principal
is correctly populated inside the exchange.data()
map like we can see below:
Is it safe to assume that we can return directly that object in method getUserPrincipal
? Or is there any other implication I'm not taking into account (which will be probably)?
Something like:
If needed I can prepare the PR with proper guidance.
When using Undertow, a request with more than 1,000 parameters triggers a io.undertow.util.ParameterLimitException
. While that's a reasonable default, I have a need to configure it. (A JSF application I am porting to Quarkus via the MyFaces Quarkus extension generates very large requests.)
Undertow provides a way of providing it with an UndertowOptionMap
, one key of which is MAX_PARAMETERS
. It would be nice if there were a way of setting it through application.properties
.
Hello,
in the Websocket Undertow adoption when an underlying Netty channel is (half) closed it is still possible to receive Websocket messages.
This is a known problem (see https://issues.redhat.com/browse/UNDERTOW-617) and the solution for messages passed on is to drop them in this case (fixed in f145e9c).
However Ping messages are still responded to (See https://github.com/quarkusio/quarkus-http/blob/main/websocket/core/src/main/java/io/undertow/websockets/FrameHandler.java#L139). In this case the Websocket connection is kept alive by the response but the implementation here drops other messages leading to a broken inconsistent state.
To be consistent pings should not be responded to as well.
I would propose a similar private handler method, that uses the same drop message mechanism.
This way the behavior is consistent and a client may even detect broken connections.
Since undertow version 2.1.0.Final (feature UNDERTOW-1600), Undertow supports SameSite=None
attributes in cookies, through the SameSiteCookieHandler
.
Unfortunately, it seems that quarkus-http has been left behind with undertow's latest developments.
Are there any plans to catch up with undertow's latest versions, or otherwise is there any other way to enable the SameSite=None
cookie attribute with Quarkus when using Undertow?
Most probably this is cause of our issue with Quarkus quarkusio/quarkus#33885
A declarative, efficient, and flexible JavaScript library for building user interfaces.
๐ Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. ๐๐๐
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google โค๏ธ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.