I play the Jetty Websocket use example here :
https://github.com/jetty-project/embedded-jetty-websocket-examples (i use native-jetty-websocket-example)
I just move from websocketpp (C++) to Java Jetty Websocket and i just wonder is there any way for me to authen the connection before the connection move to the onWebSocketConnect event ?
Back in websocketpp i'll authenticate the connection via url (eg: ws://xxx/?key=123) when i will accept the connection or not. I can drop the connection before it "upgrade", and the client will result in connect failed
In Java i don't known how to do that, when the event come to onWebSocketConnect then the connection is etablished
You can set up Security Constraints for that path and configure the Jetty authentication mechanisms, see details of how to do that here https://www.eclipse.org/jetty/documentation/jetty-9/index.html#configuring-security.
You could also use the JettyWebSocketCreator to do some checks on the HTTP Request just before the connection upgrades to WebSocket. Instead of this line https://github.com/jetty-project/embedded-jetty-websocket-examples/blob/564c40b56413905cadeb500ade40d53e578ea990/native-jetty-websocket-example/src/main/java/org/eclipse/jetty/demo/EventServer.java#L55
You can do something like:
wsContainer.addMapping("/events/*", (req, resp) ->
{
if (!Objects.equals(req.getParameterMap().get("key"), "123"))
{
resp.sendError(...);
return null;
}
return new EventSocket();
});
Related
I am trying to establish a tcp connection through which I want to share data from one webform(jsp page) to another web page with same content.
below is servlet which gets called when clicking button on jsp page. As I checked the port which trying to connect is in listening state and from servlet it should get redirected to receiver form but it just keeps loading.
but program is getting stuck at Socket insocket = socket.accept(); this line.
I searched in other resources as well but got answer as "Socket.accept() hangs by design until a client connects to the port that is being waited on, in this case, port 8189. Your program is working fine"
protected void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
String first = request.getParameter("first_name");
String last = request.getParameter("last_name");
String name = first + " " + last;
PrintWriter out = response.getWriter();
byte buffer[] = new byte[10240];
buffer = name.getBytes();
try {
ServerSocket socket = new ServerSocket(4333);
Socket insocket = socket.accept();
OutputStream outSocket = insocket.getOutputStream();
outSocket.write(buffer);
response.sendRedirect("receiver.jsp");
} catch (java.net.ConnectException e) {
System.out.println("server application not started.....");
}
}
The recommended way to establish a socket-like connection between a web browser or client and a web server is to use WebSockets. This causes the connection used for the HTTP request / response to be taken over for bidirectional socket communication. It is a widely supported extension to the HTTP protocol.
If you want to connect two or more web browsers or web clients via the web server, you need to establish WebSockets between each browser server, and then the server needs to route the information from between the server ends of the WebSockets.
The implementation details will depend on the technology stack used on the client and server sides. You could start by reading the following:
The Wikipedia WebSocket article.
A Guide to the Java API for WebSocket
RFC 6455 - The WebSocket Protocol
They way you are trying to do it looks like it won't work. Even if it does kind of work, there will be issues with managing the connections that you have established ... leading to resource leakage, problems with recycling ports, etcetera. And then you need to deal with potential security issues; e.g. establishing that the client that connects to the ServerSocket port you are listening on is not some interloper.
Does io.vertx.mysqlclient support server failover as it can be set up with MySQL Connector/J?
My application is based on quarkus using io.vertx.mutiny.mysqlclient.MySQLPool which in turn is based on io.vertx.mysqlclient. If there is support for server failover in that stack, how can it be set up? I did not find any hints in the documentation and code.
No it doesn't support failover.
You could create two clients and then use Munity failover methods to get the same effect:
MySQLPool client1 = ...
MySQLPool client2 = ...
private Uni<List<Data>> query(MySQLPool client) {
// Use client param to send queries to the database
}
Uni<List<Data>> results = query(client1)
.onFailure().recoverWithUni(() -> query(client2));
In my application.properties file I have...
server.port=8086
server.connection-timeout=15000
I know that the file is being loaded correctly because the server is running on port 8086.
In the application I have a RestController
#RestController
class TestController {
#GetMapping()
fun getValues(): ResponseEntity<*> {
return someLongRunningProcessPossiblyHanging()
}
}
When I call the endpoint, the request never times out, it just hangs indefinitely.
Am I missing something?
NOTE: I've also been informed that Tomcat uses this field in minutes, not milliseconds (rather unusual choice IMO). I've tried setting this to server.connection-timeout=1 denoting 1 minute, but this didn't work either.
NOTE: I don't want another HTTP request to cause the previous request to time out, I want each HTTP request to timeout of it's own accord, should too much time elapse to serve the request.
connection-timeout does not apply to long running requests. It does apply to the initial connection, when the server waits for the client to say something.
Tomcat docs (not Spring Boot) define it as The number of milliseconds this Connector will wait, after accepting a connection, for the request URI line to be presented [...]
To test the setting server.connection-timeout=4000 I connect using netcat and I don't send any HTTP request/headers. I get:
$ time nc -vv localhost 1234
Connection to localhost 1234 port [tcp/*] succeeded!
real 0m4.015s
user 0m0.000s
sys 0m0.000s
Alternatives
1) Async
From brightinventions.pl - Spring MVC Thread Pool Timeouts:
In Spring MVC there is no way to configure a timeout unless you use async method. With async method one can use spring.mvc.async.request-timeout= to set amount of time (in milliseconds) before asynchronous request handling times out.
I've set spring.mvc.async.request-timeout=4000 and I get a timeout in the browser with this:
#GetMapping("/test-async")
public Callable<String> getFoobar() {
return () -> {
Thread.sleep(12000); //this will cause a timeout
return "foobar";
};
}
See Spring Boot REST API - request timeout?
2) Servlet filter
Another solution would be to use a servlet filter brightinventions.pl - Request timeouts in Spring MVC (Kotlin):
override fun doFilterInternal(request: HttpServletRequest, response: HttpServletResponse, filterChain: FilterChain) {
val completed = AtomicBoolean(false)
val requestHandlingThread = Thread.currentThread()
val timeout = timeoutsPool.schedule({
if (completed.compareAndSet(false, true)) {
requestHandlingThread.interrupt()
}
}, 5, TimeUnit.SECONDS)
try {
filterChain.doFilter(request, response)
timeout.cancel(false)
} finally {
completed.set(true)
}
}
3) Tomcat Stuck Thread Detection Valve?
Tomcat has a Stuck Thread Detection Valve but I don't know if this can be configured programmatically using Spring Boot.
From the official docs:
server.connection-timeout= # Time that connectors wait for another HTTP request before closing the connection. When not set, the connector's container-specific default is used. Use a value of -1 to indicate no (that is, an infinite) timeout.
Another ref, also mentions the same. It should work for you.
When I call the endpoint, the request never times out, it just hangs indefinitely.
server.connection-timeout isn't a request timeout. It is a timeout for idle connections, i.e. those that have already had a request/response pair and on which the server is now awaiting a second request. It is essentially a server-side read timeout.
To convince some people to switch from old school tech, I need to build a chat demo application that manages more than 10K concurrent connections using Java (like Node.Js stuff).
I have tested Netty 5.0 which is awesome but requires lot of work to be done; on the other hand Jetty 9.3 is great but is slow compared to other competitors.
After some search I found the Vert.x 3 toolkit which is based on Netty with a plethora of great tools (no need to reinvent the wheel), I have seen the examples in git and I was able to build a websocket server, etc.
public void start() throws Exception {
vertx.createHttpServer().websocketHandler(new Handler<ServerWebSocket>() {
#Override
public void handle(ServerWebSocket e) {
// business stuff in the old style not yet lambda
}
}).listen(port);
}
Being new to the Vert.x world, I could not figure out how to manage connected users using it, normally the old fashion way is to use something like:
HashMap<UUID,ServerWebSocket> connectedUsers;
When a connection is established I check if it exists; if not I add it as a new entry and do some functions to send, broadcast, retrieve through the collection and so on.
My question is does Vert.x 3 have something to deal with connections to track them and remove those who left (ping pong), broadcast, etc. or should I implement them from scratch using cookies, session, ....)
I could not find any real example using Vert.x 3.
Basically, the scope of the websocketHandler represents a connection. In your example this is your anonymous class. I created a little websocket chat example where I use the Vert.x event bus to distribute the messages to all the clients.
In the start method of the server we handle the websocket connections. You can implement the closeHandler to monitor client disconnection. There are also handlers for exceptions, ping-pong, etc. You can identify a specific connection by using the textHandlerID, but you have also access to the remote address.
public void start() throws Exception {
vertx.createHttpServer().websocketHandler(handler -> {
System.out.println("client connected: "+handler.textHandlerID());
vertx.eventBus().consumer(CHAT_CHANNEL, message -> {
handler.writeTextMessage((String)message.body());
});
handler.textMessageHandler(message -> {
vertx.eventBus().publish(CHAT_CHANNEL,message);
});
handler.closeHandler(message ->{
System.out.println("client disconnected "+handler.textHandlerID());
});
}).listen(8080);
}
The client example is also written in Java. It just prints all the received messages on the websocket connection to the console. After connection it sends a message.
public void start() throws Exception {
HttpClient client = vertx.createHttpClient();
client.websocket(8080, "localhost", "", websocket -> {
websocket.handler(data -> System.out.println(data.toString("ISO-8859-1")));
websocket.writeTextMessage(NAME+ ":hello from client");
});
}
I am using a restlet 2.1 client sever based architecture, my client times out within 1 minute after sending the request. and I get the following exception :
Internal Connector Error (1002) - The calling thread timed out while waiting for a response to unblock it.
at org.restlet.resource.ClientResource$1.invoke(ClientResource.java:1663)
at com.sun.proxy.$Proxy17.getTaskList(Unknown Source)....
My code is as below :
import org.restlet.resource.ClientResource;
ClientResource cr = new ClientResource(uri);
MyResource resource= cr.wrap(MyResource .class);
updateStatus = resource.updateData(Parameter);
i also tried this code :
Context context = new Context();
context.getParameters().add("socketTimeout", new String("180000"));
context.getParameters().add("socketConnectTimeoutMs", new String("180000"));
context.getParameters().add("idleTimeout", new String("180000"));
ClientResource cr = new ClientResource(context, url);
TasksResource resource = cr.wrap(TasksResource.class);
how should I configure my client resource to avoid timeout ?
The connection timeout for a Restlet client can be configured at the client connector level. If your call is within a component, you can get the client connector from it (class Client), otherwise you need to instantiate it. Configuring timeout can be done through its parameters (method getContext and then getParameters).
Parameters depend on the underlying connectors (HTTP client, ...).
The following links will help you to fix your issue:
Restlet HTTP Connection Pool
Restlet timeout
Hope it helps you,
Thierry