TcpClient - how to send messages and receive responses? - reactor-netty

I want to do something like below:
TcpClient client = init();
String response1 = sendMsg(TcpClient client, String msg1);
String response2 = sendMsg(TcpClient client, String msg2);
close(TcpClient client);
appreciate any responses.
My unit test is below:
#Test
public void tcpServerHandlesTlvOverSsl() throws Exception {
final CountDownLatch latch = new CountDownLatch(3);
SelfSignedCertificate cert = new SelfSignedCertificate();
SslContextBuilder serverOptions = SslContextBuilder.forServer(cert.certificate(), cert.privateKey());
SslContext clientOptions = SslContextBuilder.forClient()
.trustManager(InsecureTrustManagerFactory.INSTANCE)
.build();
final TcpServer server =
TcpServer.create()
.host("localhost")
.secure(sslContextSpec -> sslContextSpec.sslContext(serverOptions));
// this is an relay tcp server
DisposableServer connectedServer =
server
.doOnConnection(connection -> {
// tlv is our customized protocol
connection.addHandlerLast("tlvEncoder", new TlvEncoder());
connection.addHandlerLast("tlvDecoder", new TlvDecoder());
// something like creating a new tcp client to the target server should be done here
})
.handle((in, out) ->
out.sendObject(
in
.receiveObject()
.log("[Server received]")
.ofType(TlvMessage.class)
.flatMap(tlv -> {
// do some work on each received message
fixTlv(tlv);
log.debug("Server fixed the tlv message: {}", tlv.toString());
return Mono.just(tlv);
})
.doOnNext(tlv -> {
if (isLegalType(tlv.getType())) {
latch.countDown();
}
// then forward the fixed tlv message to the target server by using the new created tcp client
log.debug("Server forwards to the target server: {}", tlv.toString());
// do something else with the response from the target server
if (TYPE_UPSTREAM_FINISH == tlv.getType()) {
// the closing flag is accounted
log.debug("Server closing client to the target server.");
// closing the new created tcp client to the target server
}
})
)
)
.wiretap(true)
.bindNow();
assertNotNull(connectedServer);
// simulating a client to the relay server
final TcpClient client = TcpClient.create()
.host("localhost")
.port(connectedServer.address().getPort())
.secure(spec -> spec.sslContext(clientOptions));
Connection connectedClient = client
.doOnConnected(connection -> {
connection.addHandlerLast("tlvEncoder", new TlvEncoder());
connection.addHandlerLast("tlvDecoder", new TlvDecoder());
})
.doOnDisconnected(connection -> log.info("Client disconnected"))
.option(ChannelOption.SO_KEEPALIVE, true)
.handle((in, out) -> {
in
.receiveObject()
.log("[Client received]")
.ofType(TlvMessage.class)
.doOnNext(tlv -> {
// do some work on each response from the relay server
if (isLegalType(tlv.getType())) {
latch.countDown();
}
});
return out
// simulating requests to the relay server
.sendObject(Flux.just(
demo(TYPE_UPSTREAM_INIT, "{\"param\":\"{\\\"device-id\\\":\\\"3F1806118800C678\\\"}\",\"pid\":\"-1001\",\"clientip\":\"xxx.xxx.xxx.xxx\",\"sn\":\"91598059-4d06-447a-878f-551637bcaf89_7\"}"),
demo(TYPE_UPSTREAM_FINISH, "{\"param\":\"{\\\"device-id\\\":\\\"3A1806118800C678\\\"}\",\"pid\":\"-1002\",\"clientip\":\"xxx.xxx.xxx.xxx\"}")
)
)
.neverComplete();
}
)
.wiretap(true)
.connectNow();
assertNotNull(connectedClient);
Thread.sleep(3000);
log.info("Client sends object after 3 seconds.");
connectedClient.outbound().sendObject(
Flux.just(
demo(TYPE_UPSTREAM_INIT, "{\"param\":\"{\\\"device-id\\\":\\\"3B1806118800C678\\\"}\",\"pid\":\"-1003\",\"clientip\":\"xxx.xxx.xxx.xxx\",\"sn\":\"91598059-dd06-447a-878f-551637bcaf89_7\"}"),
demo(TYPE_UPSTREAM_FINISH, "{\"param\":\"{\\\"device-id\\\":\\\"3C1806118800C678\\\"}\",\"pid\":\"-1004\",\"clientip\":\"xxx.xxx.xxx.xxx\"}")
)
);
assertTrue("Latch was counted down", latch.await(5, TimeUnit.SECONDS));
connectedClient.disposeNow();
connectedServer.disposeNow();
}
The demo method is used to assemble a tlv(our customized protocol) object.
The key logs are the below:
17:16:21.104 [reactor-tcp-nio-1] DEBUG reactor.netty.tcp.TcpClient - [id: 0x019c3187] REGISTERED
17:16:21.105 [reactor-tcp-nio-1] DEBUG reactor.netty.tcp.TcpClient - [id: 0x019c3187] CONNECT: localhost/127.0.0.1:60092
17:16:21.117 [reactor-tcp-nio-2] DEBUG reactor.netty.tcp.SslProvider - [id: 0x424c0204, L:/127.0.0.1:60092 - R:/127.0.0.1:60093] SSL enabled using engine SSLEngineImpl
17:16:21.118 [reactor-tcp-nio-2] DEBUG reactor.netty.channel.BootstrapHandlers - [id: 0x424c0204, L:/127.0.0.1:60092 - R:/127.0.0.1:60093] Initialized pipeline DefaultChannelPipeline{(reactor.left.sslHandler = io.netty.handler.ssl.SslHandler), (reactor.left.loggingHandler = io.netty.handler.logging.LoggingHandler), (reactor.left.sslReader = reactor.netty.tcp.SslProvider$SslReadHandler), (BootstrapHandlers$BootstrapInitializerHandler#0 = reactor.netty.channel.BootstrapHandlers$BootstrapInitializerHandler), (reactor.right.reactiveBridge = reactor.netty.channel.ChannelOperationsHandler)}
17:16:21.121 [reactor-tcp-nio-2] DEBUG reactor.netty.tcp.TcpServer - [id: 0x424c0204, L:/127.0.0.1:60092 - R:/127.0.0.1:60093] REGISTERED
17:16:21.121 [reactor-tcp-nio-2] DEBUG reactor.netty.tcp.TcpServer - [id: 0x424c0204, L:/127.0.0.1:60092 - R:/127.0.0.1:60093] ACTIVE
17:16:21.170 [reactor-tcp-nio-1] DEBUG io.netty.util.Recycler - -Dio.netty.recycler.maxCapacityPerThread: 4096
17:16:21.170 [reactor-tcp-nio-1] DEBUG io.netty.util.Recycler - -Dio.netty.recycler.maxSharedCapacityFactor: 2
17:16:21.170 [reactor-tcp-nio-1] DEBUG io.netty.util.Recycler - -Dio.netty.recycler.linkCapacity: 16
17:16:21.170 [reactor-tcp-nio-1] DEBUG io.netty.util.Recycler - -Dio.netty.recycler.ratio: 8
17:16:21.186 [reactor-tcp-nio-1] DEBUG reactor.netty.tcp.TcpClient - [id: 0x019c3187, L:/127.0.0.1:60093 - R:localhost/127.0.0.1:60092] ACTIVE
17:16:21.186 [reactor-tcp-nio-1] DEBUG reactor.netty.resources.PooledConnectionProvider - [id: 0x019c3187, L:/127.0.0.1:60093 - R:localhost/127.0.0.1:60092] Registering pool release on close event for channel
17:16:21.188 [reactor-tcp-nio-1] DEBUG reactor.netty.resources.PooledConnectionProvider - [id: 0x019c3187, L:/127.0.0.1:60093 - R:localhost/127.0.0.1:60092] Channel connected, now 1 active connections and 0 inactive connections
17:16:21.202 [reactor-tcp-nio-2] DEBUG reactor.netty.tcp.TcpServer - [id: 0x424c0204, L:/127.0.0.1:60092 - R:/127.0.0.1:60093] READ COMPLETE
17:16:21.203 [reactor-tcp-nio-1] DEBUG io.netty.handler.ssl.util.InsecureTrustManagerFactory - Accepting a server certificate: CN=example.com
17:16:21.241 [reactor-tcp-nio-1] DEBUG reactor.netty.tcp.TcpClient - [id: 0x019c3187, L:/127.0.0.1:60093 - R:localhost/127.0.0.1:60092] READ COMPLETE
17:16:21.247 [reactor-tcp-nio-2] DEBUG io.netty.handler.ssl.SslHandler - [id: 0x424c0204, L:/127.0.0.1:60092 - R:/127.0.0.1:60093] HANDSHAKEN: TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256
17:16:21.248 [reactor-tcp-nio-2] DEBUG reactor.netty.tcp.TcpServer - [id: 0x424c0204, L:/127.0.0.1:60092 - R:/127.0.0.1:60093] USER_EVENT: SslHandshakeCompletionEvent(SUCCESS)
17:16:21.350 [reactor-tcp-nio-2] DEBUG reactor.netty.ReactorNetty - [id: 0x424c0204, L:/127.0.0.1:60092 - R:/127.0.0.1:60093] Added decoder [tlvEncoder] at the end of the user pipeline, full pipeline: [reactor.left.sslHandler, reactor.left.loggingHandler, tlvEncoder, reactor.right.reactiveBridge, DefaultChannelPipeline$TailContext#0]
17:16:21.351 [reactor-tcp-nio-2] DEBUG reactor.netty.ReactorNetty - [id: 0x424c0204, L:/127.0.0.1:60092 - R:/127.0.0.1:60093] Added decoder [tlvDecoder] at the end of the user pipeline, full pipeline: [reactor.left.sslHandler, reactor.left.loggingHandler, tlvEncoder, tlvDecoder, reactor.right.reactiveBridge, DefaultChannelPipeline$TailContext#0]
17:16:21.351 [reactor-tcp-nio-2] DEBUG reactor.netty.tcp.TcpServer - [id: 0x424c0204, L:/127.0.0.1:60092 - R:/127.0.0.1:60093] Handler is being applied: com.baidu.iot.devicecloud.devicemanager.TcpServerTests$$Lambda$7/824208363#3252dfd9
17:16:21.367 [reactor-tcp-nio-2] DEBUG reactor.netty.channel.ChannelOperationsHandler - [id: 0x424c0204, L:/127.0.0.1:60092 - R:/127.0.0.1:60093] Writing object
17:16:21.375 [reactor-tcp-nio-2] DEBUG reactor.netty.channel.FluxReceive - [id: 0x424c0204, L:/127.0.0.1:60092 - R:/127.0.0.1:60093] Subscribing inbound receiver [pending: 0, cancelled:false, inboundDone: false]
17:16:21.377 [reactor-tcp-nio-2] INFO [Server received] - onSubscribe(FluxReceive)
17:16:21.379 [reactor-tcp-nio-2] INFO [Server received] - request(256)
17:16:21.380 [reactor-tcp-nio-2] DEBUG reactor.netty.tcp.TcpServer - [id: 0x424c0204, L:/127.0.0.1:60092 - R:/127.0.0.1:60093] READ COMPLETE
17:16:21.381 [reactor-tcp-nio-1] DEBUG io.netty.handler.ssl.SslHandler - [id: 0x019c3187, L:/127.0.0.1:60093 - R:localhost/127.0.0.1:60092] HANDSHAKEN: TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256
17:16:21.381 [reactor-tcp-nio-1] DEBUG reactor.netty.tcp.TcpClient - [id: 0x019c3187, L:/127.0.0.1:60093 - R:localhost/127.0.0.1:60092] USER_EVENT: SslHandshakeCompletionEvent(SUCCESS)
17:16:21.381 [reactor-tcp-nio-1] DEBUG reactor.netty.resources.PooledConnectionProvider - [id: 0x019c3187, L:/127.0.0.1:60093 - R:localhost/127.0.0.1:60092] onStateChange(PooledConnection{channel=[id: 0x019c3187, L:/127.0.0.1:60093 - R:localhost/127.0.0.1:60092]}, [connected])
17:16:21.381 [reactor-tcp-nio-1] DEBUG reactor.netty.resources.PooledConnectionProvider - [id: 0x019c3187, L:/127.0.0.1:60093 - R:localhost/127.0.0.1:60092] onStateChange(ChannelOperations{PooledConnection{channel=[id: 0x019c3187, L:/127.0.0.1:60093 - R:localhost/127.0.0.1:60092]}}, [configured])
17:16:21.381 [reactor-tcp-nio-1] DEBUG reactor.netty.ReactorNetty - [id: 0x019c3187, L:/127.0.0.1:60093 - R:localhost/127.0.0.1:60092] Added decoder [tlvEncoder] at the end of the user pipeline, full pipeline: [reactor.left.sslHandler, reactor.left.loggingHandler, tlvEncoder, reactor.right.reactiveBridge, DefaultChannelPipeline$TailContext#0]
17:16:21.382 [reactor-tcp-nio-1] DEBUG reactor.netty.ReactorNetty - [id: 0x019c3187, L:/127.0.0.1:60093 - R:localhost/127.0.0.1:60092] Added decoder [tlvDecoder] at the end of the user pipeline, full pipeline: [reactor.left.sslHandler, reactor.left.loggingHandler, tlvEncoder, tlvDecoder, reactor.right.reactiveBridge, DefaultChannelPipeline$TailContext#0]
17:16:21.382 [reactor-tcp-nio-1] DEBUG reactor.netty.tcp.TcpClient - [id: 0x019c3187, L:/127.0.0.1:60093 - R:localhost/127.0.0.1:60092] Handler is being applied: com.baidu.iot.devicecloud.devicemanager.TcpServerTests$$Lambda$27/1754662105#7f8c9193
17:16:21.652 [reactor-tcp-nio-1] DEBUG reactor.netty.channel.ChannelOperationsHandler - [id: 0x019c3187, L:/127.0.0.1:60093 - R:localhost/127.0.0.1:60092] Writing object
17:16:21.662 [reactor-tcp-nio-1] DEBUG reactor.netty.tcp.TcpClient - [id: 0x019c3187, L:/127.0.0.1:60093 - R:localhost/127.0.0.1:60092] WRITE: 143B
+-------------------------------------------------+
| 0 1 2 3 4 5 6 7 8 9 a b c d e f |
+--------+-------------------------------------------------+----------------+
|00000000| 01 00 89 00 00 00 7b 22 70 61 72 61 6d 22 3a 22 |......{"param":"|
|00000010| 7b 5c 22 64 65 76 69 63 65 2d 69 64 5c 22 3a 5c |{\"device-id\":\|
|00000020| 22 33 46 31 38 30 36 31 31 38 38 30 30 43 36 37 |"3F1806118800C67|
|00000030| 38 5c 22 7d 22 2c 22 70 69 64 22 3a 22 2d 31 30 |8\"}","pid":"-10|
|00000040| 30 31 22 2c 22 63 6c 69 65 6e 74 69 70 22 3a 22 |01","clientip":"|
|00000050| 78 78 78 2e 78 78 78 2e 78 78 78 2e 78 78 78 22 |xxx.xxx.xxx.xxx"|
|00000060| 2c 22 73 6e 22 3a 22 39 31 35 39 38 30 35 39 2d |,"sn":"91598059-|
|00000070| 34 64 30 36 2d 34 34 37 61 2d 38 37 38 66 2d 35 |4d06-447a-878f-5|
|00000080| 35 31 36 33 37 62 63 61 66 38 39 5f 37 22 7d |51637bcaf89_7"} |
+--------+-------------------------------------------------+----------------+
17:16:21.664 [reactor-tcp-nio-1] DEBUG reactor.netty.tcp.TcpClient - [id: 0x019c3187, L:/127.0.0.1:60093 - R:localhost/127.0.0.1:60092] WRITE: 97B
+-------------------------------------------------+
| 0 1 2 3 4 5 6 7 8 9 a b c d e f |
+--------+-------------------------------------------------+----------------+
|00000000| 04 00 5b 00 00 00 7b 22 70 61 72 61 6d 22 3a 22 |..[...{"param":"|
|00000010| 7b 5c 22 64 65 76 69 63 65 2d 69 64 5c 22 3a 5c |{\"device-id\":\|
|00000020| 22 33 41 31 38 30 36 31 31 38 38 30 30 43 36 37 |"3A1806118800C67|
|00000030| 38 5c 22 7d 22 2c 22 70 69 64 22 3a 22 2d 31 30 |8\"}","pid":"-10|
|00000040| 30 32 22 2c 22 63 6c 69 65 6e 74 69 70 22 3a 22 |02","clientip":"|
|00000050| 78 78 78 2e 78 78 78 2e 78 78 78 2e 78 78 78 22 |xxx.xxx.xxx.xxx"|
|00000060| 7d |} |
+--------+-------------------------------------------------+----------------+
17:16:21.664 [reactor-tcp-nio-1] DEBUG reactor.netty.tcp.TcpClient - [id: 0x019c3187, L:/127.0.0.1:60093 - R:localhost/127.0.0.1:60092] FLUSH
17:16:21.666 [reactor-tcp-nio-2] DEBUG reactor.netty.tcp.TcpServer - [id: 0x424c0204, L:/127.0.0.1:60092 - R:/127.0.0.1:60093] READ: 240B
+-------------------------------------------------+
| 0 1 2 3 4 5 6 7 8 9 a b c d e f |
+--------+-------------------------------------------------+----------------+
|00000000| 01 00 89 00 00 00 7b 22 70 61 72 61 6d 22 3a 22 |......{"param":"|
|00000010| 7b 5c 22 64 65 76 69 63 65 2d 69 64 5c 22 3a 5c |{\"device-id\":\|
|00000020| 22 33 46 31 38 30 36 31 31 38 38 30 30 43 36 37 |"3F1806118800C67|
|00000030| 38 5c 22 7d 22 2c 22 70 69 64 22 3a 22 2d 31 30 |8\"}","pid":"-10|
|00000040| 30 31 22 2c 22 63 6c 69 65 6e 74 69 70 22 3a 22 |01","clientip":"|
|00000050| 78 78 78 2e 78 78 78 2e 78 78 78 2e 78 78 78 22 |xxx.xxx.xxx.xxx"|
|00000060| 2c 22 73 6e 22 3a 22 39 31 35 39 38 30 35 39 2d |,"sn":"91598059-|
|00000070| 34 64 30 36 2d 34 34 37 61 2d 38 37 38 66 2d 35 |4d06-447a-878f-5|
|00000080| 35 31 36 33 37 62 63 61 66 38 39 5f 37 22 7d 04 |51637bcaf89_7"}.|
|00000090| 00 5b 00 00 00 7b 22 70 61 72 61 6d 22 3a 22 7b |.[...{"param":"{|
|000000a0| 5c 22 64 65 76 69 63 65 2d 69 64 5c 22 3a 5c 22 |\"device-id\":\"|
|000000b0| 33 41 31 38 30 36 31 31 38 38 30 30 43 36 37 38 |3A1806118800C678|
|000000c0| 5c 22 7d 22 2c 22 70 69 64 22 3a 22 2d 31 30 30 |\"}","pid":"-100|
|000000d0| 32 22 2c 22 63 6c 69 65 6e 74 69 70 22 3a 22 78 |2","clientip":"x|
|000000e0| 78 78 2e 78 78 78 2e 78 78 78 2e 78 78 78 22 7d |xx.xxx.xxx.xxx"}|
+--------+-------------------------------------------------+----------------+
17:16:21.667 [reactor-tcp-nio-1] DEBUG reactor.netty.tcp.TcpClient - [id: 0x019c3187, L:/127.0.0.1:60093 - R:localhost/127.0.0.1:60092] READ COMPLETE
17:16:21.667 [reactor-tcp-nio-2] DEBUG com.baidu.iot.devicecloud.devicemanager.handler.TlvDecoder - TlvDecoder read type: 1
17:16:21.667 [reactor-tcp-nio-2] DEBUG com.baidu.iot.devicecloud.devicemanager.handler.TlvDecoder - TlvDecoder read length: 137
17:16:21.668 [reactor-tcp-nio-2] DEBUG com.baidu.iot.devicecloud.devicemanager.handler.TlvDecoder - TlvDecoder read data success: {"param":"{\"device-id\":\"3F1806118800C678\"}","pid":"-1001","clientip":"xxx.xxx.xxx.xxx","sn":"91598059-4d06-447a-878f-551637bcaf89_7"}
17:16:21.668 [reactor-tcp-nio-2] DEBUG com.baidu.iot.devicecloud.devicemanager.handler.TlvDecoder - TlvDecoder read type: 4
17:16:21.668 [reactor-tcp-nio-2] DEBUG com.baidu.iot.devicecloud.devicemanager.handler.TlvDecoder - TlvDecoder read length: 91
17:16:21.668 [reactor-tcp-nio-2] DEBUG com.baidu.iot.devicecloud.devicemanager.handler.TlvDecoder - TlvDecoder read data success: {"param":"{\"device-id\":\"3A1806118800C678\"}","pid":"-1002","clientip":"xxx.xxx.xxx.xxx"}
17:16:21.669 [reactor-tcp-nio-2] INFO [Server received] - onNext(TlvMessage(type=1, length=137, value={"param":"{\"device-id\":\"3F1806118800C678\"}","pid":"-1001","clientip":"xxx.xxx.xxx.xxx","sn":"91598059-4d06-447a-878f-551637bcaf89_7"}))
17:16:21.670 [reactor-tcp-nio-2] DEBUG com.baidu.iot.devicecloud.devicemanager.TcpServerTests - Server fixed the tlv message: TlvMessage(type=1, length=157, value={"param":"{\"device-id\":\"3F1806118800C678\"}","pid":"-1001","clientip":"xxx.xxx.xxx.xxx","sn":"91598059-4d06-447a-878f-551637bcaf89_7","fixed":"by server"})
17:16:21.671 [reactor-tcp-nio-2] DEBUG com.baidu.iot.devicecloud.devicemanager.TcpServerTests - Server forwards to the target server: TlvMessage(type=1, length=157, value={"param":"{\"device-id\":\"3F1806118800C678\"}","pid":"-1001","clientip":"xxx.xxx.xxx.xxx","sn":"91598059-4d06-447a-878f-551637bcaf89_7","fixed":"by server"})
17:16:21.671 [reactor-tcp-nio-2] DEBUG reactor.netty.tcp.TcpServer - [id: 0x424c0204, L:/127.0.0.1:60092 - R:/127.0.0.1:60093] WRITE: 163B
+-------------------------------------------------+
| 0 1 2 3 4 5 6 7 8 9 a b c d e f |
+--------+-------------------------------------------------+----------------+
|00000000| 01 00 9d 00 00 00 7b 22 70 61 72 61 6d 22 3a 22 |......{"param":"|
|00000010| 7b 5c 22 64 65 76 69 63 65 2d 69 64 5c 22 3a 5c |{\"device-id\":\|
|00000020| 22 33 46 31 38 30 36 31 31 38 38 30 30 43 36 37 |"3F1806118800C67|
|00000030| 38 5c 22 7d 22 2c 22 70 69 64 22 3a 22 2d 31 30 |8\"}","pid":"-10|
|00000040| 30 31 22 2c 22 63 6c 69 65 6e 74 69 70 22 3a 22 |01","clientip":"|
|00000050| 78 78 78 2e 78 78 78 2e 78 78 78 2e 78 78 78 22 |xxx.xxx.xxx.xxx"|
|00000060| 2c 22 73 6e 22 3a 22 39 31 35 39 38 30 35 39 2d |,"sn":"91598059-|
|00000070| 34 64 30 36 2d 34 34 37 61 2d 38 37 38 66 2d 35 |4d06-447a-878f-5|
|00000080| 35 31 36 33 37 62 63 61 66 38 39 5f 37 22 2c 22 |51637bcaf89_7","|
|00000090| 66 69 78 65 64 22 3a 22 62 79 20 73 65 72 76 65 |fixed":"by serve|
|000000a0| 72 22 7d |r"} |
+--------+-------------------------------------------------+----------------+
17:16:21.671 [reactor-tcp-nio-2] INFO [Server received] - onNext(TlvMessage(type=4, length=91, value={"param":"{\"device-id\":\"3A1806118800C678\"}","pid":"-1002","clientip":"xxx.xxx.xxx.xxx"}))
17:16:21.671 [reactor-tcp-nio-2] DEBUG com.baidu.iot.devicecloud.devicemanager.TcpServerTests - Server fixed the tlv message: TlvMessage(type=4, length=111, value={"param":"{\"device-id\":\"3A1806118800C678\"}","pid":"-1002","clientip":"xxx.xxx.xxx.xxx","fixed":"by server"})
17:16:21.671 [reactor-tcp-nio-2] DEBUG com.baidu.iot.devicecloud.devicemanager.TcpServerTests - Server forwards to the target server: TlvMessage(type=4, length=111, value={"param":"{\"device-id\":\"3A1806118800C678\"}","pid":"-1002","clientip":"xxx.xxx.xxx.xxx","fixed":"by server"})
17:16:21.671 [reactor-tcp-nio-2] DEBUG com.baidu.iot.devicecloud.devicemanager.TcpServerTests - Server closing client to the target server.
17:16:21.672 [reactor-tcp-nio-2] DEBUG reactor.netty.tcp.TcpServer - [id: 0x424c0204, L:/127.0.0.1:60092 - R:/127.0.0.1:60093] WRITE: 117B
+-------------------------------------------------+
| 0 1 2 3 4 5 6 7 8 9 a b c d e f |
+--------+-------------------------------------------------+----------------+
|00000000| 04 00 6f 00 00 00 7b 22 70 61 72 61 6d 22 3a 22 |..o...{"param":"|
|00000010| 7b 5c 22 64 65 76 69 63 65 2d 69 64 5c 22 3a 5c |{\"device-id\":\|
|00000020| 22 33 41 31 38 30 36 31 31 38 38 30 30 43 36 37 |"3A1806118800C67|
|00000030| 38 5c 22 7d 22 2c 22 70 69 64 22 3a 22 2d 31 30 |8\"}","pid":"-10|
|00000040| 30 32 22 2c 22 63 6c 69 65 6e 74 69 70 22 3a 22 |02","clientip":"|
|00000050| 78 78 78 2e 78 78 78 2e 78 78 78 2e 78 78 78 22 |xxx.xxx.xxx.xxx"|
|00000060| 2c 22 66 69 78 65 64 22 3a 22 62 79 20 73 65 72 |,"fixed":"by ser|
|00000070| 76 65 72 22 7d |ver"} |
+--------+-------------------------------------------------+----------------+
17:16:21.672 [reactor-tcp-nio-2] DEBUG reactor.netty.tcp.TcpServer - [id: 0x424c0204, L:/127.0.0.1:60092 - R:/127.0.0.1:60093] READ COMPLETE
17:16:24.384 [main] INFO com.baidu.iot.devicecloud.devicemanager.TcpServerTests - Client sends object after 3 seconds.
java.lang.AssertionError: Latch was counted down
Process finished with exit code -1
The created TcpClient doesn't work well, and I don't know how to correct, could someone point me a way to do this correctly.

There are two issues that I can see in your code:
In the TcpClient's handle method, you declare what you want to do with the incoming data, but you do not subscribe => nothing will be executed. So change the code to:
.handle((in, out) -> {
in
.receiveObject()
.log("[Client received]")
.ofType(TlvMessage.class)
.doOnNext(tlv -> {
// do some work on each response from the relay server
if (isLegalType(tlv.getType())) {
latch.countDown();
}
})
.subscribe();
return out
// simulating requests to the relay server
.sendObject(Flux.just(
demo(TYPE_UPSTREAM_INIT, "{\"param\":\"{\\\"device-id\\\":\\\"3F1806118800C678\\\"}\",\"pid\":\"-1001\",\"clientip\":\"xxx.xxx.xxx.xxx\",\"sn\":\"91598059-4d06-447a-878f-551637bcaf89_7\"}"),
demo(TYPE_UPSTREAM_FINISH, "{\"param\":\"{\\\"device-id\\\":\\\"3A1806118800C678\\\"}\",\"pid\":\"-1002\",\"clientip\":\"xxx.xxx.xxx.xxx\"}")
)
)
.neverComplete();
}
)
When you try to send the second message to the server, you again declare what you want to send but you do not subscribe => again nothing will be executed. Change the code to:
connectedClient.outbound().sendObject(
Flux.just(
demo(TYPE_UPSTREAM_INIT, "{\"param\":\"{\\\"device-id\\\":\\\"3B1806118800C678\\\"}\",\"pid\":\"-1003\",\"clientip\":\"xxx.xxx.xxx.xxx\",\"sn\":\"91598059-dd06-447a-878f-551637bcaf89_7\"}"),
demo(TYPE_UPSTREAM_FINISH, "{\"param\":\"{\\\"device-id\\\":\\\"3C1806118800C678\\\"}\",\"pid\":\"-1004\",\"clientip\":\"xxx.xxx.xxx.xxx\"}")
)
)
.then()
.subscribe();

Related

How do I create rSockets that don't share an underlying network connection in springboot client app

I'd like to create multiple rsocket connections from a springboot client app to a single server WITHOUT sharing the same underlying network connection.
The use case for this is load testing - I want to simulate many web clients making rSocket connections to my server, and would like to create (say) 100 such connections from a single application instance so it's easier to operate and monitor than running 100 separate processes.
I'm doing something along these lines:
RSocketRequester requester = rSocketRequesterBuilder
.dataMimeType(MediaType.APPLICATION_JSON)
.setupMetadata(jwt, BearerTokenMetadata.BEARER_AUTHENTICATION_MIME_TYPE)
.rsocketStrategies(builder -> builder.encoder(new BearerTokenAuthenticationEncoder()))
.websocket(serverUri);
requester.route("my.endpoint").retrieveFlux(byte[].class);
This works fine to make multiple connections to the server and get data. But websocket(), per its documentation, seems to be re-using the same underlying shared connection, which means it doesn't adequately simulate many independent connections putting load on the server.
Any idea how to do it?
I'm using Springboot 2.4.4.
Update
I now think i'm successfully making two connections, but that my second connection request is somehow inheriting and appending to the metadata of the first connection instead of having its own separate metadata. The metadata I'm focusing on is a JWT.
Here is the logging from the server side. It looks to me like the second setup frame has two JWTs, each starting with message/x.rsocket.authentication.bearer.v0; the first JWT follwed by the second JWT.
2021-05-03 17:52:20.501 DEBUG 19737 --- [ctor-http-nio-2] reactor.netty.transport.ServerTransport : [id:98c2fa05, L:/0:0:0:0:0:0:0:0:7080] Bound new server
2021-05-03 17:52:20.506 INFO 19737 --- [ main] o.s.b.rsocket.netty.NettyRSocketServer : Netty RSocket started on port(s): 7080
2021-05-03 17:52:20.520 INFO 19737 --- [ main] c.p.pano2.rx.RxServicesApplication : Started RxServicesApplication in 2.616 seconds (JVM running for 3.152)
2021-05-03 17:52:25.799 DEBUG 19737 --- [ctor-http-nio-3] r.n.http.server.HttpServerOperations : [id:380596e7, L:/127.0.0.1:7080 - R:/127.0.0.1:58851] New http connection, requesting read
2021-05-03 17:52:25.800 DEBUG 19737 --- [ctor-http-nio-3] reactor.netty.transport.TransportConfig : [id:380596e7, L:/127.0.0.1:7080 - R:/127.0.0.1:58851] Initialized pipeline DefaultChannelPipeline{(reactor.left.httpCodec = io.netty.handler.codec.http.HttpServerCodec), (reactor.left.httpTrafficHandler = reactor.netty.http.server.HttpTrafficHandler), (reactor.right.reactiveBridge = reactor.netty.channel.ChannelOperationsHandler)}
2021-05-03 17:52:25.826 DEBUG 19737 --- [ctor-http-nio-3] r.n.http.server.HttpServerOperations : [id:380596e7, L:/127.0.0.1:7080 - R:/127.0.0.1:58851] Increasing pending responses, now 1
2021-05-03 17:52:25.831 DEBUG 19737 --- [ctor-http-nio-3] reactor.netty.ReactorNetty : [id:380596e7-1, L:/127.0.0.1:7080 - R:/127.0.0.1:58851] Added decoder [PongHandler] at the end of the user pipeline, full pipeline: [reactor.left.httpCodec, reactor.left.httpTrafficHandler, PongHandler, reactor.right.reactiveBridge, DefaultChannelPipeline$TailContext#0]
2021-05-03 17:52:25.832 DEBUG 19737 --- [ctor-http-nio-3] reactor.netty.http.server.HttpServer : [id:380596e7-1, L:/127.0.0.1:7080 - R:/127.0.0.1:58851] Handler is being applied: io.rsocket.transport.netty.server.WebsocketServerTransport$$Lambda$1058/0x0000000800720c40#cb577eb
2021-05-03 17:52:25.837 DEBUG 19737 --- [ctor-http-nio-3] reactor.netty.ReactorNetty : [id:380596e7-1, L:/127.0.0.1:7080 - R:/127.0.0.1:58851] Removed handler: reactor.left.httpTrafficHandler, pipeline: DefaultChannelPipeline{(reactor.left.httpCodec = io.netty.handler.codec.http.HttpServerCodec), (PongHandler = io.rsocket.transport.netty.server.BaseWebsocketServerTransport$PongHandler), (reactor.right.reactiveBridge = reactor.netty.channel.ChannelOperationsHandler)}
2021-05-03 17:52:25.837 DEBUG 19737 --- [ctor-http-nio-3] reactor.netty.ReactorNetty : [id:380596e7-1, L:/127.0.0.1:7080 - R:/127.0.0.1:58851] Non Removed handler: reactor.left.accessLogHandler, context: null, pipeline: DefaultChannelPipeline{(reactor.left.httpCodec = io.netty.handler.codec.http.HttpServerCodec), (PongHandler = io.rsocket.transport.netty.server.BaseWebsocketServerTransport$PongHandler), (reactor.right.reactiveBridge = reactor.netty.channel.ChannelOperationsHandler)}
2021-05-03 17:52:25.837 DEBUG 19737 --- [ctor-http-nio-3] reactor.netty.ReactorNetty : [id:380596e7-1, L:/127.0.0.1:7080 - R:/127.0.0.1:58851] Non Removed handler: reactor.left.httpMetricsHandler, context: null, pipeline: DefaultChannelPipeline{(reactor.left.httpCodec = io.netty.handler.codec.http.HttpServerCodec), (PongHandler = io.rsocket.transport.netty.server.BaseWebsocketServerTransport$PongHandler), (reactor.right.reactiveBridge = reactor.netty.channel.ChannelOperationsHandler)}
2021-05-03 17:52:25.870 DEBUG 19737 --- [ctor-http-nio-3] reactor.netty.channel.FluxReceive : [id:380596e7-1, L:/127.0.0.1:7080 - R:/127.0.0.1:58851] FluxReceive{pending=0, cancelled=false, inboundDone=false, inboundError=null}: subscribing inbound receiver
2021-05-03 17:52:25.893 DEBUG 19737 --- [ctor-http-nio-3] io.rsocket.FrameLogger : receiving ->
Frame => Stream ID: 0 Type: SETUP Flags: 0b100000000 Length: 300
Metadata:
+-------------------------------------------------+
| 0 1 2 3 4 5 6 7 8 9 a b c d e f |
+--------+-------------------------------------------------+----------------+
|00000000| 29 6d 65 73 73 61 67 65 2f 78 2e 72 73 6f 63 6b |)message/x.rsock|
|00000010| 65 74 2e 61 75 74 68 65 6e 74 69 63 61 74 69 6f |et.authenticatio|
|00000020| 6e 2e 62 65 61 72 65 72 2e 76 30 00 00 b0 65 79 |n.bearer.v0...ey|
|00000030| 4a 68 62 47 63 69 4f 69 4a 49 55 7a 49 31 4e 69 |JhbGciOiJIUzI1Ni|
|00000040| 4a 39 2e 65 79 4a 71 64 47 6b 69 4f 69 4a 56 55 |J9.eyJqdGkiOiJVU|
|00000050| 30 56 53 4d 53 49 73 49 6d 6c 68 64 43 49 36 4d |0VSMSIsImlhdCI6M|
|00000060| 54 59 79 4d 44 41 33 4f 44 63 30 4e 53 77 69 63 |TYyMDA3ODc0NSwic|
|00000070| 33 56 69 49 6a 6f 69 56 56 4e 46 55 6a 45 69 4c |3ViIjoiVVNFUjEiL|
|00000080| 43 4a 70 63 33 4d 69 4f 69 4a 6d 59 57 74 6c 49 |CJpc3MiOiJmYWtlI|
|00000090| 47 6c 7a 63 33 56 6c 63 69 49 73 49 6d 56 34 63 |Glzc3VlciIsImV4c|
|000000a0| 43 49 36 4d 54 59 79 4d 44 45 32 4e 54 45 30 4e |CI6MTYyMDE2NTE0N|
|000000b0| 58 30 2e 58 33 6e 79 62 6b 4a 44 51 4f 67 36 7a |X0.X3nybkJDQOg6z|
|000000c0| 53 7a 77 39 68 63 68 4d 54 4b 34 6e 71 48 63 34 |Szw9hchMTK4nqHc4|
|000000d0| 4c 6f 47 36 32 73 7a 73 6e 47 58 54 79 77 |LoG62szsnGXTyw |
+--------+-------------------------------------------------+----------------+
Data:
2021-05-03 17:52:25.929 INFO 19737 --- [ctor-http-nio-3] c.p.p.security.FakeReactiveJwtDecoder : Decoding jwt 1040895620 subject USER1
2021-05-03 17:52:25.947 DEBUG 19737 --- [ctor-http-nio-3] io.rsocket.FrameLogger : receiving ->
Frame => Stream ID: 1 Type: REQUEST_STREAM Flags: 0b100000000 Length: 22 InitialRequestN: 9223372036854775807
Metadata:
+-------------------------------------------------+
| 0 1 2 3 4 5 6 7 8 9 a b c d e f |
+--------+-------------------------------------------------+----------------+
|00000000| fe 00 00 05 04 74 65 73 74 |.....test |
+--------+-------------------------------------------------+----------------+
Data:
2021-05-03 17:52:25.965 INFO 19737 --- [ctor-http-nio-3] c.p.pano2.rx.web.SystemController : Test connection from USER1 null
2021-05-03 17:52:28.981 DEBUG 19737 --- [ parallel-2] io.rsocket.FrameLogger : sending ->
Frame => Stream ID: 1 Type: NEXT Flags: 0b100000 Length: 19
Data:
+-------------------------------------------------+
| 0 1 2 3 4 5 6 7 8 9 a b c d e f |
+--------+-------------------------------------------------+----------------+
|00000000| 48 65 6c 6c 6f 20 55 53 45 52 31 20 30 |Hello USER1 0 |
+--------+-------------------------------------------------+----------------+
2021-05-03 17:52:30.736 DEBUG 19737 --- [ctor-http-nio-4] r.n.http.server.HttpServerOperations : [id:d82b3f3a, L:/127.0.0.1:7080 - R:/127.0.0.1:58855] New http connection, requesting read
2021-05-03 17:52:30.736 DEBUG 19737 --- [ctor-http-nio-4] reactor.netty.transport.TransportConfig : [id:d82b3f3a, L:/127.0.0.1:7080 - R:/127.0.0.1:58855] Initialized pipeline DefaultChannelPipeline{(reactor.left.httpCodec = io.netty.handler.codec.http.HttpServerCodec), (reactor.left.httpTrafficHandler = reactor.netty.http.server.HttpTrafficHandler), (reactor.right.reactiveBridge = reactor.netty.channel.ChannelOperationsHandler)}
2021-05-03 17:52:30.751 DEBUG 19737 --- [ctor-http-nio-4] r.n.http.server.HttpServerOperations : [id:d82b3f3a, L:/127.0.0.1:7080 - R:/127.0.0.1:58855] Increasing pending responses, now 1
2021-05-03 17:52:30.751 DEBUG 19737 --- [ctor-http-nio-4] reactor.netty.ReactorNetty : [id:d82b3f3a-1, L:/127.0.0.1:7080 - R:/127.0.0.1:58855] Added decoder [PongHandler] at the end of the user pipeline, full pipeline: [reactor.left.httpCodec, reactor.left.httpTrafficHandler, PongHandler, reactor.right.reactiveBridge, DefaultChannelPipeline$TailContext#0]
2021-05-03 17:52:30.751 DEBUG 19737 --- [ctor-http-nio-4] reactor.netty.http.server.HttpServer : [id:d82b3f3a-1, L:/127.0.0.1:7080 - R:/127.0.0.1:58855] Handler is being applied: io.rsocket.transport.netty.server.WebsocketServerTransport$$Lambda$1058/0x0000000800720c40#cb577eb
2021-05-03 17:52:30.751 DEBUG 19737 --- [ctor-http-nio-4] reactor.netty.ReactorNetty : [id:d82b3f3a-1, L:/127.0.0.1:7080 - R:/127.0.0.1:58855] Removed handler: reactor.left.httpTrafficHandler, pipeline: DefaultChannelPipeline{(reactor.left.httpCodec = io.netty.handler.codec.http.HttpServerCodec), (PongHandler = io.rsocket.transport.netty.server.BaseWebsocketServerTransport$PongHandler), (reactor.right.reactiveBridge = reactor.netty.channel.ChannelOperationsHandler)}
2021-05-03 17:52:30.751 DEBUG 19737 --- [ctor-http-nio-4] reactor.netty.ReactorNetty : [id:d82b3f3a-1, L:/127.0.0.1:7080 - R:/127.0.0.1:58855] Non Removed handler: reactor.left.accessLogHandler, context: null, pipeline: DefaultChannelPipeline{(reactor.left.httpCodec = io.netty.handler.codec.http.HttpServerCodec), (PongHandler = io.rsocket.transport.netty.server.BaseWebsocketServerTransport$PongHandler), (reactor.right.reactiveBridge = reactor.netty.channel.ChannelOperationsHandler)}
2021-05-03 17:52:30.751 DEBUG 19737 --- [ctor-http-nio-4] reactor.netty.ReactorNetty : [id:d82b3f3a-1, L:/127.0.0.1:7080 - R:/127.0.0.1:58855] Non Removed handler: reactor.left.httpMetricsHandler, context: null, pipeline: DefaultChannelPipeline{(reactor.left.httpCodec = io.netty.handler.codec.http.HttpServerCodec), (PongHandler = io.rsocket.transport.netty.server.BaseWebsocketServerTransport$PongHandler), (reactor.right.reactiveBridge = reactor.netty.channel.ChannelOperationsHandler)}
2021-05-03 17:52:30.752 DEBUG 19737 --- [ctor-http-nio-4] reactor.netty.channel.FluxReceive : [id:d82b3f3a-1, L:/127.0.0.1:7080 - R:/127.0.0.1:58855] FluxReceive{pending=0, cancelled=false, inboundDone=false, inboundError=null}: subscribing inbound receiver
2021-05-03 17:52:30.755 DEBUG 19737 --- [ctor-http-nio-4] io.rsocket.FrameLogger : receiving ->
Frame => Stream ID: 0 Type: SETUP Flags: 0b100000000 Length: 522
Metadata:
+-------------------------------------------------+
| 0 1 2 3 4 5 6 7 8 9 a b c d e f |
+--------+-------------------------------------------------+----------------+
|00000000| 29 6d 65 73 73 61 67 65 2f 78 2e 72 73 6f 63 6b |)message/x.rsock|
|00000010| 65 74 2e 61 75 74 68 65 6e 74 69 63 61 74 69 6f |et.authenticatio|
|00000020| 6e 2e 62 65 61 72 65 72 2e 76 30 00 00 b0 65 79 |n.bearer.v0...ey|
|00000030| 4a 68 62 47 63 69 4f 69 4a 49 55 7a 49 31 4e 69 |JhbGciOiJIUzI1Ni|
|00000040| 4a 39 2e 65 79 4a 71 64 47 6b 69 4f 69 4a 56 55 |J9.eyJqdGkiOiJVU|
|00000050| 30 56 53 4d 53 49 73 49 6d 6c 68 64 43 49 36 4d |0VSMSIsImlhdCI6M|
|00000060| 54 59 79 4d 44 41 33 4f 44 63 30 4e 53 77 69 63 |TYyMDA3ODc0NSwic|
|00000070| 33 56 69 49 6a 6f 69 56 56 4e 46 55 6a 45 69 4c |3ViIjoiVVNFUjEiL|
|00000080| 43 4a 70 63 33 4d 69 4f 69 4a 6d 59 57 74 6c 49 |CJpc3MiOiJmYWtlI|
|00000090| 47 6c 7a 63 33 56 6c 63 69 49 73 49 6d 56 34 63 |Glzc3VlciIsImV4c|
|000000a0| 43 49 36 4d 54 59 79 4d 44 45 32 4e 54 45 30 4e |CI6MTYyMDE2NTE0N|
|000000b0| 58 30 2e 58 33 6e 79 62 6b 4a 44 51 4f 67 36 7a |X0.X3nybkJDQOg6z|
|000000c0| 53 7a 77 39 68 63 68 4d 54 4b 34 6e 71 48 63 34 |Szw9hchMTK4nqHc4|
|000000d0| 4c 6f 47 36 32 73 7a 73 6e 47 58 54 79 77 29 6d |LoG62szsnGXTyw)m|
|000000e0| 65 73 73 61 67 65 2f 78 2e 72 73 6f 63 6b 65 74 |essage/x.rsocket|
|000000f0| 2e 61 75 74 68 65 6e 74 69 63 61 74 69 6f 6e 2e |.authentication.|
|00000100| 62 65 61 72 65 72 2e 76 30 00 00 b0 65 79 4a 68 |bearer.v0...eyJh|
|00000110| 62 47 63 69 4f 69 4a 49 55 7a 49 31 4e 69 4a 39 |bGciOiJIUzI1NiJ9|
|00000120| 2e 65 79 4a 71 64 47 6b 69 4f 69 4a 56 55 30 56 |.eyJqdGkiOiJVU0V|
|00000130| 53 4d 69 49 73 49 6d 6c 68 64 43 49 36 4d 54 59 |SMiIsImlhdCI6MTY|
|00000140| 79 4d 44 41 33 4f 44 63 31 4d 43 77 69 63 33 56 |yMDA3ODc1MCwic3V|
|00000150| 69 49 6a 6f 69 56 56 4e 46 55 6a 49 69 4c 43 4a |iIjoiVVNFUjIiLCJ|
|00000160| 70 63 33 4d 69 4f 69 4a 6d 59 57 74 6c 49 47 6c |pc3MiOiJmYWtlIGl|
|00000170| 7a 63 33 56 6c 63 69 49 73 49 6d 56 34 63 43 49 |zc3VlciIsImV4cCI|
|00000180| 36 4d 54 59 79 4d 44 45 32 4e 54 45 31 4d 48 30 |6MTYyMDE2NTE1MH0|
|00000190| 2e 4a 33 63 63 52 68 72 31 43 4b 70 45 43 58 66 |.J3ccRhr1CKpECXf|
|000001a0| 45 51 53 31 5a 49 63 71 4f 6d 76 57 31 52 52 4d |EQS1ZIcqOmvW1RRM|
|000001b0| 43 38 67 53 76 4a 76 45 54 44 64 67 |C8gSvJvETDdg |
+--------+-------------------------------------------------+----------------+
Data:
2021-05-03 17:52:30.757 INFO 19737 --- [ctor-http-nio-4] c.p.p.security.FakeReactiveJwtDecoder : Decoding jwt 1994845380 subject USER1
2021-05-03 17:52:30.757 DEBUG 19737 --- [ctor-http-nio-4] io.rsocket.FrameLogger : receiving ->
Frame => Stream ID: 1 Type: REQUEST_STREAM Flags: 0b100000000 Length: 22 InitialRequestN: 9223372036854775807
Metadata:
+-------------------------------------------------+
| 0 1 2 3 4 5 6 7 8 9 a b c d e f |
+--------+-------------------------------------------------+----------------+
|00000000| fe 00 00 05 04 74 65 73 74 |.....test |
+--------+-------------------------------------------------+----------------+
Data:
2021-05-03 17:52:30.758 INFO 19737 --- [ctor-http-nio-4] c.p.pano2.rx.web.SystemController : Test connection from USER1 null
2021-05-03 17:52:31.967 DEBUG 19737 --- [ parallel-2] io.rsocket.FrameLogger : sending ->
Frame => Stream ID: 1 Type: NEXT Flags: 0b100000 Length: 19
Data:
+-------------------------------------------------+
| 0 1 2 3 4 5 6 7 8 9 a b c d e f |
+--------+-------------------------------------------------+----------------+
|00000000| 48 65 6c 6c 6f 20 55 53 45 52 31 20 31 |Hello USER1 1 |
+--------+-------------------------------------------------+----------------+
2021-05-03 17:52:33.765 DEBUG 19737 --- [ parallel-4] io.rsocket.FrameLogger : sending ->
Frame => Stream ID: 1 Type: NEXT Flags: 0b100000 Length: 19
Data:
+-------------------------------------------------+
| 0 1 2 3 4 5 6 7 8 9 a b c d e f |
+--------+-------------------------------------------------+----------------+
|00000000| 48 65 6c 6c 6f 20 55 53 45 52 31 20 30 |Hello USER1 0 |
+--------+-------------------------------------------------+----------------+
I'm having trouble connecting what I see from wiretap log from the client side; the encoding in the frame logger seems to be different and less human-readable, but it does look like a second request is longer than the first. (Omitting the log to stay within the 30k char limit)
The code I'm using to generate the two client requests is:
private void testRequest(String user) {
String jwt = FakeJwtUtils.createJwt(user, user, 24*60*60*1000L);
URI uri = config.getUri();
String baseUrl = uri.getHost() + ":" + uri.getPort();
HttpClient httpClient = HttpClient.newConnection().baseUrl(baseUrl).wiretap(true); // newConnection() to avoid shared connection
WebsocketClientTransport transport = WebsocketClientTransport.create(httpClient, uri.getPath());
try {
log.info("Setting up rSocketRequesterBuilder for jwt sub {}: {}", FakeJwtUtils.parseClaimsAsMap(jwt).get("sub"), jwt);
} catch (Exception ignore) { }
var requesterBuilder = rSocketRequesterBuilder
.dataMimeType(MediaType.APPLICATION_JSON)
.setupMetadata(jwt, BearerTokenMetadata.BEARER_AUTHENTICATION_MIME_TYPE)
.rsocketStrategies(builder -> builder.encoder(new BearerTokenAuthenticationEncoder()))
.transport(transport);
requesterBuilder.route("test").retrieveFlux(byte[].class).subscribe(bytes -> log.info("rcvd: {}", new String(bytes)));
}
Any pointers would be much appreciated!
I'm answering my own question in case anyone else searching has a similar confusion to mine.
The root issue is that I was reusing the RSocketRequester.Builder to make multiple requesters for my multiple requests. This caused multiple issues; most problematic being that I was effectively (in the code above) calling setupMetadata(jwt, BearerTokenMetadata.BEARER_AUTHENTICATION_MIME_TYPE) multiple times on the same builder, with the effect of appending JWT entries rather than setting or replacing as I expected.
The solution seems to be simply to create a new builder for each connection:
RSocketRequester.builder()
.dataMimeType(MediaType.APPLICATION_JSON)
.setupMetadata(jwt, BearerTokenMetadata.BEARER_AUTHENTICATION_MIME_TYPE)
.rsocketStrategies(b -> b.encoder(new BearerTokenAuthenticationEncoder()))
.websocket(config.getUri())
.route("test").retrieveFlux(byte[].class).subscribe();

How to send delete request with custom header using Spring's WebClient?

I want to send an http delete request with custom header.
I tried to do this with Spring's WebClient, with following code:
#Test
public void validateDeleteCouldCarryHeader() {
WebClient.create("https://jira.spring.io/")
.delete()
.header("X-FOO", "BAR")
.retrieve()
.bodyToMono(Map.class)
.block();
}
I am expecting something like:
DELETE / HTTP/1.1
X-FOO: BAR
...
content-length: 0
But, the actual request made is:
DELETE / HTTP/1.1
user-agent: ReactorNetty/0.7.0.RELEASE
host: jira.spring.io
accept: */*
accept-encoding: gzip
content-length: 0
Did I miss some thing to include the custom header X-FOO ?
Update 1: I upgraded reactor-netty to 0.7.3.RELEASE,
And the missing header is still missing:
DELETE / HTTP/1.1
user-agent: ReactorNetty/0.7.3.RELEASE
host: jira.spring.io
accept: */*
accept-encoding: gzip
content-length: 0
2018-12-28 22:32:32.813 DEBUG 12064 --- [ctor-http-nio-4] r.ipc.netty.http.client.HttpClient : [id: 0x2c6a9cea, L:/172.17.1.131:54532 - R:jira.spring.io/35.199.60.33:443] WRITE: 138B
+-------------------------------------------------+
| 0 1 2 3 4 5 6 7 8 9 a b c d e f |
+--------+-------------------------------------------------+----------------+
|00000000| 44 45 4c 45 54 45 20 2f 20 48 54 54 50 2f 31 2e |DELETE / HTTP/1.|
|00000010| 31 0d 0a 75 73 65 72 2d 61 67 65 6e 74 3a 20 52 |1..user-agent: R|
|00000020| 65 61 63 74 6f 72 4e 65 74 74 79 2f 30 2e 37 2e |eactorNetty/0.7.|
|00000030| 33 2e 52 45 4c 45 41 53 45 0d 0a 68 6f 73 74 3a |3.RELEASE..host:|
|00000040| 20 6a 69 72 61 2e 73 70 72 69 6e 67 2e 69 6f 0d | jira.spring.io.|
|00000050| 0a 61 63 63 65 70 74 3a 20 2a 2f 2a 0d 0a 61 63 |.accept: */*..ac|
|00000060| 63 65 70 74 2d 65 6e 63 6f 64 69 6e 67 3a 20 67 |cept-encoding: g|
|00000070| 7a 69 70 0d 0a 63 6f 6e 74 65 6e 74 2d 6c 65 6e |zip..content-len|
|00000080| 67 74 68 3a 20 30 0d 0a 0d 0a |gth: 0.... |
+--------+-------------------------------------------------+----------------+
Update 2: I found there's a reactor's BOM (Bismuth-RELEASE) imported in my pom, after removed that BOM, Spring Boot 2.0.5.RELEASE included the custom header I want.
DELETE / HTTP/1.1
user-agent: ReactorNetty/0.7.9.RELEASE
host: jira.spring.io
accept: */*
accept-encoding: gzip
X-FOO: BAR
Reactor Netty 0.7.0.RELEASE is quite old now, and you should upgrade to a newer version.
I've tried to reproduce this and couldn't.
Setting the log level of reactor.ipc.netty.http.client.HttpClient to "DEBUG" shows this:
[reactor-http-nio-4] DEBUG reactor.ipc.netty.http.client.HttpClient - [id: 0x69202b84, L:/192.168.0.28:60880 - R:jira.spring.io/35.199.60.33:443] WRITE: 150B
+-------------------------------------------------+
| 0 1 2 3 4 5 6 7 8 9 a b c d e f |
+--------+-------------------------------------------------+----------------+
|00000000| 44 45 4c 45 54 45 20 2f 20 48 54 54 50 2f 31 2e |DELETE / HTTP/1.|
|00000010| 31 0d 0a 75 73 65 72 2d 61 67 65 6e 74 3a 20 52 |1..user-agent: R|
|00000020| 65 61 63 74 6f 72 4e 65 74 74 79 2f 30 2e 37 2e |eactorNetty/0.7.|
|00000030| 30 2e 52 45 4c 45 41 53 45 0d 0a 68 6f 73 74 3a |0.RELEASE..host:|
|00000040| 20 6a 69 72 61 2e 73 70 72 69 6e 67 2e 69 6f 0d | jira.spring.io.|
|00000050| 0a 61 63 63 65 70 74 3a 20 2a 2f 2a 0d 0a 61 63 |.accept: */*..ac|
|00000060| 63 65 70 74 2d 65 6e 63 6f 64 69 6e 67 3a 20 67 |cept-encoding: g|
|00000070| 7a 69 70 0d 0a 58 2d 46 4f 4f 3a 20 42 41 52 0d |zip..X-FOO: BAR.|
|00000080| 0a 63 6f 6e 74 65 6e 74 2d 6c 65 6e 67 74 68 3a |.content-length:|
|00000090| 20 30 0d 0a 0d 0a | 0.... |
+--------+-------------------------------------------------+----------------+
So the client is indeed sending those headers. Maybe there's something wrong with the way you're capturing the outgoing request information?

Websocket client hanshake error 426 on upgrade

Reader's digest version:
First time writing a websocket client. Java 1.8 using Eclipse. While on my workplace internal network getting a handshake error exception and the websocket log information tells me:
< Session 1c61123c-aa5f-4e59-a49d-b5d3c77c0bbd [598 ms]: Received handshake response:
< 426
< connection: Keep-Alive
< content-length: 29
< content-type: text/plain; charset=utf-8
< date: Mon, 12 Jun 2017 16:40:04 GMT
< server: nginx
Exception in thread "main" java.lang.RuntimeException: javax.websocket.DeploymentException: Handshake error.
at webSocketExample.WebsocketClientEndpoint.<init>(WebsocketClientEndpoint.java:60)
Details:
When I am connected to my internal work network and try to make a websocket connection I initially get connected but then I am sending a TCP reset. If I throw the code on my laptop and connect over a different network like my home Comcast connection the connection is made and I receive the initial data response from the server. I then take my laptop and hook it up to my internal work network and I go back to getting the handshake error.
I have been unable to resolve it yet with my internal security team as we don't do websocket development here so the knowledge base is a little lacking.
I set my proxy prior to calling this routine from my main. It has been verified that I am getting connected to the server but then I am sending a reset. Here is the code I am executing:
try {
System.setProperty("javax.net.debug", "all");
ClientManager client = ClientManager.createClient();
final SSLContextConfigurator defaultConfig = new SSLContextConfigurator();
defaultConfig.retrieve(System.getProperties());
SSLEngineConfigurator sslEngine = new SSLEngineConfigurator(defaultConfig, true, false, false);
client.getProperties().put(ClientProperties.SSL_ENGINE_CONFIGURATOR, sslEngine);
client.getProperties().put(ClientProperties.LOG_HTTP_UPGRADE, true);
client.connectToServer(new Endpoint() {
#Override
public void onOpen(Session session, EndpointConfig config) {
session.addMessageHandler(new MessageHandler.Whole<String>() {
#Override
public void onMessage(String message) {
System.out.println(message);
}
});
}
}, ClientEndpointConfig.Builder.create().build(),
new URI("wss://api.sandbox.gemini.com/v1/marketdata/BTCUSD"));
} catch (Exception e) {
throw new RuntimeException(e);
}
I have read all the posts/questions/answers that I have been able to find but haven't come up with anything yet. I am somewhat limited on what I can personally do on our network as we have pretty tight security but I can work with my security team to find answers if I get asked a question.
I would think it has to be internal to my work network and the proxy maybe but I haven't been able to resolve it. Also, this is the last part of the log information from the connection and error reporting:
Padded plaintext after DECRYPTION: len = 170
0000: 48 54 54 50 2F 31 2E 31 20 34 32 36 20 55 70 67 HTTP/1.1 426 Upg
0010: 72 61 64 65 20 52 65 71 75 69 72 65 64 0D 0A 44 rade Required..D
0020: 61 74 65 3A 20 4D 6F 6E 2C 20 31 32 20 4A 75 6E ate: Mon, 12 Jun
0030: 20 32 30 31 37 20 31 36 3A 35 30 3A 32 35 20 47 2017 16:50:25 G
0040: 4D 54 0D 0A 53 65 72 76 65 72 3A 20 6E 67 69 6E MT..Server: ngin
0050: 78 0D 0A 43 6F 6E 6E 65 63 74 69 6F 6E 3A 20 4B x..Connection: K
0060: 65 65 70 2D 41 6C 69 76 65 0D 0A 43 6F 6E 74 65 eep-Alive..Conte
0070: 6E 74 2D 54 79 70 65 3A 20 74 65 78 74 2F 70 6C nt-Type: text/pl
0080: 61 69 6E 3B 20 63 68 61 72 73 65 74 3D 75 74 66 ain; charset=utf
0090: 2D 38 0D 0A 43 6F 6E 74 65 6E 74 2D 4C 65 6E 67 -8..Content-Leng
00A0: 74 68 3A 20 32 39 0D 0A 0D 0A th: 29....
[Raw read (bb)]: length = 58
0000: 17 03 03 00 35 EC 0F C3 40 0D 18 B4 7B 53 C6 2D ....5...#....S.-
0010: F5 83 29 72 15 51 AC 31 8F 86 52 C9 3C 98 BB F8 ..)r.Q.1..R.<...
0020: 94 4A D7 3A 6E 17 8C 75 9E 58 25 0B AE B5 2F 13 .J.:n..u.X%.../.
0030: 8C 44 29 94 2F 4A 46 18 C9 1A .D)./JF...
Padded plaintext after DECRYPTION: len = 29
0000: 55 70 67 72 61 64 65 20 74 6F 20 57 65 62 53 6F Upgrade to WebSo
0010: 63 6B 65 74 20 72 65 71 75 69 72 65 64 cket required
> Session 6f920826-4b05-47bd-8cad-212038ff9fad [86 ms]: Sending handshake request:
> GET wss://api.sandbox.gemini.com/v1/marketdata/BTCUSD
> Connection: Upgrade
> Host: api.sandbox.gemini.com
> Origin: api.sandbox.gemini.com
> Sec-WebSocket-Key: nkgv7uk/bPSKBiOz5T/Bdg==
> Sec-WebSocket-Version: 13
> Upgrade: websocket
< Session 6f920826-4b05-47bd-8cad-212038ff9fad [600 ms]: Received handshake response:
< 426
< connection: Keep-Alive
< content-length: 29
< content-type: text/plain; charset=utf-8
< date: Mon, 12 Jun 2017 16:50:25 GMT
< server: nginx
If you got this far, thanks...
Adding sniffer information from my network team:
You establish a connection Pkt 263, which you are going through the proxy server, mcweb-a 170.137.249.117. Then you transmit data. The reset is sent in Pkt 280.
enter image description here
In case anyone comes across this. The issue was a problem with my proxy server. We had to add the specific endpoint as being allowable so it would skip some of the security checks.

Fine Uploader 5.11.10 SignatureDoesNotMatch with PHP & AWS S3

UPDATED POST AND RETURN INFO
I'm new to FineUploader and I'm running into problems when uploading files to AWS s3. S3 responds with <Error><Code>SignatureDoesNotMatch</Code><Message>The request signature we calculated does not match the signature you provided. Check your key and signing method.</Message> I've tried many different options and parameters and have currently paired it down to a very simple configuration but still get the same response. I've followed the steps in the documentation for setting up fineuploder and the PHP signature endpoint for signing, gone through countless options/settings, looked at various posts but nothing has quite got me to a solution.
The js is simplified down to:
var s3Uploader = new qq.s3.FineUploader({
debug: true,
element: document.getElementById('fine_uploader'),
request: {
endpoint: 'https://bucketname.s3.amazonaws.com',
accessKey: 'KEY'
},
cors: {
expected: true,
sendCredentials: true
},
signature: {
endpoint: 'https://domain/s3/endpoint',
version: 4
},
uploadSuccess: {
endpoint: 'https://domain/s3/endpointsuccess'
},
iframeSupport: {
localBlankPagePath: 'https://domain/s3/blank'
},
thumbnails: {
placeholders: {
notAvailablePath: "https://domain/not_available-generic.png",
waitingPath: "https://domain/waiting-generic.png"
}
}
});
The endpoint-cors.php file for signing requests is identical to that found on Github FineUploader/php-s3-server/endpoint-cors.php dated Nov 5, 2015.
FineUploder submits the following to my endpoint for signing:
{"expiration":"2016-12-30T16:58:27.028Z","conditions":[{"acl":"private"},{"bucket":"bucketname"},{"Content-Type":"application/pdf"},{"success_action_status":"200"},{"x-amz-algorithm":"AWS4-HMAC-SHA256"},{"key":"2c6ed85e-1d5f-45e3-8458-e864f92a8cf3.pdf"},{"x-amz-credential":"KEY/20161230/us-east-1/s3/aws4_request"},{"x-amz-date":"20161230T165327Z"},{"x-amz-meta-qqfilename":"DefaultDocument.pdf"}]}
My signing endpoint responds with:
{"policy":"eyJleHBpcmF0aW9uIjoiMjAxNi0xMi0zMFQxNjo1ODoyNy4wMjhaIiwiY29uZGl0aW9ucyI6W3siYWNsIjoicHJpdmF0ZSJ9LHsiYnVja2V0IjoidXBsb2FkdG9idWlsZGVycG9wIn0seyJDb250ZW50LVR5cGUiOiJhcHBsaWNhdGlvblwvcGRmIn0seyJzdWNjZXNzX2FjdGlvbl9zdGF0dXMiOiIyMDAifSx7IngtYW16LWFsZ29yaXRobSI6IkFXUzQtSE1BQy1TSEEyNTYifSx7ImtleSI6IjJjNmVkODVlLTFkNWYtNDVlMy04NDU4LWU4NjRmOTJhOGNmMy5wZGYifSx7IngtYW16LWNyZWRlbnRpYWwiOiJBS0lBSjRaNlRWRDVVNTZOUzVRUVwvMjAxNjEyMzBcL3VzLWVhc3QtMVwvczNcL2F3czRfcmVxdWVzdCJ9LHsieC1hbXotZGF0ZSI6IjIwMTYxMjMwVDE2NTMyN1oifSx7IngtYW16LW1ldGEtcXFmaWxlbmFtZSI6IkRlZmF1bHREb2N1bWVudC5wZGYifV19","signature":"01dd1e6ab8be148c9f26b8721a267f41d0b4e1d6ac1da7ca3f5a1cc8ab9888e3"}
AWS S3 POST information for file upload:
Request URL:https://bucketname.s3.amazonaws.com/
Request Method:POST
Status Code:403 Forbidden
Remote Address:ipaddress:443
Response Headers
Access-Control-Allow-Methods:POST, PUT, DELETE
Access-Control-Allow-Origin:*
Access-Control-Expose-Headers:ETag
Access-Control-Max-Age:3000
Connection:close
Content-Type:application/xml
Date:Fri, 30 Dec 2016 16:53:29 GMT
Server:AmazonS3
Transfer-Encoding:chunked
Vary:Origin, Access-Control-Request-Headers, Access-Control-Request-Method
x-amz-id-2:lQOge5d8wTNIwH1g3TE/IuNPXNad29p6PbC8DHPDTPZzWvS9eTK6wE5nd2K6Kt/f+FsH9B0oBRw=
x-amz-request-id:E9A9C61173E13568
Request Headers
Accept:*/*
Accept-Encoding:gzip, deflate, br
Accept-Language:en-US,en;q=0.8
Connection:keep-alive
Content-Length:659510
Content-Type:multipart/form-data; boundary=----WebKitFormBoundaryiz1gbHgrB4vnnG1m
Host:bucketname.s3.amazonaws.com
Origin:https://domain
Referer:https://domain/create/?pt=O1&pid=mFflJn
User-Agent:Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/55.0.2883.87 Safari/537.36
Request Payload
------WebKitFormBoundaryiz1gbHgrB4vnnG1m
Content-Disposition: form-data; name="key"
2c6ed85e-1d5f-45e3-8458-e864f92a8cf3.pdf
------WebKitFormBoundaryiz1gbHgrB4vnnG1m
Content-Disposition: form-data; name="Content-Type"
application/pdf
------WebKitFormBoundaryiz1gbHgrB4vnnG1m
Content-Disposition: form-data; name="success_action_status"
200
------WebKitFormBoundaryiz1gbHgrB4vnnG1m
Content-Disposition: form-data; name="acl"
private
------WebKitFormBoundaryiz1gbHgrB4vnnG1m
Content-Disposition: form-data; name="x-amz-meta-qqfilename"
DefaultDocument.pdf
------WebKitFormBoundaryiz1gbHgrB4vnnG1m
Content-Disposition: form-data; name="x-amz-algorithm"
AWS4-HMAC-SHA256
------WebKitFormBoundaryiz1gbHgrB4vnnG1m
Content-Disposition: form-data; name="x-amz-credential"
AKIAJ4Z6TVD5U56NS5QQ/20161230/us-east-1/s3/aws4_request
------WebKitFormBoundaryiz1gbHgrB4vnnG1m
Content-Disposition: form-data; name="x-amz-date"
20161230T165327Z
------WebKitFormBoundaryiz1gbHgrB4vnnG1m
Content-Disposition: form-data; name="policy"
eyJleHBpcmF0aW9uIjoiMjAxNi0xMi0zMFQxNjo1ODoyNy4wMjhaIiwiY29uZGl0aW9ucyI6W3siYWNsIjoicHJpdmF0ZSJ9LHsiYnVja2V0IjoidXBsb2FkdG9idWlsZGVycG9wIn0seyJDb250ZW50LVR5cGUiOiJhcHBsaWNhdGlvblwvcGRmIn0seyJzdWNjZXNzX2FjdGlvbl9zdGF0dXMiOiIyMDAifSx7IngtYW16LWFsZ29yaXRobSI6IkFXUzQtSE1BQy1TSEEyNTYifSx7ImtleSI6IjJjNmVkODVlLTFkNWYtNDVlMy04NDU4LWU4NjRmOTJhOGNmMy5wZGYifSx7IngtYW16LWNyZWRlbnRpYWwiOiJBS0lBSjRaNlRWRDVVNTZOUzVRUVwvMjAxNjEyMzBcL3VzLWVhc3QtMVwvczNcL2F3czRfcmVxdWVzdCJ9LHsieC1hbXotZGF0ZSI6IjIwMTYxMjMwVDE2NTMyN1oifSx7IngtYW16LW1ldGEtcXFmaWxlbmFtZSI6IkRlZmF1bHREb2N1bWVudC5wZGYifV19
------WebKitFormBoundaryiz1gbHgrB4vnnG1m
Content-Disposition: form-data; name="x-amz-signature"
01dd1e6ab8be148c9f26b8721a267f41d0b4e1d6ac1da7ca3f5a1cc8ab9888e3
------WebKitFormBoundaryiz1gbHgrB4vnnG1m
Content-Disposition: form-data; name="file"; filename="DefaultDocument.pdf"
Content-Type: application/pdf
------WebKitFormBoundaryiz1gbHgrB4vnnG1m--
AWS S3 POST RESPONSE:
<?xml version="1.0" encoding="UTF-8"?>
<Error><Code>SignatureDoesNotMatch</Code><Message>The request signature we calculated does not match the signature you provided. Check your key and signing method.</Message><AWSAccessKeyId>AKIAJ4Z6TVD5U56NS5QQ</AWSAccessKeyId><StringToSign>eyJleHBpcmF0aW9uIjoiMjAxNi0xMi0zMFQxNjo1ODoyNy4wMjhaIiwiY29uZGl0aW9ucyI6W3siYWNsIjoicHJpdmF0ZSJ9LHsiYnVja2V0IjoidXBsb2FkdG9idWlsZGVycG9wIn0seyJDb250ZW50LVR5cGUiOiJhcHBsaWNhdGlvblwvcGRmIn0seyJzdWNjZXNzX2FjdGlvbl9zdGF0dXMiOiIyMDAifSx7IngtYW16LWFsZ29yaXRobSI6IkFXUzQtSE1BQy1TSEEyNTYifSx7ImtleSI6IjJjNmVkODVlLTFkNWYtNDVlMy04NDU4LWU4NjRmOTJhOGNmMy5wZGYifSx7IngtYW16LWNyZWRlbnRpYWwiOiJBS0lBSjRaNlRWRDVVNTZOUzVRUVwvMjAxNjEyMzBcL3VzLWVhc3QtMVwvczNcL2F3czRfcmVxdWVzdCJ9LHsieC1hbXotZGF0ZSI6IjIwMTYxMjMwVDE2NTMyN1oifSx7IngtYW16LW1ldGEtcXFmaWxlbmFtZSI6IkRlZmF1bHREb2N1bWVudC5wZGYifV19</StringToSign><SignatureProvided>01dd1e6ab8be148c9f26b8721a267f41d0b4e1d6ac1da7ca3f5a1cc8ab9888e3</SignatureProvided><StringToSignBytes>65 79 4a 6c 65 48 42 70 63 6d 46 30 61 57 39 75 49 6a 6f 69 4d 6a 41 78 4e 69 30 78 4d 69 30 7a 4d 46 51 78 4e 6a 6f 31 4f 44 6f 79 4e 79 34 77 4d 6a 68 61 49 69 77 69 59 32 39 75 5a 47 6c 30 61 57 39 75 63 79 49 36 57 33 73 69 59 57 4e 73 49 6a 6f 69 63 48 4a 70 64 6d 46 30 5a 53 4a 39 4c 48 73 69 59 6e 56 6a 61 32 56 30 49 6a 6f 69 64 58 42 73 62 32 46 6b 64 47 39 69 64 57 6c 73 5a 47 56 79 63 47 39 77 49 6e 30 73 65 79 4a 44 62 32 35 30 5a 57 35 30 4c 56 52 35 63 47 55 69 4f 69 4a 68 63 48 42 73 61 57 4e 68 64 47 6c 76 62 6c 77 76 63 47 52 6d 49 6e 30 73 65 79 4a 7a 64 57 4e 6a 5a 58 4e 7a 58 32 46 6a 64 47 6c 76 62 6c 39 7a 64 47 46 30 64 58 4d 69 4f 69 49 79 4d 44 41 69 66 53 78 37 49 6e 67 74 59 57 31 36 4c 57 46 73 5a 32 39 79 61 58 52 6f 62 53 49 36 49 6b 46 58 55 7a 51 74 53 45 31 42 51 79 31 54 53 45 45 79 4e 54 59 69 66 53 78 37 49 6d 74 6c 65 53 49 36 49 6a 4a 6a 4e 6d 56 6b 4f 44 56 6c 4c 54 46 6b 4e 57 59 74 4e 44 56 6c 4d 79 30 34 4e 44 55 34 4c 57 55 34 4e 6a 52 6d 4f 54 4a 68 4f 47 4e 6d 4d 79 35 77 5a 47 59 69 66 53 78 37 49 6e 67 74 59 57 31 36 4c 57 4e 79 5a 57 52 6c 62 6e 52 70 59 57 77 69 4f 69 4a 42 53 30 6c 42 53 6a 52 61 4e 6c 52 57 52 44 56 56 4e 54 5a 4f 55 7a 56 52 55 56 77 76 4d 6a 41 78 4e 6a 45 79 4d 7a 42 63 4c 33 56 7a 4c 57 56 68 63 33 51 74 4d 56 77 76 63 7a 4e 63 4c 32 46 33 63 7a 52 66 63 6d 56 78 64 57 56 7a 64 43 4a 39 4c 48 73 69 65 43 31 68 62 58 6f 74 5a 47 46 30 5a 53 49 36 49 6a 49 77 4d 54 59 78 4d 6a 4d 77 56 44 45 32 4e 54 4d 79 4e 31 6f 69 66 53 78 37 49 6e 67 74 59 57 31 36 4c 57 31 6c 64 47 45 74 63 58 46 6d 61 57 78 6c 62 6d 46 74 5a 53 49 36 49 6b 52 6c 5a 6d 46 31 62 48 52 45 62 32 4e 31 62 57 56 75 64 43 35 77 5a 47 59 69 66 56 31 39</StringToSignBytes><RequestId>E9A9C61173E13568</RequestId><HostId>lQOge5d8wTNIwH1g3TE/IuNPXNad29p6PbC8DHPDTPZzWvS9eTK6wE5nd2K6Kt/f+FsH9B0oBRw=</HostId></Error>
Comparison of the endpoint signature and the AWS S3 POST response appear the same signature and policy are being submitted.
Response Snipets:
endpoint response: {....,"signature":"01dd1e6ab8be148c9f26b8721a267f41d0b4e1d6ac1da7ca3f5a1cc8ab9888e3"}
AWS S3 response: <SignatureProvided>01dd1e6ab8be148c9f26b8721a267f41d0b4e1d6ac1da7ca3f5a1cc8ab9888e3</SignatureProvided>
endpoint policy: eyJleHBpcmF0aW9uIjoiMjAxNi0xMi0zMFQxNjo1ODoyNy4wMjhaIiwiY29uZGl0aW9ucyI6W3siYWNsIjoicHJpdmF0ZSJ9LHsiYnVja2V0IjoidXBsb2FkdG9idWlsZGVycG9wIn0seyJDb250ZW50LVR5cGUiOiJhcHBsaWNhdGlvblwvcGRmIn0seyJzdWNjZXNzX2FjdGlvbl9zdGF0dXMiOiIyMDAifSx7IngtYW16LWFsZ29yaXRobSI6IkFXUzQtSE1BQy1TSEEyNTYifSx7ImtleSI6IjJjNmVkODVlLTFkNWYtNDVlMy04NDU4LWU4NjRmOTJhOGNmMy5wZGYifSx7IngtYW16LWNyZWRlbnRpYWwiOiJBS0lBSjRaNlRWRDVVNTZOUzVRUVwvMjAxNjEyMzBcL3VzLWVhc3QtMVwvczNcL2F3czRfcmVxdWVzdCJ9LHsieC1hbXotZGF0ZSI6IjIwMTYxMjMwVDE2NTMyN1oifSx7IngtYW16LW1ldGEtcXFmaWxlbmFtZSI6IkRlZmF1bHREb2N1bWVudC5wZGYifV19
S3 Response: <StringToSign>eyJleHBpcmF0aW9uIjoiMjAxNi0xMi0zMFQxNjo1ODoyNy4wMjhaIiwiY29uZGl0aW9ucyI6W3siYWNsIjoicHJpdmF0ZSJ9LHsiYnVja2V0IjoidXBsb2FkdG9idWlsZGVycG9wIn0seyJDb250ZW50LVR5cGUiOiJhcHBsaWNhdGlvblwvcGRmIn0seyJzdWNjZXNzX2FjdGlvbl9zdGF0dXMiOiIyMDAifSx7IngtYW16LWFsZ29yaXRobSI6IkFXUzQtSE1BQy1TSEEyNTYifSx7ImtleSI6IjJjNmVkODVlLTFkNWYtNDVlMy04NDU4LWU4NjRmOTJhOGNmMy5wZGYifSx7IngtYW16LWNyZWRlbnRpYWwiOiJBS0lBSjRaNlRWRDVVNTZOUzVRUVwvMjAxNjEyMzBcL3VzLWVhc3QtMVwvczNcL2F3czRfcmVxdWVzdCJ9LHsieC1hbXotZGF0ZSI6IjIwMTYxMjMwVDE2NTMyN1oifSx7IngtYW16LW1ldGEtcXFmaWxlbmFtZSI6IkRlZmF1bHREb2N1bWVudC5wZGYifV19</StringToSign>
Thanks for any help you provide.

Is it possible to do a bash brace expansion using a variable bound without using eval?

Consider the following script.
#!/bin/bash
echo {00..99}
n=99
echo {00..$n}
The output of this script is:
00 01 02 03 04 05 06 07 08 09 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99
{00..99}
The desired output is:
00 01 02 03 04 05 06 07 08 09 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99
00 01 02 03 04 05 06 07 08 09 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99
One solution which produces the desired output is
eval echo {00..$n}
Unfortunately, this solution uses eval which I'd prefer to avoid if possible.
Does anyone know of a way to obtain the desired result using brace expansion but not eval?
From the bash manual:
The order of expansions is: brace expansion; tilde expansion, parameter and variable expansion, arithmetic expansion, and command substitution (done in a left-to-right fashion); word splitting; and pathname expansion.
Given that variable expansion comes after brace expansion, and that there is no way to induce a different order of operations without using eval, I would have to conclude that no, there is no way to avoid using eval.
Does anyone know of a way to obtain the desired without without eval?
You can use seq command,
seq -w -s ' ' 0 $n
Test:
sat $ seq -w -s " " 0 $n
00 01 02 03 04 05 06 07 08 09 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99
Not sure if this meets your requirements, as it doesn't use braces, but (with GNU seq at least) the following produces the desired output:
$ n=99
$ seq -f%02.0f -s' ' 00 "$n"
00 01 02 03 04 05 06 07 08 09 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99
The "-f" option produces the zero-padding, and the "-d" uses spaces to separate, rather than newlines.

Resources