[undertow-dev] Using UndertowClient from one server to call another server

Stuart Douglas sdouglas at redhat.com
Tue Aug 29 19:37:46 EDT 2017


The issue is that you are attempting to use prior knowledge to connect
to a https endpoint. HTTPS endpoints must use ALPN instead.

I did not notice you were attempting to use HTTPS in the original
issue. The code should not attempt an upgrade in this case. Is it
possible that ALPN is failing so normal HTTP/1 is used instead, then
the server closes the connection so your request fails due to the
connection being closed?

Stuart

On Wed, Aug 30, 2017 at 9:24 AM, Steve Hu <stevehu at gmail.com> wrote:
> Hi Stuart,
>
> I have created two servers with one calls another with h2c-prior to
> reproduce the issue. There is a README.md in the root folder with
> instructions.
>
> https://github.com/stevehu/server2server
>
> Thanks,
>
> Steve
>
> On Mon, Aug 28, 2017 at 11:01 PM, Stuart Douglas <sdouglas at redhat.com>
> wrote:
>>
>> That would be great. This is tested in the test suite so I am not sure why
>> it is not working for you.
>>
>> Stuart
>>
>> On 29 Aug. 2017 12:59 pm, "Steve Hu" <stevehu at gmail.com> wrote:
>>
>> Yes. It is another Undertow server with HTTP 2.0 enabled. I can build a
>> repo with two servers to reproduce the issue if it is necessary.
>>
>> Thanks,
>>
>> Steve
>>
>> On Mon, Aug 28, 2017 at 10:43 PM, Stuart Douglas <sdouglas at redhat.com>
>> wrote:
>>>
>>> What is the endpoint that you are trying to connect to? Is it another
>>> Undertow server?
>>>
>>> Stuart
>>>
>>> On Tue, Aug 29, 2017 at 12:17 PM, Steve Hu <stevehu at gmail.com> wrote:
>>> > Hi Stuart,
>>> >
>>> > Thanks for the quick reply. I have opened an issue
>>> > https://issues.jboss.org/browse/UNDERTOW-1170
>>> >
>>> > Also, I have tried your workaround with h2c-prior:// but got the
>>> > following
>>> > error in the callback.
>>> >
>>> > java.nio.channels.ClosedChannelException
>>> > at
>>> >
>>> > io.undertow.protocols.http2.Http2Channel.createStream(Http2Channel.java:827)
>>> > at
>>> >
>>> > io.undertow.client.http2.Http2ClientConnection.sendRequest(Http2ClientConnection.java:195)
>>> > at
>>> >
>>> > com.networknt.apic.handler.DataGetHandler.handleRequest(DataGetHandler.java:57)
>>> >
>>> >
>>> > On Mon, Aug 28, 2017 at 9:50 PM, Stuart Douglas <sdouglas at redhat.com>
>>> > wrote:
>>> >>
>>> >> This looks like a bug in the client with regards to how it handles
>>> >> HTTP upgrade. If the second request is added before the initial
>>> >> upgrade request is fully processed you can get this error.
>>> >>
>>> >> If you file a JIRA I will look into it. For now a possible workaround
>>> >> would be to use prior knowledge rather than upgrade (by using a URL of
>>> >> the form h2c-prior://target:p8080/whatever).
>>> >>
>>> >> Stuart
>>> >>
>>> >> On Tue, Aug 29, 2017 at 11:25 AM, Steve Hu <stevehu at gmail.com> wrote:
>>> >> > Hi,
>>> >> >
>>> >> > I am trying to use UndertowClient to call another service in the
>>> >> > current
>>> >> > service handleRequest using HTTP 2.0. If I have concurrent requests
>>> >> > to
>>> >> > the
>>> >> > current service, then I will get the following error.
>>> >> >
>>> >> > java.io.IOException: UT001033: Invalid connection state
>>> >> > at
>>> >> >
>>> >> >
>>> >> > io.undertow.client.http.HttpClientConnection.sendRequest(HttpClientConnection.java:336)
>>> >> >
>>> >> > Since HTTP 2.0 connection is multiplex, so I use instance variables
>>> >> > for
>>> >> > UndertowClient instance and ClientConnection instance and don't
>>> >> > close
>>> >> > the
>>> >> > connection for each call.
>>> >> >
>>> >> > My question is how many requests can go through the same connection?
>>> >> > Is
>>> >> > the
>>> >> > Invalid connection state caused by too many requests in the same
>>> >> > connection?
>>> >> > If yes, I can use a connection pool just like the HTTP 1.1. Also, is
>>> >> > it
>>> >> > possible that the server will close the connection if it is idle for
>>> >> > a
>>> >> > period of time?
>>> >> >
>>> >> > Here is the handler code for reference.
>>> >> >
>>> >> > public class DataGetHandler implements HttpHandler {
>>> >> >     UndertowClient client = UndertowClient.getInstance();
>>> >> >     ClientConnection connection;
>>> >> >
>>> >> >     @Override
>>> >> >     public void handleRequest(HttpServerExchange exchange) throws
>>> >> > Exception
>>> >> > {
>>> >> >         List<String> list = new ArrayList<>();
>>> >> >         final CountDownLatch latch = new CountDownLatch(1);
>>> >> >         if(connection == null) {
>>> >> >             try {
>>> >> >                 connection = client.connect(new URI(apidHost),
>>> >> > Http2Client.WORKER, Http2Client.SSL, Http2Client.POOL, enableHttp2 ?
>>> >> > OptionMap.create(UndertowOptions.ENABLE_HTTP2, true):
>>> >> > OptionMap.EMPTY).get();
>>> >> >             } catch (Exception e) {
>>> >> >                 logger.error("Exeption:", e);
>>> >> >                 throw new ClientException(e);
>>> >> >             }
>>> >> >         }
>>> >> >         final AtomicReference<ClientResponse> reference = new
>>> >> > AtomicReference<>();
>>> >> >         try {
>>> >> >             ClientRequest request = new
>>> >> > ClientRequest().setMethod(Methods.GET).setPath(apidPath);
>>> >> >             connection.sendRequest(request,
>>> >> > client.createClientCallback(reference, latch));
>>> >> >             latch.await();
>>> >> >             int statusCode = reference.get().getResponseCode();
>>> >> >             if(statusCode >= 300){
>>> >> >                 throw new Exception("Failed to call API D: " +
>>> >> > statusCode);
>>> >> >             }
>>> >> >             List<String> apidList =
>>> >> >
>>> >> >
>>> >> > Config.getInstance().getMapper().readValue(reference.get().getAttachment(Http2Client.RESPONSE_BODY),
>>> >> >                     new TypeReference<List<String>>(){});
>>> >> >             list.addAll(apidList);
>>> >> >         } catch (Exception e) {
>>> >> >             logger.error("Exception:", e);
>>> >> >             throw new ClientException(e);
>>> >> >         }
>>> >> >         list.add("API C: Message 1");
>>> >> >         list.add("API C: Message 2");
>>> >> >
>>> >> >
>>> >> >
>>> >> > exchange.getResponseSender().send(Config.getInstance().getMapper().writeValueAsString(list));
>>> >> >     }
>>> >> > }
>>> >> >
>>> >> >
>>> >> > _______________________________________________
>>> >> > undertow-dev mailing list
>>> >> > undertow-dev at lists.jboss.org
>>> >> > https://lists.jboss.org/mailman/listinfo/undertow-dev
>>> >
>>> >
>>
>>
>>
>


More information about the undertow-dev mailing list