Protocol::WebSocketSourceProtocolWebSocketExtensionsServer

class Server

Manages extensions on the server side, negotiating client offers and applying the agreed extensions.

Definitions

def self.default

Create a default server with permessage-deflate compression enabled.

Signature

returns Server

A new server with the default compression extension.

Implementation

def self.default
	self.new([
		[Extension::Compression, {}]
	])
end

def initialize(extensions)

Initialize a new server extension manager.

Signature

parameter extensions Array

The list of supported extensions, each as [klass, options].

Implementation

def initialize(extensions)
	@extensions = extensions
	@accepted = []
end

attr :extensions

Signature

attribute Array

The list of supported extensions.

attr :accepted

Signature

attribute Array

The extensions accepted after negotiation.

def named

Build a lookup table of extensions keyed by their name.

Signature

returns Hash

A hash mapping extension names to their [klass, options] pairs.

Implementation

def named
	@extensions.map do |extension|
		[extension.first::NAME, extension]
	end.to_h
end

def accept(headers)

Negotiate client extension offers and yield accepted response headers.

Signature

parameter headers Array(String)

The Sec-WebSocket-Extensions request header values.

yields {|header| ...}

Each accepted extension header to include in the response.

parameter header Array(String)

The negotiated extension header tokens.

returns Array

The accepted extensions as [klass, options] pairs.

Implementation

def accept(headers)
	extensions = []
	
	named = self.named
	response = []
	
	# Each response header should map to at least one extension.
	Extensions.parse(headers) do |name, arguments|
		if extension = named[name]
			klass, options = extension
			
			if result = klass.negotiate(arguments, **options)
				header, options = result
				
				# The extension is accepted and no further offers will be considered:
				named.delete(name)
				
				yield header if block_given?
				
				@accepted << [klass, options]
			end
		end
	end
	
	return @accepted
end

def apply(connection)

Apply all accepted extensions to the given connection as a server.

Signature

parameter connection Connection

The WebSocket connection to configure.

Implementation

def apply(connection)
	@accepted.reverse_each do |(klass, options)|
		klass.server(connection, **options)
	end
end