Skip to content

Commit

Permalink
Make WebSocketService interface (line#5368)
Browse files Browse the repository at this point in the history
Motivation:

`WebsocketService` is a final class, so it is not easy to make another
service run WebSocket and HTTP requests on the same path.

`WebSocketService` is changed as a marker interface in line#5280. However,
the interface does not have API, the service cannot take advantage of
the protocol detection of the original `WebSocketService`. Graphql
WebSocket implementation copied and pasted similar code for WebSocket
detection.

The design of the code here was determined after discussions with other
maintainers based on the idea from
line#5280 (comment)

Modifications:

- Add `WebSocketService` interface and rename the original one to
`DefaultWebSocketService`
- Add `WebSocketProtocolHandler` that is in charge of:
  - Upgrade HTTP request to WebSocket
  - Decode HTTP request to WebSocket for inbound
  - Encode WebSocket to HTTP response for outbound
- Refactor `DefaultWebSocketService` to implement new methods
`WebSocketService` and `WebSocketProtocolHandler`
- Modify Webservicebuilder so that a fallback service can be configured.
- The fallback service would be useful when WebSocket and HTTP request
is served at the same path.

Result:

- You can now set a fallback service to `WebSocketService` via
`WebSocketServiceBuilder.fallbackService()`
- Refactor `WebsocketService` to enable composion and delegatation.
  • Loading branch information
ikhoon authored Jan 22, 2024
1 parent 7031340 commit 3963f2a
Show file tree
Hide file tree
Showing 13 changed files with 742 additions and 297 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ final class WebSocketClientFrameDecoder extends WebSocketFrameDecoder {

WebSocketClientFrameDecoder(ClientRequestContext ctx, int maxFramePayloadLength,
boolean allowMaskMismatch) {
super(ctx, maxFramePayloadLength, allowMaskMismatch);
super(maxFramePayloadLength, allowMaskMismatch);
this.ctx = ctx;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@

import com.linecorp.armeria.common.annotation.UnstableApi;
import com.linecorp.armeria.common.stream.StreamMessage;
import com.linecorp.armeria.internal.common.websocket.WebSocketWrapper;

/**
* A {@link StreamMessage} that publishes {@link WebSocketFrame}s.
Expand All @@ -30,4 +31,12 @@ public interface WebSocket extends StreamMessage<WebSocketFrame> {
static WebSocketWriter streaming() {
return new DefaultWebSocket();
}

/**
* Returns a new {@link WebSocket} whose stream is produced from the specified {@link StreamMessage}.
*/
@UnstableApi
static WebSocket of(StreamMessage<WebSocketFrame> delegate) {
return new WebSocketWrapper(delegate);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,6 @@
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.linecorp.armeria.common.RequestContext;
import com.linecorp.armeria.common.annotation.Nullable;
import com.linecorp.armeria.common.stream.HttpDecoder;
import com.linecorp.armeria.common.stream.StreamDecoderInput;
Expand Down Expand Up @@ -64,7 +63,6 @@ enum State {
CORRUPT
}

private final RequestContext ctx;
private final int maxFramePayloadLength;
private final boolean allowMaskMismatch;
@Nullable
Expand All @@ -81,8 +79,7 @@ enum State {
private boolean receivedClosingHandshake;
private State state = State.READING_FIRST;

protected WebSocketFrameDecoder(RequestContext ctx, int maxFramePayloadLength, boolean allowMaskMismatch) {
this.ctx = ctx;
protected WebSocketFrameDecoder(int maxFramePayloadLength, boolean allowMaskMismatch) {
this.maxFramePayloadLength = maxFramePayloadLength;
this.allowMaskMismatch = allowMaskMismatch;
}
Expand Down
Loading

0 comments on commit 3963f2a

Please sign in to comment.