websocket-server 1.1.4-java → 1.2.0-java

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: ed1041a901164c473dbfb099e709e6195fc9f206fca0659125b9a417dc911312
4
- data.tar.gz: 230e76a31baf6d4d7647b4f21b76c60e36bcf0f1a9860d7cffcf20010387a751
3
+ metadata.gz: 64315a4d554857c31f1dd058666d4ff50813ec6a0afe829ad89434ab997ad55a
4
+ data.tar.gz: 6732df15258e1c3fcb5b2552160ad1125e383ab42bc7fa29763e992bf93c920a
5
5
  SHA512:
6
- metadata.gz: 7f2b3c9a744be8afa350a108e8b2c39017f049a6ab9aaf3e0ea3c54886212d7a4c0d79daa0d86d48882e34f7a8a184e55508d2c33e2a9564dad477bc76b23ca6
7
- data.tar.gz: 40db817d3b7af688a03ff27bd40d9a6e7df7ef8ea4c843d81affb260b62845f8f7324546b7a02f5691ac7700a39244e751a7bda4c389a7a4b4d7b674ed80a2f5
6
+ metadata.gz: a284c684a87c395f2587f0756f0ea6d312233208597e79de7c2e681e0f609ebd8ff552f017f199a0fe4f198860eef0bf2b7876e8d3a43829f9a2f1838635de73
7
+ data.tar.gz: 34fe8725f760895177dd962954564c9b246005a09ecca02e5be8e3c836edaa71d8bcb9d8aa3af55920579b32cd8c660dfe07214729f3036332a735b4500196f6
@@ -30,7 +30,7 @@ module WebSocket
30
30
  # configuration for the channel pipeline that will handle requests of
31
31
  # the server.
32
32
  class ChannelInitializer < ::Server::ChannelInitializer
33
- HttpObjectAggregatorBufferBytesSize = 65_536
33
+ HTTP_OBJECT_AGGREGATOR_BUFFER_BYTES_SIZE = 65_536
34
34
 
35
35
  def initialize(channel_group, options = {})
36
36
  super(channel_group, options)
@@ -40,15 +40,15 @@ module WebSocket
40
40
  # rubocop: disable Metrics/MethodLength
41
41
  def initChannel(channel)
42
42
  pipeline = channel.pipeline
43
- pipeline.addLast(ssl_handler(channel)) if @options[:ssl]
43
+ pipeline.addLast(ssl_handler(channel)) if ssl?
44
44
  pipeline.addLast(HttpServerCodec.new)
45
- pipeline.addLast(HttpObjectAggregator.new(HttpObjectAggregatorBufferBytesSize))
45
+ pipeline.addLast(HttpObjectAggregator.new(HTTP_OBJECT_AGGREGATOR_BUFFER_BYTES_SIZE))
46
46
  pipeline.addLast(ChunkedWriteHandler.new)
47
- pipeline.addLast(IdleStateHandler.new(@options[:idle_reading], @options[:idle_writing], 0))
47
+ pipeline.addLast(IdleStateHandler.new(idle_reading, idle_writing, 0))
48
48
  pipeline.addLast(WebSocket::IdleHandler.new)
49
49
  pipeline.addLast(WebSocketServerCompressionHandler.new)
50
- pipeline.addLast(WebSocketServerProtocolHandler.new(@options[:web_socket_path], nil, true))
51
- pipeline.addLast(SslCipherInspector.new) if !ssl_context.nil? && @options[:inspect_ssl]
50
+ pipeline.addLast(WebSocketServerProtocolHandler.new(web_socket_path, nil, true))
51
+ pipeline.addLast(SslCipherInspector.new) if !ssl_context.nil? && inspect_ssl?
52
52
  pipeline.addLast(HttpStaticFileServerHandler.new(@options))
53
53
  add_user_handlers(pipeline)
54
54
  pipeline.addLast(default_handler)
