Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Allow WebSocket maxFrameSize to be configured #2195

Merged
merged 2 commits into from Mar 12, 2020
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
2 changes: 1 addition & 1 deletion Sources/Vapor/Response/Response.swift
Expand Up @@ -33,7 +33,7 @@ public final class Response: CustomStringConvertible {
}

internal enum Upgrader {
case webSocket(onUpgrade: (WebSocket) -> ())
case webSocket(maxFrameSize: Int?, onUpgrade: (WebSocket) -> ())
}

internal var upgrader: Upgrader?
Expand Down
3 changes: 2 additions & 1 deletion Sources/Vapor/Routing/RoutesBuilder+WebSocket.swift
Expand Up @@ -2,11 +2,12 @@ extension RoutesBuilder {
@discardableResult
public func webSocket(
_ path: PathComponent...,
maxFrameSize: Int? = nil,
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

As a user, passing app.webSocket(maxFrameSize: nil) { ... } might make me think I'm disabling max frame size here. Maybe an enum instead would better express this?

enum WebSocketMaxFrameSize {
    case default
    case override(Int)
}

extension WebSocketMaxFrameSize: ExpressibleByIntegerLiteral {
    init(integerValue: Int) { 
        self = .override(integerValue)
    }
}

We could re-use this enum on the top-level config as well.

This may be overly pedantic though and perhaps a doc block explaining the behavior would be sufficient. What are your thoughts?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The enum is a good idea! I just updated the PR to use the enum.

onUpgrade: @escaping (Request, WebSocket) -> ()
) -> Route {
return self.on(.GET, path) { request -> Response in
let res = Response(status: .switchingProtocols)
res.upgrader = .webSocket(onUpgrade: { ws in
res.upgrader = .webSocket(maxFrameSize: maxFrameSize, onUpgrade: { ws in
onUpgrade(request, ws)
})
return res
Expand Down
5 changes: 3 additions & 2 deletions Sources/Vapor/Server/HTTPServerUpgradeHandler.swift
Expand Up @@ -51,8 +51,9 @@ final class HTTPServerUpgradeHandler: ChannelDuplexHandler, RemovableChannelHand
self.upgradeState = .upgraded
if res.status == .switchingProtocols, let upgrader = res.upgrader {
switch upgrader {
case .webSocket(let onUpgrade):
let webSocketUpgrader = NIOWebSocketServerUpgrader(automaticErrorHandling: false, shouldUpgrade: { channel, _ in
case .webSocket(let maxFrameSize, let onUpgrade):
let maxFrameSize = maxFrameSize ?? 1 << 14
let webSocketUpgrader = NIOWebSocketServerUpgrader(maxFrameSize: maxFrameSize, automaticErrorHandling: false, shouldUpgrade: { channel, _ in
return channel.eventLoop.makeSucceededFuture([:])
}, upgradePipelineHandler: { channel, req in
return WebSocket.server(on: channel, onUpgrade: onUpgrade)
Expand Down