How set the nativeHeaders to Spring Java SockJS client on CONNECT frame - stomp

I have implemented a Java SockJS client for WebSocket over STOMP using Spring Famework 4.3.2 actually.
My Javascript client create a nativeHeaders that Java client dont create.
Java client:
StandardWebSocketClient webSocketClient = new StandardWebSocketClient();
List<Transport> transports = new ArrayList<>(2);
transports.add(new WebSocketTransport(webSocketClient));
SockJsClient sockJsClient = new SockJsClient(transports);
WebSocketStompClient stompClient = new WebSocketStompClient(sockJsClient);
stompClient.setMessageConverter(new SimpleMessageConverter());
stompClient.setTaskScheduler(taskScheduler);
StompSessionHandlerImp stompSessionHandlerImp = new StompSessionHandlerImp();
WebSocketHttpHeaders handshakeHeaders = new WebSocketHttpHeaders();
handshakeHeaders.add("tokenGroup", "192:168:99:3::DEMO");
handshakeHeaders.add("targetNickname", "NULL_BORRAR");
stompClient.connect(stompUrlEndpoint.toString(), handshakeHeaders, stompSessionHandlerImp, new Object[0]);
JavaScript:
var from = "192:168:99:3::DEMO";
var targetNickname = "";
stompClient.connect({tokenGroup:from, targetNickname: targetNickname}, function(frame) {
...
}
In the server side, a use the an implementation of ChannelInterceptorAdapter to see the output. JavaScript client include tokenGroup and targetNickname into nativeHeaders.
Java client websocket upgrade handshake:
request.getHeaders(): {Origin=[localhost:8080], Sec-WebSocket-Key=[tVFgflo2od6obTCKW/Y1Ng==],
Connection=[Upgrade], Sec-WebSocket-Version=[13], Host=[localhost:8080],
Upgrade=[websocket],
**targetNickname=[NULL_BORRAR], tokenGroup=[192:168:99:3::DEMO]**}
Java client websocket CONNECT Stomp Message:
message: GenericMessage [payload=byte[0], headers={simpMessageType=CONNECT, stompCommand=CONNECT, **nativeHeaders={heart-beat=[10000,10000], accept-version=[1.1,1.2]}**, simpSessionAttributes={ip=/127.0.0.1:53640}, simpHeartbeat=[J#907d80, simpSessionId=2c150f9d47504b76a896ada101e8e1bc}]
JavaScript client websocket upgrade handshake:
request.getHeaders(): {Origin=[http://localhost:3000], Sec-WebSocket-Key=[slsZkCofKgaFZyxsADbzlw==],
User-Agent=[Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/52.0.2743.116 Safari/537.36],
Connection=[Upgrade], Sec-WebSocket-Version=[13], Host=[localhost:8080],
Accept-Encoding=[gzip, deflate, sdch], DNT=[1], Pragma=[no-cache],
Upgrade=[websocket], Sec-WebSocket-Extensions=[permessage-deflate; client_max_window_bits], Cache-Control=[no-cache], Accept-Language=[en-US,en;q=0.8]}
JavaScript client Websocket CONNECT Stomp Message:
message: GenericMessage [payload=byte[0], headers={simpMessageType=CONNECT, stompCommand=CONNECT, **nativeHeaders={tokenGroup=[192:168:99:4::DEMO], targetNickname=[], accept-version=[1.1,1.0], heart-beat=[10000,10000]}**, simpSessionAttributes={ip=/127.0.0.1:55150}, simpHeartbeat=[J#915deb, simpSessionId=g3pcbfvj}]
You can see that Java client have nativeHeaders={heart-beat=[10000,10000], accept-version=[1.1,1.2]} and Javacript have nativeHeaders={tokenGroup=[192:168:99:4::DEMO], targetNickname=[], accept-version=[1.1,1.0], heart-beat=[10000,10000]}
How can I include the "tokenGroup" into Java client? Is normal that Java and JavaScript client work different?

Solution:
You need use the overloaded method that include an StompHeaders.
WebSocketHttpHeaders handshakeHeaders = new WebSocketHttpHeaders();
StompHeaders connectHeaders = new StompHeaders();
connectHeaders.add("tokenGroup", "192:168:99:3::DEMO");
stompClient.connect(stompUrlEndpoint.toString(), handshakeHeaders, connectHeaders, stompSessionHandlerImp, new Object[0]);
Now this produce the next in the server:
message: GenericMessage [payload=byte[0], headers={simpMessageType=CONNECT, stompCommand=CONNECT, nativeHeaders={tokenGroup=[192:168:99:3::DEMO], heart-beat=[10000,10000], accept-version=[1.1,1.2]}, simpSessionAttributes={ip=/127.0.0.1:57773}, simpHeartbeat=[J#1ac7a81, simpSessionId=a1648581b94d422e8b88258efad36ffb}]
nativeHeader now include the tokenGrouo header on connect.

Related

How to consume a message on server side from websocket client (browser)?

I just set a websocket connection, and I want to send a message from browser to server.
I used connect() method to send message. But I don't know how to consume it at server-side. Here is what I have done at client side.
var socket = new SockJS('http://localhost:8080/websocket/test);
var message = 'A message to send';
stompClient = Stomp.over(socket);
stompClient.connect({}, function(frame) {
stompClient.send('/app/hello',{},message);
I expected to get the message sent in the server console and store it in an object.

Error during web socket handshake; websocket connection failed, using autobahn.js

I am trying to create a websocket server using Ratchet, React and Autobahn. When trying to connect I get this error in console
autobahn.min.js:196 WebSocket connection to 'ws://localhost:8090/'
failed: Error during WebSocket handshake: Unexpected response code:
426
During some digging in Google I found out that Ratchet supports only WAMP1, but that information was 2014. Is this still relevant?
This is the JS
var connection = new autobahn.Connection({
transports: [{
type: 'websocket',
port: 8090,
host: 'localhost',
url: 'ws://localhost:8090'
}],
realm: 'realm1'
});
connection.open();
This is the WebsocketController class
<?php
namespace App\Http\Controllers;
use Ratchet\MessageComponentInterface;
use Ratchet\ConnectionInterface;
use Ratchet\Wamp\WampServerInterface;
class WebSocketController extends Controller implements WampServerInterface{
private $connections = [];
protected $subscribedTopics = array();
public function onSubscribe(ConnectionInterface $conn, $topic) {
$this->subscribedTopics[$topic->getId()] = $topic;
}
public function onUnSubscribe(ConnectionInterface $conn, $topic) {
}
public function onOpen(ConnectionInterface $conn) {
$this->connections->attach($conn);
echo "New connection! ({$conn->resourceId})\n";
}
public function onClose(ConnectionInterface $conn) {
}
public function onCall(ConnectionInterface $conn, $id, $topic, array $params) {
// In this application if clients send data it's because the user hacked around in console
$conn->callError($id, $topic, 'You are not allowed to make calls')->close();
}
public function onPublish(ConnectionInterface $conn, $topic, $event, array $exclude, array $eligible) {
// In this application if clients send data it's because the user hacked around in console
$conn->close();
}
public function onError(ConnectionInterface $conn, \Exception $e) {
echo "New error!".$e;
}
/**
* #param string JSON'ified string we'll receive from ZeroMQ
*/
public function onBlogEntry($entry) {
$entryData = json_decode($entry, true);
// If the lookup topic object isn't set there is no one to publish to
if (!array_key_exists($entryData['category'], $this->subscribedTopics)) {
return;
}
$topic = $this->subscribedTopics[$entryData['category']];
// re-send the data to all the clients subscribed to that category
$topic->broadcast($entryData);
}
}
This is the server:
$loop = Factory::create();
$pusher = new WebsocketController;
// Listen for the web server to make a ZeroMQ push after an ajax request
$context = new Context($loop);
$pull = $context->getSocket(\ZMQ::SOCKET_PULL);
$pull->bind('tcp://127.0.0.1:5555'); // Binding to 127.0.0.1 means the only client that can connect is itself
$pull->on('message', array($pusher, 'onBlogEntry'));
// Set up our WebSocket server for clients wanting real-time updates
$webSock = new \React\Socket\Server('0.0.0.0:8090', $loop); // Binding to 0.0.0.0 means remotes can connect
$webServer = new \Ratchet\Server\IoServer(
new \Ratchet\Http\HttpServer(
new \Ratchet\WebSocket\WsServer(
new \Ratchet\Wamp\WampServer(
$pusher
)
)
),
$webSock
);
$loop->run();
Headers
Request URL:ws://localhost:8090/
Request Method:GET
Status Code:426 No Sec-WebSocket-Protocols requested supported
Response Headers
view source
Connection:Upgrade
Sec-WebSocket-Protocol:0
Sec-WebSocket-Version:13
Transfer-Encoding:chunked
Upgrade:websocket
X-Powered-By:Ratchet/0.4
Request Headers
view source
Accept-Encoding:gzip, deflate, br
Accept-Language:en-US,en;q=0.9,et;q=0.8
Cache-Control:no-cache
Connection:Upgrade
Host:localhost:8090
Origin:http://ermp.ee:8000
Pragma:no-cache
Sec-WebSocket-Extensions:permessage-deflate; client_max_window_bits
Sec-WebSocket-Key:GbJ7qf3lzKDE2hmh3mxJpQ==
Sec-WebSocket-Protocol:wamp.2.json, wamp.2.msgpack
Sec-WebSocket-Version:13
Upgrade:websocket
User-Agent:Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/62.0.3202.94 Safari/537.36
What am I doing wrong here?
I was making something similar to your program when I encountered with this problem. I realized that I was running localhost on the wrong port AND I had processes like Skype running in background on my desired selected port.
Local host runs on port 8000.
Change your code above to this and try as this worked for me in one of my projects
var connection = new autobahn.Connection({
transports: [{
type: 'websocket',
port: 8000,
host: 'localhost',
url: 'ws://localhost:8000'
}],
realm: 'realm1'
});
connection.open();
Also check on your computer if there is already an application running on port 8000, if it is end the program/process to solve the problem.
In Server:
$webSock = new \React\Socket\Server('0.0.0.0:8000', $loop); // Binding to 0.0.0.0 means remotes can connect
In Headers:
Host:localhost:8000
And you right ratchet does support only wamp1
Maybe you can switch ratchet to thruway which may solve problem
I switched from Ratchet to ThruwayPHP and it started working immediately if somebody else has the same issue.

Minio Received non-HTTP message from new connection

server error:
Received non-http message from new connection
client error:
code:
var endpoint = "127.0.0.1:9000";
var accessKey = "MFQD47M******R5TZ1";
var secretKey = "WsuNQtYs********npA7iMRLjRmx";
var minio = new MinioClient(endpoint, accessKey, secretKey).WithSSL();
await minio.ListBucketsAsync();
Try removing .WithSSL(). It seems like your server is expecting plain HTTP, but your client is expecting HTTPS. First try changing the client to plain HTTP. If that works, you'd probably want to properly enable HTTPS on your server so you have a secure connection.
https://docs.minio.io/docs/how-to-secure-access-to-minio-server-with-tls

Xamarin - httpclient while using a secure https

I cannot seem to connect to a https client using the Xamarin httpclient
I have tried various methods but the same error message always get returned
{System.Net.WebException: Error: SendFailure (Error writing headers) ---> System.Net.WebException: Error writing headers ---> System.IO.IOException: The authentication or decryption has failed.
Has anyone found a solution to this
Http Code:
HttpClient client = new HttpClient(new NativeMessageHandler());
client.BaseAddress = new System.Uri("https://....");
client.DefaultRequestHeaders.Accept.Add(new System.Net.Http.Headers.MediaTypeWithQualityHeaderValue("application/json"));
var request = new HttpRequestMessage(HttpMethod.Post, "https://....");
var response = await client.SendAsync(request).ConfigureAwait(false);
var json = await response.Content.ReadAsStringAsync().ConfigureAwait(false);

Httpcomponents-client proxy problems

I have problems when trying to connect to the internet via a proxy using the new httocomponent-client module
If I use directly the Proxy object and HttpURLConnection everything goes fine:
URL u = new URL("http://www.google.com");
Proxy proxy = new Proxy(Type.HTTP, new InetSocketAddress("somehost", 8080));
HttpURLConnection con = (HttpURLConnection) u.openConnection(proxy);
con.setRequestMethod("GET");
System.out.println(con.getResponseCode());
Now I try to do the same with the new api:
HttpHost proxy = new HttpHost("somehost", 8080, "http");
httpClient.getParams().setParameter(ConnRoutePNames.DEFAULT_PROXY, proxy);
HttpHost targetHost = new HttpHost("http://www.google.com");
HttpGet httpGet = new HttpGet("/");
try {
HttpResponse httpResponse = httpClient.execute(targetHost, httpGet);
System.out.println(httpResponse.toString());
} catch (Exception e) {
e.printStackTrace();
}
but I get this:
HTTP/1.1 407 Proxy Authentication Required ( Forefront TMG requires authorization to fulfill the request. Access to the Web Proxy filter is denied. ) [Via: 1.1 xxx, Proxy-Authenticate: Negotiate, Proxy-Authenticate: Kerberos, Proxy-Authenticate: NTLM, Connection: Keep-Alive, Proxy-Connection: Keep-Alive, Pragma: no-cache, Cache-Control: no-cache, Content-Type: text/html, Content-Length: 7079 ]
I also tried
ProxySelectorRoutePlanner routePlanner = new ProxySelectorRoutePlanner(
httpClient.getConnectionManager().getSchemeRegistry(),new MyProxySelector());
httpClient.setRoutePlanner(routePlanner);
Where MyProxySelector return the Proxy that I nned but no result.
Why using the new API makes the proxy authentication required inside the code?
I don't know why the solution with ProxySelectorRoutePlanner doesn't work, are you sure you start your JVM with the proxy settings ?
It looks like you need to add this line :
httpClient.getCredentialsProvider().setCredentials(new AuthScope("yourProxyHost", Port),
new UsernamePasswordCredentials("yourUsername", "yourPass"));

Resources