@@ -67,6 +67,43 @@ module WebSocket
67
67
  end
68
68
  end
69
69
  end
70
+
71
+ private
72
+
73
+ def web_socket_path
74
+ @web_socket_path ||= begin
75
+ value = @options[:web_socket_path]
76
+ value.nil? || value.empty? ? DEFAULT_WEB_SOCKET_PATH : value
77
+ end
78
+ end
79
+
80
+ def idle_reading
81
+ @idle_reading ||= begin
82
+ value = @options[:idle_reading]
83
+ value.nil? ? DEFAULT_IDLE_READING_SECONDS : value
84
+ end
85
+ end
86
+
87
+ def idle_writing
88
+ @idle_writing ||= begin
89
+ value = @options[:idle_writing]
90
+ value.nil? ? DEFAULT_IDLE_WRITING_SECONDS : value
91
+ end
92
+ end
93
+
94
+ def ssl?
95
+ @ssl ||= begin
96
+ value = @options[:ssl]
97
+ value.nil? ? DEFAULT_SSL_ENABLED : value
98
+ end
99
+ end
100
+
101
+ def inspect_ssl?
102
+ @inspect_ssl = begin
103
+ value = @options[:inspect_ssl]
104
+ value.nil? ? DEFAULT_SSL_INSPECTION_ENABLED : value
105
+ end
106
+ end
70
107
  end
71
108
  # class ServerInitializer
72
109
  end
@@ -14,45 +14,70 @@ require 'logger'
14
14
 
15
15
  # The WebSocket module
16
16
  module WebSocket
