mirror of
https://github.com/signalapp/Signal-Server
synced 2026-04-19 23:08:03 +01:00
Add websocket-resources as a module
This commit is contained in:
@@ -0,0 +1,64 @@
|
||||
package org.whispersystems.websocket;
|
||||
|
||||
import org.eclipse.jetty.server.AbstractNCSARequestLog;
|
||||
import org.eclipse.jetty.server.NCSARequestLog;
|
||||
import org.eclipse.jetty.server.RequestLog;
|
||||
import org.eclipse.jetty.util.component.AbstractLifeCycle;
|
||||
import org.eclipse.jetty.websocket.api.RemoteEndpoint;
|
||||
import org.junit.Test;
|
||||
import org.whispersystems.websocket.messages.WebSocketMessageFactory;
|
||||
import org.whispersystems.websocket.messages.WebSocketRequestMessage;
|
||||
import org.whispersystems.websocket.servlet.LoggableRequest;
|
||||
import org.whispersystems.websocket.servlet.LoggableResponse;
|
||||
import org.whispersystems.websocket.servlet.WebSocketServletRequest;
|
||||
import org.whispersystems.websocket.servlet.WebSocketServletResponse;
|
||||
import org.whispersystems.websocket.session.WebSocketSessionContext;
|
||||
|
||||
import javax.servlet.ServletContext;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Optional;
|
||||
|
||||
import static org.mockito.Mockito.mock;
|
||||
import static org.mockito.Mockito.when;
|
||||
|
||||
public class LoggableRequestResponseTest {
|
||||
|
||||
@Test
|
||||
public void testLogging() {
|
||||
NCSARequestLog requestLog = new EnabledNCSARequestLog();
|
||||
|
||||
WebSocketClient webSocketClient = mock(WebSocketClient.class );
|
||||
WebSocketRequestMessage requestMessage = mock(WebSocketRequestMessage.class);
|
||||
ServletContext servletContext = mock(ServletContext.class );
|
||||
RemoteEndpoint remoteEndpoint = mock(RemoteEndpoint.class );
|
||||
WebSocketMessageFactory messageFactory = mock(WebSocketMessageFactory.class);
|
||||
|
||||
when(requestMessage.getVerb()).thenReturn("GET");
|
||||
when(requestMessage.getBody()).thenReturn(Optional.empty());
|
||||
when(requestMessage.getHeaders()).thenReturn(new HashMap<>());
|
||||
when(requestMessage.getPath()).thenReturn("/api/v1/test");
|
||||
when(requestMessage.getRequestId()).thenReturn(1L);
|
||||
when(requestMessage.hasRequestId()).thenReturn(true);
|
||||
|
||||
WebSocketSessionContext sessionContext = new WebSocketSessionContext (webSocketClient );
|
||||
HttpServletRequest servletRequest = new WebSocketServletRequest (sessionContext, requestMessage, servletContext);
|
||||
HttpServletResponse servletResponse = new WebSocketServletResponse(remoteEndpoint, 1, messageFactory );
|
||||
|
||||
LoggableRequest loggableRequest = new LoggableRequest (servletRequest );
|
||||
LoggableResponse loggableResponse = new LoggableResponse(servletResponse);
|
||||
|
||||
requestLog.log(loggableRequest, loggableResponse);
|
||||
}
|
||||
|
||||
|
||||
private class EnabledNCSARequestLog extends NCSARequestLog {
|
||||
@Override
|
||||
public boolean isEnabled() {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,73 @@
|
||||
package org.whispersystems.websocket;
|
||||
|
||||
|
||||
import org.eclipse.jetty.websocket.api.Session;
|
||||
import org.eclipse.jetty.websocket.servlet.ServletUpgradeRequest;
|
||||
import org.eclipse.jetty.websocket.servlet.ServletUpgradeResponse;
|
||||
import org.junit.Test;
|
||||
import org.whispersystems.websocket.auth.AuthenticationException;
|
||||
import org.whispersystems.websocket.auth.WebSocketAuthenticator;
|
||||
import org.whispersystems.websocket.setup.WebSocketEnvironment;
|
||||
|
||||
import javax.servlet.ServletException;
|
||||
import java.io.IOException;
|
||||
import java.util.Optional;
|
||||
|
||||
import io.dropwizard.jersey.setup.JerseyEnvironment;
|
||||
import static org.junit.Assert.*;
|
||||
import static org.mockito.Matchers.eq;
|
||||
import static org.mockito.Mockito.*;
|
||||
|
||||
public class WebSocketResourceProviderFactoryTest {
|
||||
|
||||
@Test
|
||||
public void testUnauthorized() throws ServletException, AuthenticationException, IOException {
|
||||
JerseyEnvironment jerseyEnvironment = mock(JerseyEnvironment.class );
|
||||
WebSocketEnvironment environment = mock(WebSocketEnvironment.class );
|
||||
WebSocketAuthenticator authenticator = mock(WebSocketAuthenticator.class);
|
||||
ServletUpgradeRequest request = mock(ServletUpgradeRequest.class );
|
||||
ServletUpgradeResponse response = mock(ServletUpgradeResponse.class);
|
||||
|
||||
when(environment.getAuthenticator()).thenReturn(authenticator);
|
||||
when(authenticator.authenticate(eq(request))).thenReturn(new WebSocketAuthenticator.AuthenticationResult<>(Optional.empty(), true));
|
||||
when(environment.jersey()).thenReturn(jerseyEnvironment);
|
||||
|
||||
WebSocketResourceProviderFactory factory = new WebSocketResourceProviderFactory(environment);
|
||||
Object connection = factory.createWebSocket(request, response);
|
||||
|
||||
assertNull(connection);
|
||||
verify(response).sendForbidden(eq("Unauthorized"));
|
||||
verify(authenticator).authenticate(eq(request));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testValidAuthorization() throws AuthenticationException, ServletException {
|
||||
JerseyEnvironment jerseyEnvironment = mock(JerseyEnvironment.class );
|
||||
WebSocketEnvironment environment = mock(WebSocketEnvironment.class );
|
||||
WebSocketAuthenticator authenticator = mock(WebSocketAuthenticator.class);
|
||||
ServletUpgradeRequest request = mock(ServletUpgradeRequest.class );
|
||||
ServletUpgradeResponse response = mock(ServletUpgradeResponse.class);
|
||||
Session session = mock(Session.class );
|
||||
Account account = new Account();
|
||||
|
||||
when(environment.getAuthenticator()).thenReturn(authenticator);
|
||||
when(authenticator.authenticate(eq(request))).thenReturn(new WebSocketAuthenticator.AuthenticationResult<>(Optional.of(account), true));
|
||||
when(environment.jersey()).thenReturn(jerseyEnvironment);
|
||||
|
||||
WebSocketResourceProviderFactory factory = new WebSocketResourceProviderFactory(environment);
|
||||
Object connection = factory.createWebSocket(request, response);
|
||||
|
||||
assertNotNull(connection);
|
||||
verifyNoMoreInteractions(response);
|
||||
verify(authenticator).authenticate(eq(request));
|
||||
|
||||
((WebSocketResourceProvider)connection).onWebSocketConnect(session);
|
||||
|
||||
assertNotNull(((WebSocketResourceProvider) connection).getContext().getAuthenticated());
|
||||
assertEquals(((WebSocketResourceProvider)connection).getContext().getAuthenticated(), account);
|
||||
}
|
||||
|
||||
private static class Account {}
|
||||
|
||||
|
||||
}
|
||||
@@ -0,0 +1,90 @@
|
||||
package org.whispersystems.websocket;
|
||||
|
||||
import org.eclipse.jetty.server.RequestLog;
|
||||
import org.eclipse.jetty.websocket.api.CloseStatus;
|
||||
import org.eclipse.jetty.websocket.api.RemoteEndpoint;
|
||||
import org.eclipse.jetty.websocket.api.Session;
|
||||
import org.eclipse.jetty.websocket.api.UpgradeRequest;
|
||||
import org.junit.Test;
|
||||
import org.mockito.ArgumentCaptor;
|
||||
import org.whispersystems.websocket.WebSocketResourceProvider;
|
||||
import org.whispersystems.websocket.auth.AuthenticationException;
|
||||
import org.whispersystems.websocket.auth.WebSocketAuthenticator;
|
||||
import org.whispersystems.websocket.messages.protobuf.ProtobufWebSocketMessageFactory;
|
||||
import org.whispersystems.websocket.setup.WebSocketConnectListener;
|
||||
|
||||
import javax.servlet.http.HttpServlet;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
import java.io.IOException;
|
||||
import java.util.LinkedList;
|
||||
import java.util.Optional;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.mockito.Mockito.*;
|
||||
|
||||
public class WebSocketResourceProviderTest {
|
||||
|
||||
@Test
|
||||
public void testOnConnect() throws AuthenticationException, IOException {
|
||||
HttpServlet contextHandler = mock(HttpServlet.class);
|
||||
WebSocketAuthenticator<String> authenticator = mock(WebSocketAuthenticator.class);
|
||||
RequestLog requestLog = mock(RequestLog.class);
|
||||
WebSocketResourceProvider provider = new WebSocketResourceProvider(contextHandler, requestLog,
|
||||
null,
|
||||
new ProtobufWebSocketMessageFactory(),
|
||||
Optional.empty(),
|
||||
30000);
|
||||
|
||||
Session session = mock(Session.class );
|
||||
UpgradeRequest request = mock(UpgradeRequest.class);
|
||||
|
||||
when(session.getUpgradeRequest()).thenReturn(request);
|
||||
when(authenticator.authenticate(request)).thenReturn(new WebSocketAuthenticator.AuthenticationResult<>(Optional.of("fooz"), true));
|
||||
|
||||
provider.onWebSocketConnect(session);
|
||||
|
||||
verify(session, never()).close(anyInt(), anyString());
|
||||
verify(session, never()).close();
|
||||
verify(session, never()).close(any(CloseStatus.class));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testRouteMessage() throws Exception {
|
||||
HttpServlet servlet = mock(HttpServlet.class );
|
||||
WebSocketAuthenticator<String> authenticator = mock(WebSocketAuthenticator.class);
|
||||
RequestLog requestLog = mock(RequestLog.class );
|
||||
WebSocketResourceProvider provider = new WebSocketResourceProvider(servlet, requestLog, Optional.of((WebSocketAuthenticator)authenticator), new ProtobufWebSocketMessageFactory(), Optional.empty(), 30000);
|
||||
|
||||
Session session = mock(Session.class );
|
||||
RemoteEndpoint remoteEndpoint = mock(RemoteEndpoint.class);
|
||||
UpgradeRequest request = mock(UpgradeRequest.class);
|
||||
|
||||
when(session.getUpgradeRequest()).thenReturn(request);
|
||||
when(session.getRemote()).thenReturn(remoteEndpoint);
|
||||
when(authenticator.authenticate(request)).thenReturn(new WebSocketAuthenticator.AuthenticationResult<>(Optional.of("foo"), true));
|
||||
|
||||
provider.onWebSocketConnect(session);
|
||||
|
||||
verify(session, never()).close(anyInt(), anyString());
|
||||
verify(session, never()).close();
|
||||
verify(session, never()).close(any(CloseStatus.class));
|
||||
|
||||
byte[] message = new ProtobufWebSocketMessageFactory().createRequest(Optional.of(111L), "GET", "/bar", new LinkedList<String>(), Optional.of("hello world!".getBytes())).toByteArray();
|
||||
|
||||
provider.onWebSocketBinary(message, 0, message.length);
|
||||
|
||||
ArgumentCaptor<HttpServletRequest> requestCaptor = ArgumentCaptor.forClass(HttpServletRequest.class);
|
||||
|
||||
verify(servlet).service(requestCaptor.capture(), any(HttpServletResponse.class));
|
||||
|
||||
HttpServletRequest bundledRequest = requestCaptor.getValue();
|
||||
|
||||
byte[] expected = new byte[bundledRequest.getInputStream().available()];
|
||||
int read = bundledRequest.getInputStream().read(expected);
|
||||
|
||||
assertThat(read).isEqualTo(expected.length);
|
||||
assertThat(new String(expected)).isEqualTo("hello world!");
|
||||
}
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user