proxy_cache_lock_timeout - nginx send timeout
Proxy de Jetty WebSocket (1)
Solo me pregunto si alguien ha experimentado con el proxy WebSocket (para un proxy transparente) usando Jetty integrado.
Después de aproximadamente un día y medio de jugar con Jetty 9.1.2.v20140210, todo lo que puedo decir es que no puede usar WebSockets en su forma actual, y agregar ese soporte no es una tarea trivial (al menos, por lo menos).
Básicamente, Jetty ProxyServlet elimina los campos de encabezado "Actualizar" y "Conexión" independientemente de si se trata de una solicitud de reconocimiento de WebSocket. Agregar estos campos de vuelta es fácil como se muestra a continuación. Pero, cuando el servidor proxy devolvió una respuesta con el código HTTP 101 (protocolos de conmutación), no se realiza ninguna actualización de protocolo en el servidor proxy. Entonces, cuando llega el primer paquete WebSocket, el HttpParser se atraganta y lo ve como una solicitud HTTP incorrecta.
Si alguien ya tiene una solución para esto o está familiarizado con Jetty para sugerir qué probar, eso sería muy apreciado.
A continuación se muestra el código de mi experimento que elimina los bits sin importancia:
public class ProxyServer
{
public static void main(String[] args) throws Exception
{
Server server = new Server();
ServerConnector connector = new ServerConnector(server);
connector.setPort(8888);
server.addConnector(connector);
// Setup proxy handler to handle CONNECT methods
ConnectHandler proxy = new ConnectHandler();
server.setHandler(proxy);
// Setup proxy servlet
ServletContextHandler context = new ServletContextHandler(proxy, "/", ServletContextHandler.SESSIONS);
ServletHolder proxyServlet = new ServletHolder(MyProxyServlet.class);
context.addServlet(proxyServlet, "/*");
server.start();
}
}
@SuppressWarnings("serial")
public class MyProxyServlet extends ProxyServlet
{
@Override
protected void customizeProxyRequest(Request proxyRequest, HttpServletRequest request)
{
// Pass through the upgrade and connection header fields for websocket handshake request.
String upgradeValue = request.getHeader("Upgrade");
if (upgradeValue != null && upgradeValue.compareToIgnoreCase("websocket") == 0)
{
setHeader(proxyRequest, "Upgrade", upgradeValue);
setHeader(proxyRequest, "Connection", request.getHeader("Connection"));
}
}
@Override
protected void onResponseHeaders(HttpServletRequest request, HttpServletResponse response, Response proxyResponse)
{
super.onResponseHeaders(request, response, proxyResponse);
// Restore the upgrade and connection header fields for websocket handshake request.
HttpFields fields = proxyResponse.getHeaders();
for (HttpField field : fields)
{
if (field.getName().compareToIgnoreCase("Upgrade") == 0)
{
String upgradeValue = field.getValue();
if (upgradeValue != null && upgradeValue.compareToIgnoreCase("websocket") == 0)
{
response.setHeader(field.getName(), upgradeValue);
for (HttpField searchField : fields)
{
if (searchField.getName().compareToIgnoreCase("Connection") == 0) {
response.setHeader(searchField.getName(), searchField.getValue());
}
}
}
}
}
}
}
Imaginemos el esquema de proxy que está intentando construir, tenemos el cliente A , el servidor B y el proxy P. Ahora veamos el flujo de trabajo de conexión: 1. Una conexión TCP establecida con el proxy P (AP) 2. A envía una solicitud CONNECT addr (B) con el protocolo de enlace WebSocket
Aquí tiene el primer problema: los encabezados RFC HTTP utilizados en el protocolo de enlace WS no son encabezados de extremo a extremo, porque para HTTP solo tienen sentido en una capa de transporte (entre dos saltos).
- P establece conexión TCP a B (PB)
- P envía la solicitud HTTP del protocolo de enlace WS a B
- B responde con HTTP-> actualización WS (enviando 101)
Y aquí hay otro problema, después de enviar el servidor HTTP 101 B y el cliente A ahora se comunicará solo a través de TCP, pero el servlet de Jetty no admite la propagación de paquetes TCP sin formato. En otras palabras, el servlet proxy de Jetty espera hasta que el cliente A comience a transmitir la solicitud HTTP, lo que nunca sucederá después de que A reciba HTTP 101.
Necesitará implementar esto por usted mismo utilizando el servidor WS y el cliente WS.