Skip to content

Commit

Permalink
support send websocket binary fix #2818
Browse files Browse the repository at this point in the history
- added `Websocket.renderBinary`
  • Loading branch information
jknack committed May 14, 2023
1 parent f3bcf48 commit d23270a
Show file tree
Hide file tree
Showing 8 changed files with 125 additions and 15 deletions.
7 changes: 4 additions & 3 deletions jooby/src/main/java/io/jooby/Context.java
Original file line number Diff line number Diff line change
Expand Up @@ -1387,13 +1387,14 @@ default ParamLookup lookup() {
* <p>This context is necessary for creating a bridge between {@link MessageEncoder} and {@link
* WebSocket}.
*
* <p>This method is part of Public API, but direct usage is discourage.
* <p>This method is part of Public API, but direct usage is discouraged.
*
* @param ctx Originating context.
* @param ws WebSocket.
* @param binary True for sending binary message.
* @return Read only context.
*/
static @NonNull Context websocket(@NonNull Context ctx, @NonNull WebSocket ws) {
return new WebSocketSender(ctx, ws);
static @NonNull Context websocket(@NonNull Context ctx, @NonNull WebSocket ws, boolean binary) {
return new WebSocketSender(ctx, ws, binary);
}
}
20 changes: 20 additions & 0 deletions jooby/src/main/java/io/jooby/WebSocket.java
Original file line number Diff line number Diff line change
Expand Up @@ -262,6 +262,26 @@ interface OnError {
*/
@NonNull WebSocket render(@NonNull Object value, boolean broadcast);

/**
* Encode a value and send a binary message to client.
*
* @param value Value to send.
* @return This websocket.
*/
default @NonNull WebSocket renderBinary(@NonNull Object value) {
return renderBinary(value, false);
}

/**
* Encode a value and send a binary message to current client (broadcast = false) or to ALL
* connected clients under the websocket path (broadcast = true).
*
* @param value Value to send.
* @param broadcast True to send to all connected clients.
* @return This websocket.
*/
@NonNull WebSocket renderBinary(@NonNull Object value, boolean broadcast);

/**
* Close the web socket and send a {@link WebSocketCloseStatus#NORMAL} code to client.
*
Expand Down
16 changes: 13 additions & 3 deletions jooby/src/main/java/io/jooby/internal/WebSocketSender.java
Original file line number Diff line number Diff line change
Expand Up @@ -22,21 +22,31 @@
public class WebSocketSender extends ForwardingContext implements DefaultContext {

private final WebSocket ws;
private final boolean binary;

public WebSocketSender(@NonNull Context context, @NonNull WebSocket ws) {
public WebSocketSender(@NonNull Context context, @NonNull WebSocket ws, boolean binary) {
super(context);
this.ws = ws;
this.binary = binary;
}

@NonNull @Override
public Context send(@NonNull String data, @NonNull Charset charset) {
ws.send(data);
if (binary) {
ws.sendBinary(data.getBytes(charset));
} else {
ws.send(data.getBytes(charset));
}
return this;
}

@NonNull @Override
public Context send(@NonNull byte[] data) {
ws.send(data);
if (binary) {
ws.sendBinary(data);
} else {
ws.send(data);
}
return this;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -233,13 +233,22 @@ private WebSocket sendMessage(

@NonNull @Override
public WebSocket render(@NonNull Object value, boolean broadcast) {
return renderMessage(value, broadcast, false);
}

@NonNull @Override
public WebSocket renderBinary(@NonNull Object value, boolean broadcast) {
return renderMessage(value, broadcast, true);
}

private WebSocket renderMessage(Object value, boolean broadcast, boolean binary) {
if (broadcast) {
for (WebSocket ws : all.getOrDefault(key, Collections.emptyList())) {
ws.render(value, false);
for (JettyWebSocket ws : all.getOrDefault(key, Collections.emptyList())) {
ws.renderMessage(value, false, binary);
}
} else {
try {
Context.websocket(ctx, this).render(value);
Context.websocket(ctx, this, binary).render(value);
} catch (Throwable x) {
onWebSocketError(x);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -85,13 +85,22 @@ public WebSocket sendBinary(@NonNull byte[] message, boolean broadcast) {

@Override
public WebSocket render(Object value, boolean broadcast) {
return renderMessage(value, broadcast, false);
}

@Override
public WebSocket renderBinary(Object value, boolean broadcast) {
return renderMessage(value, broadcast, true);
}

private WebSocket renderMessage(Object value, boolean broadcast, boolean binary) {
if (broadcast) {
for (WebSocket ws : all.getOrDefault(key, Collections.emptyList())) {
ws.render(value, false);
for (NettyWebSocket ws : all.getOrDefault(key, Collections.emptyList())) {
ws.renderMessage(value, false, binary);
}
} else {
try {
Context.websocket(netty, this).render(value);
Context.websocket(netty, this, binary).render(value);
} catch (Throwable x) {
handleError(x);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -94,6 +94,11 @@ public WebSocket render(@NonNull Object value, boolean broadcast) {
return sendObject(value, broadcast);
}

@NonNull @Override
public WebSocket renderBinary(@NonNull Object value, boolean broadcast) {
return sendObject(value, broadcast);
}

@NonNull @Override
public WebSocket close(@NonNull WebSocketCloseStatus closeStatus) {
try {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -150,13 +150,22 @@ private WebSocket sendMessage(ByteBuffer buffer, boolean binary, boolean broadca

@NonNull @Override
public WebSocket render(@NonNull Object value, boolean broadcast) {
return renderMessage(value, broadcast, false);
}

@NonNull @Override
public WebSocket renderBinary(@NonNull Object value, boolean broadcast) {
return renderMessage(value, broadcast, true);
}

private WebSocket renderMessage(Object value, boolean broadcast, boolean binary) {
if (broadcast) {
for (WebSocket ws : all.getOrDefault(key, Collections.emptyList())) {
ws.render(value, false);
for (UndertowWebSocket ws : all.getOrDefault(key, Collections.emptyList())) {
ws.renderMessage(value, false, binary);
}
} else {
try {
Context.websocket(ctx, this).render(value);
Context.websocket(ctx, this, binary).render(value);
} catch (Throwable x) {
onError(channel, x);
}
Expand Down
47 changes: 47 additions & 0 deletions tests/src/test/java/io/jooby/i2818/Issue2818.java
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,9 @@
import static org.junit.jupiter.api.Assertions.assertEquals;

import java.nio.charset.StandardCharsets;
import java.util.Map;

import io.jooby.jackson.JacksonModule;
import io.jooby.junit.ServerTest;
import io.jooby.junit.ServerTestRunner;

Expand Down Expand Up @@ -106,4 +108,49 @@ public void shouldBroadcastBinaryFromByteArray(ServerTestRunner runner) {
});
});
}

@ServerTest
public void shouldRenderBinary(ServerTestRunner runner) {
runner
.define(
app -> {
app.install(new JacksonModule());
app.ws(
"/ws/render-bin",
(ctx, initializer) -> {
initializer.onMessage((ws, message) -> ws.renderBinary(Map.of("foo", "bar")));
});
})
.ready(
client -> {
client.syncWebSocket(
"/ws/render-bin",
ws -> {
assertEquals("{\"foo\":\"bar\"}", ws.send("binary"));
});
});
}

@ServerTest
public void shouldBroadcastRenderBinary(ServerTestRunner runner) {
runner
.define(
app -> {
app.install(new JacksonModule());
app.ws(
"/ws/render-bin",
(ctx, initializer) -> {
initializer.onMessage(
(ws, message) -> ws.renderBinary(Map.of("foo", "bar"), true));
});
})
.ready(
client -> {
client.syncWebSocket(
"/ws/render-bin",
ws -> {
assertEquals("{\"foo\":\"bar\"}", ws.send("binary"));
});
});
}
}

0 comments on commit d23270a

Please sign in to comment.