17
+ WEBSOCKET_SUBMODULE_DIR_PATH = File.expand_path(__dir__)
18
+ LIB_DIR_PATH = File.expand_path(File.dirname(WEBSOCKET_SUBMODULE_DIR_PATH))
19
+ PROJECT_DIR_PATH = File.expand_path(File.dirname(LIB_DIR_PATH))
20
+ DEFAULT_LOG_LEVEL = Logger::INFO
21
+ DEFAULT_HOSTNAME = '0.0.0.0'.freeze
22
+ DEFAULT_PORT = 4000
23
+ DEFAULT_SSL_PORT = 443
24
+ DEFAULT_TELNET_PROXY_HOST = nil
25
+ DEFAULT_TELNET_PROXY_PORT = 21
26
+ DEFAULT_KEEP_ALIVE = true
27
+ DEFAULT_MAX_QUEUED_INCOMING_CONNECTIONS = 100
28
+ DEFAULT_IDLE_READING_SECONDS = 5 * 60 # seconds
29
+ DEFAULT_IDLE_WRITING_SECONDS = 30 # seconds
30
+ DEFAULT_SSL_ENABLED = false
31
+ DEFAULT_SSL_CERTIFICATE_FILE_PATH = File.join(PROJECT_DIR_PATH, 'fullchain.pem')
32
+ # openssl pkcs8 -topk8 -nocrypt -in websocket.key -out websocket_pcks8
33
+ #
34
+ # The privkey.key file here should be generated using the following
35
+ # openssl command:
36
+ #
37
+ # openssl pkcs8 -topk8 -inform PEM -outform DER -in privkey.pem -nocrypt > privkey.key
38
+ #
39
+ DEFAULT_SSL_PRIVATE_KEY_FILE_PATH = File.join(PROJECT_DIR_PATH, 'privkey.key')
40
+ DEFAULT_SSL_INSPECTION_ENABLED = false
41
+ DEFAULT_WEB_SOCKET_PATH = '/websocket'.freeze
42
+ DEFAULT_WEB_DIR = 'web'.freeze
43
+ DEFAULT_WEB_ROOT = File.join(PROJECT_DIR_PATH, DEFAULT_WEB_DIR)
44
+ DEFAULT_INDEX_PAGE = 'index.html'.freeze
45
+ DEFAULT_PING_MESSAGE = "ping\n".freeze
46
+ # EEE, dd MMM yyyy HH:mm:ss zzz
47
+ DEFAULT_HTTP_DATE_FORMAT = '%a, %d %b %Y %H:%M:%S %Z'.freeze
48
+ DEFAULT_HTTP_DATE_GMT_TIMEZONE = 'GMT'.freeze
49
+ DEFAULT_CACHE_SECONDS = 60 # seconds
50
+ DEFAULT_INSECURE_URI_PATTERN = %r{.*[<>&"].*}
51
+ DEFAULT_LOG_REQUESTS = false
52
+
17
53
  # rubocop: disable Metrics/MethodLength
18
54
  def server_config
19
- @server_config ||= begin
20
- server_submodule_dir_path = File.expand_path(__dir__)
21
- lib_dir_path = File.expand_path(File.dirname(server_submodule_dir_path))
22
- project_dir_path = File.expand_path(File.dirname(lib_dir_path))
23
- {
24
- log_level: Logger::INFO,
25
- host: '0.0.0.0',
26
- port: 4000,
27
- ssl_port: 443,
28
- telnet_proxy_host: nil,
29
- telnet_proxy_port: 21,
30
- ssl: false,
31
- ssl_certificate_file_path: File.join(project_dir_path, 'fullchain.pem'),
32
- # openssl pkcs8 -topk8 -nocrypt -in websocket.key -out websocket_pcks8
33
- #
34
- # The privkey.key file here should be generated using the following
35
- # openssl command:
36
- #
37
- # openssl pkcs8 -topk8 -inform PEM -outform DER -in privkey.pem -nocrypt > privkey.key
38
- #
39
- ssl_private_key_file_path: File.join(project_dir_path, 'privkey.key'),
40
- use_jdk_ssl_provider: false,
41
- inspect_ssl: false,
42
- idle_reading: 5 * 60, # seconds
43
- idle_writing: 30, # seconds
44
- index_page: 'index.html',
45
- web_root: File.join(project_dir_path, 'web'),
46
- web_socket_path: '/websocket',
47
- ping_message: "ping\n",
48
- http_date_format: '%a, %d %b %Y %H:%M:%S %Z', # EEE, dd MMM yyyy HH:mm:ss zzz
49
- http_date_gmt_timezone: 'GMT',
50
- http_cache_seconds: 60,
51
- insecure_uri_pattern: /.*[<>&"].*/,
52
- allowed_file_name: /[A-Za-z0-9][-_A-Za-z0-9\\.]*/,
53
- log_requests: false
54
- }
55
- end
55
+ @server_config ||= {
56
+ log_level: DEFAULT_LOG_LEVEL,
57
+ host: DEFAULT_HOSTNAME,
58
+ port: DEFAULT_PORT,
59
+ ssl_port: DEFAULT_SSL_PORT,
60
+ telnet_proxy_host: DEFAULT_TELNET_PROXY_HOST,
61
+ telnet_proxy_port: DEFAULT_TELNET_PROXY_PORT,
62
+ ssl: DEFAULT_SSL_ENABLED,
63
+ ssl_certificate_file_path: DEFAULT_SSL_CERTIFICATE_FILE_PATH,
64
+ ssl_private_key_file_path: DEFAULT_SSL_PRIVATE_KEY_FILE_PATH,
65
+ use_jdk_ssl_provider: false,
66
+ inspect_ssl: DEFAULT_SSL_INSPECTION_ENABLED,
67
+ idle_reading: DEFAULT_IDLE_READING_SECONDS,
68
+ idle_writing: DEFAULT_IDLE_WRITING_SECONDS,
69
+ keep_alive: DEFAULT_KEEP_ALIVE,
70
+ max_queued_incoming_connections: DEFAULT_MAX_QUEUED_INCOMING_CONNECTIONS,
71
+ index_page: DEFAULT_INDEX_PAGE,
72
+ web_root: DEFAULT_WEB_ROOT,
73
+ web_socket_path: DEFAULT_WEB_SOCKET_PATH,
74
+ ping_message: DEFAULT_PING_MESSAGE,
75
+ http_date_format: DEFAULT_HTTP_DATE_FORMAT,
76
+ http_date_gmt_timezone: DEFAULT_HTTP_DATE_GMT_TIMEZONE,
77
+ http_cache_seconds: DEFAULT_CACHE_SECONDS,
78
+ insecure_uri_pattern: DEFAULT_INSECURE_URI_PATTERN,
79
+ log_requests: DEFAULT_LOG_REQUESTS
80
+ }
56
81
  end
57
82
  module_function :server_config
58
83
  # rubocop: enable Metrics/MethodLength
@@ -28,7 +28,7 @@ module WebSocket
28
28
  class FrameHandler < SimpleChannelInboundHandler
29
29
  include ChannelHandler
30
30
  include ChannelFutureListener
31
- UnsupportedFrameTypeErrorTemplate =
31
+ UNSUPPORTED_FRAME_TYPE_ERROR_TEMPLATE =
32
32
  '%<handler>s encountered unsupported frame type: %<frame>s'.freeze
33
33
 
34
34
  def initialize
@@ -50,7 +50,9 @@ module WebSocket
50
50
 
51
51
  def unsupported_frame(frame, handler)
52
52
  raise java.lang.UnsupportedOperationException, format(
53
- UnsupportedFrameTypeErrorTemplate, handler: handler.class, frame: frame.class
53
+ UNSUPPORTED_FRAME_TYPE_ERROR_TEMPLATE,
54
+ handler: handler.class,
55
+ frame: frame.class
54
56
  )
55
57
  end
56
58
 
@@ -21,6 +21,8 @@ module WebSocket
21
21
 
22
22
  # The HeaderHelpers module
23
23
  module HeaderHelpers
24
+ PRIVATE_MAX_AGE_TEMPLATE = 'private, max-age=%<max_age>s'.freeze
25
+
24
26
  def keep_alive_header(response)
25
27
  response.headers().set(HttpHeaderNames::CONNECTION, HttpHeaderValues::KEEP_ALIVE)
26
28
  end
@@ -41,15 +43,13 @@ module WebSocket
41
43
  response.headers().set(HttpHeaderNames::LAST_MODIFIED, last_modified)
42
44
  end
43
45
 
44
- PrivateMaxAgeTempalte = 'private, max-age=%<max_age>s'.freeze
45
-
46
46
  # rubocop: disable Metrics/AbcSize
47
47
  def date_and_cache_headers(response, path, timestamp = Time.now)
48
48
  maximum_age = options[:http_cache_seconds]
49
49
  date_format = options[:http_date_format]
50
50
  date_header(response, timestamp.strftime(date_format))
51
51
  expires_header(response, Time.at(timestamp.to_i + maximum_age).strftime(date_format))
52
- cache_control_header(response, format(PrivateMaxAgeTempalte, max_age: maximum_age.to_s))
52
+ cache_control_header(response, format(PRIVATE_MAX_AGE_TEMPLATE, max_age: maximum_age.to_s))
53
53
  last_modified_header(response, File.mtime(path).strftime(date_format))
54
54
  end
55
55
  # rubocop: enable Metrics/AbcSize
@@ -36,6 +36,7 @@ module WebSocket
36
36
 
37
37
  # The HttpStaticFileServerHandlerInstanceMethods module
38
38
  module HttpStaticFileServerHandlerInstanceMethods
39
+ WEB_SOCKET_PATH_PATTERN_TEMPLATE = '^%<path>s$'.freeze
39
40
  FORWARD_SLASH_BEFORE_EOL_PATTERN = %r{/$}
40
41
  URI_FORWARD_SLASH_TEMPLATE = '%<uri>s/'.freeze
41
42
 
@@ -44,7 +45,7 @@ module WebSocket
44
45
  # rubocop: disable Metrics/MethodLength
45
46
  # rubocop: disable Metrics/PerceivedComplexity
46
47
  def messageReceived(ctx, request)
47
- return if %r{^#{options[:web_socket_path]}$}.match?(request.uri)
48
+ return if web_socket_path_pattern.match?(request.uri)
48
49
 
49
50
  unless request.decoderResult().isSuccess()
50
51
  send_error(ctx, HttpResponseStatus::BAD_REQUEST)
@@ -153,6 +154,22 @@ module WebSocket
153
154
  return unless ctx.channel().isActive()
154
155
  send_error(ctx, HttpResponseStatus::INTERNAL_SERVER_ERROR)
155
156
  end
157
+
158
+ private
159
+
160
+ def web_socket_path_pattern
161
+ @web_socket_path_pattern ||= begin
162
+ pattern = format(WEB_SOCKET_PATH_PATTERN_TEMPLATE, path: web_socket_path)
163
+ Regexp.new(pattern)
164
+ end
165
+ end
166
+
167
+ def web_socket_path
168
+ @web_socket_path ||= begin
169
+ value = options[:web_socket_path]
170
+ value.nil? || value.empty? ? DEFAULT_WEB_SOCKET_PATH : value
171
+ end
172
+ end
156
173
  end
157
174
  # module HttpStaticFileServerHandlerInstanceMethods
158
175
  end
@@ -19,47 +19,14 @@ require_relative 'shutdown_hook'
19
19
  # The WebSocket module
20
20
  module WebSocket
21
21
  java_import Java::io.netty.bootstrap.ServerBootstrap
22
- java_import Java::io.netty.channel.group.DefaultChannelGroup
23
- java_import Java::io.netty.channel.nio.NioEventLoopGroup
24
- java_import Java::io.netty.handler.logging.LoggingHandler
25
- java_import Java::io.netty.handler.logging.LogLevel
26
- java_import Java::io.netty.util.concurrent.GlobalEventExecutor
22
+ java_import Java::io.netty.channel.ChannelOption
27
23
 
28
24
  # The InstanceMethods module
29
25
  module InstanceMethods
30
- def configure_handlers(&block)
31
- add_listener(self)
32
- channel_initializer << block if block_given?
33
- end
34
-
35
- def bootstrap
36
- @bootstrap = ServerBootstrap.new
37
- @bootstrap.group(boss_group, worker_group)
38
- @bootstrap.channel(Server::CHANNEL_TYPE)
39
- @bootstrap.handler(logging_handler) if @options[:log_requests]
40
- @bootstrap.childHandler(channel_initializer)
41
- end
42
-
43
26
  def channel_initializer
44
27
  @channel_initializer ||= ::WebSocket::ChannelInitializer.new(channel_group, @options)
45
28
  end
46
29
 
47
- def boss_group
48
- @boss_group ||= NioEventLoopGroup.new(2)
49
- end
50
-
51
- def worker_group
52
- @worker_group ||= NioEventLoopGroup.new
53
- end
54
-
55
- def channel_group
56
- @channel_group ||= DefaultChannelGroup.new('server_channels', GlobalEventExecutor::INSTANCE)
57
- end
58
-
59
- def logging_handler
60
- LoggingHandler.new(LogLevel::INFO)
61
- end
62
-
63
30
  # rubocop: disable Metrics/AbcSize
64
31
  # rubocop: disable Metrics/MethodLength
65
32
  def run(params = {})
@@ -83,32 +50,12 @@ module WebSocket
83
50
  @port ||= (@options[:ssl] ? @options[:ssl_port] : @options[:port]).to_i
84
51
  end
85
52
 
86
- def shutdown
87
- channel_group.disconnect().awaitUninterruptibly()
88
- channel_group.close().awaitUninterruptibly()
89
- end
90
-
91
- def stop
92
- boss_group&.shutdownGracefully()
93
- worker_group&.shutdownGracefully()
94
- end
95
-
96
- def <<(handler)
97
- channel_initializer.handlers << handler
98
- end
99
-
100
- def add_listener(*listener)
101
- channel_initializer.add_listener(*listener)
53
+ def log_requests?
54
+ @log_requests ||= begin
55
+ value = @options[:log_requests]
56
+ value.nil? ? DEFAULT_LOG_REQUESTS : value
57
+ end
102
58
  end
103
-
104
- # def all_exist?(*files)
105
- # files.all? { |f| File.exist?(f) }
106
- # end
107
-
108
- # def init_ssl_context(certificate, private_key)
109
- # return certificate_key_pair(certificate, private_key) if all_exist?(certificate, private_key)
110
- # options[:use_jdk_ssl_provider] ? jdk_ssl_provider : self_signed_certificate
111
- # end
112
59
  end
113
60
  # module ServerInstanceMethods
114
61
  end
@@ -36,6 +36,15 @@ module WebSocket
36
36
  channel_initializer.ssl_context = context unless context.nil?
37
37
  end
38
38
 
39
+ def all_exist?(*files)
40
+ files.all? { |f| File.exist?(f) }
41
+ end
42
+
43
+ def init_ssl_context(certificate, private_key)
44
+ return certificate_key_pair(certificate, private_key) if all_exist?(certificate, private_key)
45
+ options[:use_jdk_ssl_provider] ? jdk_ssl_provider : self_signed_certificate
46
+ end
47
+
39
48
  def ssl_context
40
49
  @ssl_context ||= init_ssl_context(options[:ssl_certificate_file_path], options[:ssl_private_key_file_path])
41
50
  end
@@ -28,7 +28,7 @@ module WebSocket
28
28
  DOT_FILE_SEPARATOR_PATTERN.match?(uri) ||
29
29
  uri.start_with?('.') ||
30
30
  uri.end_with?('.') ||
31
- options[:insecure_uri_pattern].match?(uri)
31
+ insecure_uri_pattern.match?(uri)
32
32
  end
33
33
 
34
34
  def sanitize_uri(uri)
@@ -39,7 +39,23 @@ module WebSocket
39
39
  uri = uri.gsub(FORWARD_SLASH_PATTERN, File::SEPARATOR)
40
40
  return nil if insecure_uri?(uri)
41
41
  # Convert to absolute path.
42
- File.join(options[:web_root], uri)
42
+ File.join(web_root, uri)
43
+ end
44
+
45
+ private
46
+
47
+ def web_root
48
+ @web_root ||= begin
49
+ value = options[:web_root]
50
+ value || DEFAULT_WEB_ROOT
51
+ end
52
+ end
53
+
54
+ def insecure_uri_pattern
55
+ @insecure_uri_pattern ||= begin
56
+ value = options[:insecure_uri_pattern]
57
+ value || DEFAULT_INSECURE_URI_PATTERN
58
+ end
43
59
  end
44
60
  end
45
61
  # module ValidationHelpers
@@ -12,5 +12,5 @@
12
12
 
13
13
  # The WebSocket module
14
14
  module WebSocket
15
- VERSION = '1.1.4'.freeze
15
+ VERSION = '1.2.0'.freeze
16
16
  end
@@ -262,8 +262,6 @@ module WebSocket
262
262
 
263
263
  def add_listener(*listener)
264
264
  listeners.addAll(listener)
265
- ensure
266
- log.trace "Listeners: #{listeners}"
267
265
  end
268
266
 
269
267
  def remove_listener(*listener)
@@ -33,7 +33,6 @@ module WebSocket
33
33
  end
34
34
 
35
35
  # rubocop: disable Metrics/AbcSize
36
- # rubocop: disable Metrics/MethodLength
37
36
  def main(args = parse_arguments)
38
37
  Logging.log_level = args[:log_level]
39
38
  return telnet_proxy(args) unless args[:telnet_proxy_host].nil?
@@ -42,13 +41,11 @@ module WebSocket
42
41
  warn format("\r%<class>s", class: e.class)
43
42
  exit
44
43
  rescue StandardError => e
45
- puts Logging.log_level
46
44
  ::WebSocket::Server.log.fatal(e.message)
47
45
  e.backtrace.each { |t| WebSocket::Server.log.debug t }
48
46
  abort
49
47
  end
50
48
  # rubocop: enable Metrics/AbcSize
51
- # rubocop: enable Metrics/MethodLength
52
49
  end
53
50
  # module WebSocket
54
51
 
@@ -0,0 +1,71 @@
1
+
2
+ span.underline {
3
+ text-decoration: underline;
4
+ }
5
+ span.blink {
6
+ text-decoration: blink;
7
+ }
8
+ span.flash {
9
+ text-decoration: flash;
10
+ }
11
+ span.inverse {
12
+ text-decoration: inverse;
13
+ }
14
+ span.hidden {
15
+ display: none;
16
+ }
17
+ span.line-through {
18
+ text-decoration: line-through;
19
+ }
20
+ span.monospace {
21
+ font-family: 'Droid Sans Mono', sans-serif;
22
+ }
23
+
24
+ span.black-foreground {
25
+ color: black;
26
+ }
27
+ span.red-foreground {
28
+ color: red;
29
+ }
30
+ span.green-foreground {
31
+ color: green;
32
+ }
33
+ span.yellow-foreground {
34
+ color: yellow;
35
+ }
36
+ span.dodgerblue-foreground {
37
+ color: dodgerblue;
38
+ }
39
+ span.magenta-foreground {
40
+ color: magenta;
41
+ }
42
+ span.cyan-foreground {
43
+ color: cyan;
44
+ }
45
+ span.white-foreground {
46
+ color: white;
47
+ }
48
+ span.black-background {
49
+ background-color: black;
50
+ }
51
+ span.red-background {
52
+ background-color: red;
53
+ }
54
+ span.green-background {
55
+ background-color: green;
56
+ }
57
+ span.yellow-background {
58
+ background-color: yellow;
59
+ }
60
+ span.dodgerblue-background {
61
+ background-color: dodgerblue;
62
+ }
63
+ span.magenta-background {
64
+ background-color: magenta;
65
+ }
66
+ span.cyan-background {
67
+ background-color: cyan;
68
+ }
69
+ span.white-background {
70
+ background-color: white;
71
+ }
metadata CHANGED
@@ -1,21 +1,21 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: websocket-server
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.1.4
4
+ version: 1.2.0
5
5
  platform: java
6
6
  authors:
7
7
  - Nels Nelson
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2024-04-12 00:00:00.000000000 Z
11
+ date: 2024-04-16 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  requirement: !ruby/object:Gem::Requirement
15
15
  requirements:
16
16
  - - "~>"
17
17
  - !ruby/object:Gem::Version
18
- version: 1.1.3
18
+ version: 1.2.1
19
19
  name: tcp-server
20
20
  type: :runtime
21
21
  prerelease: false
@@ -23,7 +23,7 @@ dependencies:
23
23
  requirements:
24
24
  - - "~>"
25
25
  - !ruby/object:Gem::Version
26
- version: 1.1.3
26
+ version: 1.2.1
27
27
  force_ruby_platform: false
28
28
  description: Websocket Server for JRuby is a websocket server with a file server to
29
29
  support a demo javascript client application which interfaces with a demo echo server
@@ -66,6 +66,7 @@ files:
66
66
  - lib/websocket_client.rb
67
67
  - lib/websocket_server.rb
68
68
  - web/client.html
69
+ - web/css/client/ansispan.css
69
70
  - web/css/client/console.css
70
71
  - web/css/client/parchment.css
71
72
  - web/favicon.ico