websocket-server 1.0.1-java → 1.1.2-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 +4 -4
- data/{LICENSE → LICENSE.txt} +1 -1
- data/README.md +30 -31
- data/exe/websocket +1 -1
- data/lib/{log.rb → logging.rb} +90 -81
- data/lib/server/mime_types.rb +1 -1
- data/lib/websocket/arguments_parser.rb +28 -12
- data/lib/websocket/channel_initializer.rb +1 -1
- data/lib/websocket/config.rb +1 -1
- data/lib/websocket/encoding.rb +1 -1
- data/lib/websocket/file_server_channel_progressive_future_listener.rb +1 -1
- data/lib/websocket/frame_handler.rb +1 -1
- data/lib/websocket/header_helpers.rb +1 -1
- data/lib/websocket/http_static_file_server_handler.rb +1 -1
- data/lib/websocket/http_static_file_server_handler_instance_methods.rb +5 -6
- data/lib/websocket/idle_handler.rb +2 -1
- data/lib/websocket/idle_state_user_event_handler.rb +1 -1
- data/lib/websocket/instance_methods.rb +7 -19
- data/lib/websocket/listenable.rb +2 -24
- data/lib/websocket/message_handler.rb +1 -1
- data/lib/websocket/response_helpers.rb +3 -3
- data/lib/websocket/server.rb +1 -3
- data/lib/websocket/shutdown_hook.rb +1 -2
- data/lib/websocket/ssl_cipher_inspector.rb +2 -1
- data/lib/websocket/ssl_context_initialization.rb +1 -1
- data/lib/websocket/telnet_proxy.rb +1 -1
- data/lib/websocket/validation_helpers.rb +9 -13
- data/lib/websocket/version.rb +2 -2
- data/lib/websocket-server.rb +1 -1
- data/lib/websocket_client.rb +83 -39
- data/lib/websocket_server.rb +16 -11
- metadata +8 -49
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 1a82a08a0eb5e690dcea50d8df9c9173fc9ee89dcb533e856b70c4a6622a5c11
|
4
|
+
data.tar.gz: 561c75644b76a40ed767a5c4e03d7d35dfb606c1819d39f08449b0c4283620ff
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: '083153e26d8f09e3cf8c9667bb02970d5861bba51d6390b9d02b8a5a5950c8c5e47afb172822b44e2e2e14810f90112314b87d3a5fbef201bbec1c8f2d4b46d1'
|
7
|
+
data.tar.gz: 446b92140447fdf3a45abae203308a1ac716f9ca6e6e15bd79053059c44a60fb2345a5421e7c391e855ba4739682258b5e01207ce52775e2eb6561a40a23db09
|
data/{LICENSE → LICENSE.txt}
RENAMED
data/README.md
CHANGED
@@ -14,12 +14,13 @@ Follow these instructions to get a websocket server echo program running in your
|
|
14
14
|
|
15
15
|
### Container
|
16
16
|
|
17
|
-
You may run the websocket server in a container.
|
17
|
+
You may run the websocket server in a container. Using [colima] for a container runtime is recommended.
|
18
18
|
|
19
19
|
```sh
|
20
20
|
colima start
|
21
|
-
docker-compose up
|
21
|
+
docker-compose up --detach
|
22
22
|
open http://localhost:4000/client.html
|
23
|
+
docker-compose down
|
23
24
|
```
|
24
25
|
|
25
26
|
|
@@ -35,34 +36,33 @@ docker run --detach --publish 4000:4000 --name websocket-server-jruby websocket-
|
|
35
36
|
|
36
37
|
Run directly with the required dependencies installed.
|
37
38
|
|
38
|
-
### Install asdf
|
39
39
|
|
40
|
-
|
40
|
+
## Install mise-en-place
|
41
|
+
|
42
|
+
The [mise] CLI tool used to manage multiple runtime versions.
|
43
|
+
|
44
|
+
See: https://mise.jdx.dev/getting-started.html
|
41
45
|
|
42
46
|
```sh
|
43
|
-
|
44
|
-
|
45
|
-
|
47
|
+
curl https://mise.jdx.dev/install.sh | sh
|
48
|
+
~/.local/bin/mise --version
|
49
|
+
mise 2024.x.x
|
46
50
|
```
|
47
51
|
|
48
|
-
|
49
|
-
|
50
|
-
Download and install the latest version of the [Java JDK].
|
52
|
+
Enable mise activation in future zsh sessions.
|
51
53
|
|
52
54
|
```sh
|
53
|
-
|
54
|
-
asdf install java openjdk-17.0.2
|
55
|
+
echo 'eval "$(~/.local/bin/mise activate zsh)"' >> ~/.zshrc
|
55
56
|
```
|
56
57
|
|
57
58
|
|
58
|
-
|
59
|
+
## Install required runtime software
|
60
|
+
|
61
|
+
Use mise to install the runtime software defined as requirements
|
62
|
+
in the .tool-versions file.
|
59
63
|
|
60
64
|
```sh
|
61
|
-
|
62
|
-
pushd "${HOME}/.asdf/plugins/ruby/ruby-build"; git fetch origin; git pull origin master; popd
|
63
|
-
# ~/.asdf/plugins/ruby/bin/list-all
|
64
|
-
asdf list all ruby
|
65
|
-
asdf install
|
65
|
+
mise install
|
66
66
|
```
|
67
67
|
|
68
68
|
|
@@ -106,12 +106,11 @@ bundle exec rake publish
|
|
106
106
|
Here is a bird's-eye view of the project layout.
|
107
107
|
|
108
108
|
```sh
|
109
|
-
# date && tree
|
110
|
-
|
109
|
+
# date && tree -A -I "logs|vendor|tmp|Gemfile.lock"
|
110
|
+
Sun Jul 31 15:17:32 CDT 2022
|
111
111
|
.
|
112
112
|
├── Dockerfile
|
113
113
|
├── Gemfile
|
114
|
-
├── Gemfile.lock
|
115
114
|
├── LICENSE
|
116
115
|
├── README.md
|
117
116
|
├── Rakefile
|
@@ -119,10 +118,9 @@ Wed Apr 6 23:05:28 CDT 2022
|
|
119
118
|
├── exe
|
120
119
|
│ └── websocket
|
121
120
|
├── lib
|
122
|
-
│ ├──
|
121
|
+
│ ├── logging.rb
|
123
122
|
│ ├── server
|
124
|
-
│ │
|
125
|
-
│ │ └── server.rb
|
123
|
+
│ │ └── mime_types.rb
|
126
124
|
│ ├── websocket
|
127
125
|
│ │ ├── arguments_parser.rb
|
128
126
|
│ │ ├── channel_initializer.rb
|
@@ -135,22 +133,20 @@ Wed Apr 6 23:05:28 CDT 2022
|
|
135
133
|
│ │ ├── http_static_file_server_handler_instance_methods.rb
|
136
134
|
│ │ ├── idle_handler.rb
|
137
135
|
│ │ ├── idle_state_user_event_handler.rb
|
136
|
+
│ │ ├── instance_methods.rb
|
138
137
|
│ │ ├── listenable.rb
|
139
138
|
│ │ ├── message_handler.rb
|
140
|
-
│ │ ├── modular_handler.rb
|
141
139
|
│ │ ├── response_helpers.rb
|
142
140
|
│ │ ├── server.rb
|
143
|
-
│ │ ├── server_instance_methods.rb
|
144
141
|
│ │ ├── shutdown_hook.rb
|
145
142
|
│ │ ├── ssl_cipher_inspector.rb
|
146
143
|
│ │ ├── ssl_context_initialization.rb
|
147
144
|
│ │ ├── telnet_proxy.rb
|
148
145
|
│ │ ├── validation_helpers.rb
|
149
146
|
│ │ └── version.rb
|
147
|
+
│ ├── websocket-server.rb
|
150
148
|
│ ├── websocket_client.rb
|
151
149
|
│ └── websocket_server.rb
|
152
|
-
├── logs
|
153
|
-
│ └── server.log
|
154
150
|
├── spec
|
155
151
|
│ ├── spec_helper.rb
|
156
152
|
│ ├── test_spec.rb
|
@@ -172,14 +168,17 @@ Wed Apr 6 23:05:28 CDT 2022
|
|
172
168
|
│ │ ├── console.js
|
173
169
|
│ │ └── websocket.js
|
174
170
|
│ └── jquery.min.js
|
171
|
+
├── websocket-server-1.0.1-java.gem
|
175
172
|
├── websocket-server-jruby.gemspec
|
176
|
-
|
173
|
+
├── websocket.rb
|
174
|
+
└── websocket_server.png
|
177
175
|
|
178
|
-
|
176
|
+
12 directories, 51 files
|
179
177
|
```
|
180
178
|
|
181
179
|
[license]: https://gitlab.com/nelsnelson/websocket-server-jruby/blob/master/LICENSE
|
182
|
-
[
|
180
|
+
[mise]: https://mise.jdx.dev/
|
181
|
+
[colima]: https://github.com/abiosoft/colima
|
183
182
|
[Netty project]: https://github.com/netty/netty
|
184
183
|
[Java JDK]: https://www.java.com/en/download/
|
185
184
|
[JRuby]: https://jruby.org/download
|
data/exe/websocket
CHANGED
data/lib/{log.rb → logging.rb}
RENAMED
@@ -1,6 +1,9 @@
|
|
1
1
|
# encoding: utf-8
|
2
2
|
# frozen_string_literal: false
|
3
3
|
|
4
|
+
# -*- mode: ruby -*-
|
5
|
+
# vi: set ft=ruby :
|
6
|
+
|
4
7
|
# =begin
|
5
8
|
|
6
9
|
# Copyright Nels Nelson 2016-2019 but freely usable (see license)
|
@@ -8,11 +11,10 @@
|
|
8
11
|
# =end
|
9
12
|
|
10
13
|
require 'java'
|
14
|
+
require 'fileutils'
|
11
15
|
require 'logger'
|
12
16
|
|
13
|
-
require 'log4j-2'
|
14
|
-
|
15
|
-
require 'fileutils'
|
17
|
+
require 'apache-log4j-2'
|
16
18
|
|
17
19
|
# The Logging module
|
18
20
|
module Logging
|
@@ -22,16 +24,22 @@ module Logging
|
|
22
24
|
lib_dir_path = File.expand_path(__dir__)
|
23
25
|
project_dir_path = File.expand_path(File.dirname(lib_dir_path))
|
24
26
|
logs_dir_path = File.expand_path(File.join(project_dir_path, 'logs'))
|
25
|
-
|
27
|
+
FileUtils.mkdir_p(logs_dir_path)
|
28
|
+
log_file_path = File.expand_path(File.join(logs_dir_path, 'server.log'))
|
29
|
+
FileUtils.touch(log_file_path)
|
26
30
|
{
|
27
|
-
level:
|
31
|
+
level: Logger::INFO,
|
28
32
|
name: 'websocket',
|
29
33
|
lib_dir_path: lib_dir_path,
|
30
34
|
project_dir_path: project_dir_path,
|
31
35
|
logs_dir_path: logs_dir_path,
|
32
|
-
|
33
|
-
rolling_log_file_name_template:
|
34
|
-
|
36
|
+
log_file_path: log_file_path,
|
37
|
+
rolling_log_file_name_template: File.expand_path(
|
38
|
+
File.join(logs_dir_path, 'server-%d{yyyy-MM-dd}.log.gz')),
|
39
|
+
logging_pattern_template: {
|
40
|
+
java: '%d{ABSOLUTE} %-5p [%c{1}] %m%n',
|
41
|
+
ruby: "%<timestamp>s %-5<severity>s [%<progname>s] %<msg>s\n"
|
42
|
+
},
|
35
43
|
schedule: '0 0 0 * * ?',
|
36
44
|
size: '100M'
|
37
45
|
}
|
@@ -41,69 +49,52 @@ module Logging
|
|
41
49
|
# rubocop: enable Metrics/MethodLength
|
42
50
|
end
|
43
51
|
|
44
|
-
# The
|
45
|
-
module
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
module_function :init
|
51
|
-
|
52
|
-
def init_log_file
|
53
|
-
FileUtils.mkdir_p(Logging.config[:logs_dir_path])
|
54
|
-
return if File.file?(Logging.config[:server_log_file])
|
55
|
-
|
56
|
-
File.write(Logging.config[:server_log_file], '')
|
52
|
+
# The Logging module
|
53
|
+
module Logging
|
54
|
+
if defined?(Java)
|
55
|
+
java_import Java::org.apache.logging.log4j.core.appender::ConsoleAppender
|
56
|
+
java_import Java::org.apache.logging.log4j.core.config::Configurator
|
57
|
+
java_import Java::org.apache.logging.log4j.core.config.builder.api::ConfigurationBuilderFactory
|
57
58
|
end
|
58
|
-
module_function :init_log_file
|
59
59
|
|
60
60
|
# rubocop: disable Metrics/AbcSize
|
61
61
|
# rubocop: disable Metrics/MethodLength
|
62
62
|
def init_log4j(log_level = org.apache.logging.log4j.Level::INFO)
|
63
|
-
server_log_file = Logging.config[:server_log_file]
|
64
|
-
logs_dir_path = Logging.config[:logs_dir_path]
|
65
|
-
rolling_log_file_name_template = Logging.config[:rolling_log_file_name_template]
|
66
|
-
rolling_log_file_path = File.join(logs_dir_path, rolling_log_file_name_template)
|
67
|
-
|
68
63
|
java.lang::System.setProperty('log4j.shutdownHookEnabled', java.lang::Boolean.toString(false))
|
69
|
-
|
70
|
-
config = factory.newConfigurationBuilder()
|
64
|
+
config = ConfigurationBuilderFactory.newConfigurationBuilder()
|
71
65
|
|
72
|
-
if log_level.is_a?
|
73
|
-
log_level = org.apache.logging.log4j.Level.to_level(
|
74
|
-
log_level.to_s.upcase
|
75
|
-
)
|
76
|
-
end
|
66
|
+
log_level = org.apache.logging.log4j::Level.to_level(log_level.to_s.upcase) if log_level.is_a? Symbol
|
77
67
|
config.setStatusLevel(log_level)
|
78
|
-
config.setConfigurationName(
|
68
|
+
config.setConfigurationName('websocket')
|
79
69
|
|
80
|
-
#
|
81
|
-
target =
|
70
|
+
# create a console appender
|
71
|
+
target = ConsoleAppender::Target::SYSTEM_OUT
|
72
|
+
pattern = Logging.config[:logging_pattern_template][:java]
|
82
73
|
layout = config.newLayout('PatternLayout')
|
83
|
-
layout = layout.addAttribute('pattern',
|
74
|
+
layout = layout.addAttribute('pattern', pattern)
|
84
75
|
appender = config.newAppender('stdout', 'CONSOLE')
|
85
76
|
appender = appender.addAttribute('target', target)
|
86
77
|
appender = appender.add(layout)
|
87
78
|
config.add(appender)
|
88
79
|
|
89
|
-
#
|
80
|
+
# create a root logger
|
90
81
|
root_logger = config.newRootLogger(log_level)
|
91
82
|
root_logger = root_logger.add(config.newAppenderRef('stdout'))
|
92
83
|
|
93
|
-
#
|
84
|
+
# create a rolling file appender
|
94
85
|
cron = config.newComponent('CronTriggeringPolicy')
|
95
|
-
cron = cron.addAttribute('schedule',
|
86
|
+
cron = cron.addAttribute('schedule', '0 0 0 * * ?')
|
96
87
|
|
97
88
|
size = config.newComponent('SizeBasedTriggeringPolicy')
|
98
|
-
size = size.addAttribute('size',
|
89
|
+
size = size.addAttribute('size', '100M')
|
99
90
|
|
100
91
|
policies = config.newComponent('Policies')
|
101
92
|
policies = policies.addComponent(cron)
|
102
93
|
policies = policies.addComponent(size)
|
103
94
|
|
104
95
|
appender = config.newAppender('rolling_file', 'RollingFile')
|
105
|
-
appender = appender.addAttribute('fileName',
|
106
|
-
appender = appender.addAttribute('filePattern',
|
96
|
+
appender = appender.addAttribute('fileName', Logging.config[:log_file_path])
|
97
|
+
appender = appender.addAttribute('filePattern', Logging.config[:rolling_log_file_name_template])
|
107
98
|
appender = appender.add(layout)
|
108
99
|
appender = appender.addComponent(policies)
|
109
100
|
config.add(appender)
|
@@ -113,28 +104,20 @@ module LogInitialization
|
|
113
104
|
config.add(root_logger)
|
114
105
|
|
115
106
|
logging_configuration = config.build()
|
116
|
-
ctx =
|
107
|
+
ctx = Configurator.initialize(logging_configuration)
|
117
108
|
ctx.updateLoggers()
|
118
109
|
end
|
110
|
+
module_function :init_log4j
|
119
111
|
# rubocop: enable Metrics/AbcSize
|
120
112
|
# rubocop: enable Metrics/MethodLength
|
121
113
|
# def init_log4j
|
122
|
-
module_function :init_log4j
|
123
|
-
end
|
124
|
-
# module LogInitialization
|
125
|
-
|
126
|
-
::LogInitialization.init
|
127
114
|
|
128
|
-
|
129
|
-
|
130
|
-
|
131
|
-
alias log4j_error error
|
132
|
-
def error(error_or_message, error = nil)
|
133
|
-
return extract_backtrace(error_or_message) if error.nil?
|
134
|
-
log4j_error(generate_message(error_or_message, error))
|
135
|
-
extract_backtrace(error)
|
136
|
-
end
|
115
|
+
init_log4j if defined?(Java)
|
116
|
+
end
|
117
|
+
# module Logging
|
137
118
|
|
119
|
+
# Namespace for methods to help with implicit backtrace printing
|
120
|
+
module LoggerHelpers
|
138
121
|
def generate_message(error_or_message, error)
|
139
122
|
error_message = "#{error_or_message}: #{error.class.name}"
|
140
123
|
error_message << ": #{error.message}" if error.respond_to?(:message)
|
@@ -142,40 +125,67 @@ class org.apache.logging.log4j.core::Logger
|
|
142
125
|
end
|
143
126
|
|
144
127
|
def extract_backtrace(error, default_result = nil)
|
145
|
-
log4j_error(error)
|
146
128
|
if error.respond_to?(:backtrace)
|
147
|
-
error.backtrace.each { |trace|
|
129
|
+
error.backtrace.each { |trace| original_error(trace) unless trace.nil? }
|
148
130
|
elsif error.respond_to?(:getStackTrace)
|
149
|
-
error.getStackTrace().each { |trace|
|
131
|
+
error.getStackTrace().each { |trace| original_error(trace) unless trace.nil? }
|
150
132
|
else
|
151
133
|
default_result
|
152
134
|
end
|
153
135
|
end
|
154
136
|
end
|
155
|
-
|
137
|
+
|
138
|
+
# Monkey-patch the built-in Ruby Logger class to support
|
139
|
+
# implicit backtrace printing
|
140
|
+
# TODO: Figure out if this is actually useful.
|
141
|
+
class Logger
|
142
|
+
include LoggerHelpers
|
143
|
+
|
144
|
+
alias original_error error
|
145
|
+
def error(error_or_message, error = nil)
|
146
|
+
return extract_backtrace(error_or_message) if error.nil?
|
147
|
+
original_error(generate_message(error_or_message, error))
|
148
|
+
extract_backtrace(original_error(error))
|
149
|
+
end
|
150
|
+
end
|
156
151
|
|
157
152
|
# The Logging module
|
158
153
|
module Logging
|
159
|
-
|
154
|
+
if defined?(Java)
|
155
|
+
java_import Java::org.apache.logging.log4j.Level
|
156
|
+
java_import Java::org.apache.logging.log4j.LogManager
|
157
|
+
end
|
158
|
+
|
159
|
+
FORWARD_SLASH_PATTERN = %r{/}
|
160
|
+
|
161
|
+
def init_logger(level = :info, logger_name = nil)
|
160
162
|
return init_java_logger(level, logger_name, caller[2]) if defined?(Java)
|
161
|
-
init_ruby_logger(level)
|
163
|
+
init_ruby_logger(level, logger_name, caller[2])
|
162
164
|
end
|
163
165
|
|
164
|
-
def
|
165
|
-
|
166
|
-
|
167
|
-
|
166
|
+
def ruby_log_formatter(severity_level, datetime, program_name, message)
|
167
|
+
format(
|
168
|
+
Logging.config[:logging_pattern_template][:ruby],
|
169
|
+
timestamp: datetime.strftime(Logging.config[:logging_timestamp_format]),
|
170
|
+
progname: program_name, severity: severity_level, msg: message)
|
168
171
|
end
|
169
172
|
|
170
|
-
|
171
|
-
def init_java_logger(level, logger_name = nil, source_location = nil)
|
173
|
+
def init_ruby_logger(level = nil, logger_name = nil, source_location = nil)
|
172
174
|
logger_name = get_formatted_logger_name(logger_name)
|
173
|
-
logger_name = source_location.split(
|
174
|
-
|
175
|
-
|
176
|
-
|
175
|
+
logger_name = source_location.split(FORWARD_SLASH_PATTERN).last if logger_name.empty?
|
176
|
+
log = Logger.new($stdout, progname: logger_name)
|
177
|
+
log.level = level.to_s unless level.nil?
|
178
|
+
log.formatter = method(:ruby_log_formatter)
|
179
|
+
log
|
180
|
+
end
|
181
|
+
|
182
|
+
def init_java_logger(level = nil, logger_name = nil, source_location = nil)
|
183
|
+
logger_name = get_formatted_logger_name(logger_name)
|
184
|
+
logger_name = source_location.split(FORWARD_SLASH_PATTERN).last if logger_name.empty?
|
185
|
+
log = LogManager.getLogger(logger_name)
|
186
|
+
log.level = Level.to_level(level.to_s.upcase) unless level.nil?
|
187
|
+
log
|
177
188
|
end
|
178
|
-
# rubocop: enable Metrics/AbcSize
|
179
189
|
|
180
190
|
def get_formatted_logger_name(logger_name = nil)
|
181
191
|
return logger_name.to_s[/\w+$/] unless logger_name.nil?
|
@@ -202,14 +212,13 @@ module Logging
|
|
202
212
|
when 1 then :info
|
203
213
|
when 0 then :debug
|
204
214
|
when -1 then :trace
|
205
|
-
when -
|
215
|
+
when -Float::INFINITY..-2 then :all
|
206
216
|
end
|
207
217
|
end
|
208
218
|
# rubocop: enable Metrics/CyclomaticComplexity
|
209
|
-
module_function :symbolize_numeric_log_level
|
210
219
|
|
211
|
-
def log_level=(
|
212
|
-
Logging.config[:level] = symbolize_numeric_log_level(
|
220
|
+
def log_level=(level)
|
221
|
+
Logging.config[:level] = symbolize_numeric_log_level(level)
|
213
222
|
end
|
214
223
|
module_function :log_level=
|
215
224
|
|
@@ -218,7 +227,7 @@ module Logging
|
|
218
227
|
end
|
219
228
|
module_function :log_level
|
220
229
|
|
221
|
-
def log(level = Logging.log_level, log_name =
|
230
|
+
def log(level = Logging.log_level, log_name = Logging.config[:app_name])
|
222
231
|
@log ||= init_logger(level, log_name)
|
223
232
|
end
|
224
233
|
alias logger log
|
data/lib/server/mime_types.rb
CHANGED
@@ -6,7 +6,7 @@
|
|
6
6
|
|
7
7
|
# =begin
|
8
8
|
#
|
9
|
-
# Copyright Nels Nelson 2016-
|
9
|
+
# Copyright Nels Nelson 2016-2024 but freely usable (see license)
|
10
10
|
#
|
11
11
|
# =end
|
12
12
|
|
@@ -16,20 +16,21 @@ require_relative 'config'
|
|
16
16
|
|
17
17
|
# The WebSocket module
|
18
18
|
module WebSocket
|
19
|
+
# rubocop: disable Metrics/ClassLength
|
19
20
|
# The ArgumentsParser class
|
20
21
|
class ArgumentsParser
|
21
|
-
Flags = %i[
|
22
|
-
banner port telnet_proxy_host telnet_proxy_port
|
23
|
-
ssl ssl_certificate ssl_private_key use_jdk_ssl_provider
|
24
|
-
inspect_ssl idle_reading idle_writing log_requests web_root
|
25
|
-
verbose help version
|
26
|
-
].freeze
|
27
22
|
attr_reader :parser, :options
|
28
23
|
|
29
24
|
def initialize(option_parser = OptionParser.new)
|
30
25
|
@parser = option_parser
|
31
26
|
@options = ::WebSocket.server_config.dup
|
32
|
-
|
27
|
+
@flags = %i[
|
28
|
+
banner port telnet_proxy_host telnet_proxy_port
|
29
|
+
ssl ssl_certificate ssl_private_key use_jdk_ssl_provider
|
30
|
+
inspect_ssl idle_reading idle_writing log_requests web_root
|
31
|
+
verbose help version
|
32
|
+
]
|
33
|
+
@flags.each { |method_name| method(method_name)&.call if respond_to?(method_name) }
|
33
34
|
end
|
34
35
|
|
35
36
|
def banner
|
@@ -38,9 +39,17 @@ module WebSocket
|
|
38
39
|
@parser.separator 'Options:'
|
39
40
|
end
|
40
41
|
|
42
|
+
def validated_port(val, integer_pattern = /^\d+$/)
|
43
|
+
raise OptionParser::InvalidArgument, "Invalid port: #{v}" unless \
|
44
|
+
integer_pattern.match?(val.to_s) && val.positive? && val < 65_536
|
45
|
+
|
46
|
+
val
|
47
|
+
end
|
48
|
+
|
41
49
|
def port
|
42
|
-
|
43
|
-
|
50
|
+
description = "Port on which to listen for connections; default: #{@options[:port]}"
|
51
|
+
@parser.on('-p', '--port=<port>', Integer, description) do |v|
|
52
|
+
@options[:port] = validated_port(v).to_i
|
44
53
|
end
|
45
54
|
end
|
46
55
|
|
@@ -112,6 +121,7 @@ module WebSocket
|
|
112
121
|
|
113
122
|
def verbose
|
114
123
|
@parser.on_tail('-v', '--verbose', 'Increase verbosity') do
|
124
|
+
@options[:log_level] ||= 0
|
115
125
|
@options[:log_level] -= 1
|
116
126
|
end
|
117
127
|
end
|
@@ -125,17 +135,23 @@ module WebSocket
|
|
125
135
|
|
126
136
|
def version
|
127
137
|
@parser.on_tail('--version', 'Show version') do
|
128
|
-
puts "#{File.basename($PROGRAM_NAME)} version #{WebSocket
|
138
|
+
puts "#{File.basename($PROGRAM_NAME)} version #{::WebSocket::VERSION}"
|
129
139
|
exit
|
130
140
|
end
|
131
141
|
end
|
132
142
|
end
|
143
|
+
# rubocop: enable Metrics/ClassLength
|
133
144
|
# class ArgumentsParser
|
134
145
|
|
135
146
|
def parse_arguments(arguments_parser = WebSocket::ArgumentsParser.new)
|
136
147
|
arguments_parser.parser.parse!(ARGV)
|
137
148
|
arguments_parser.options
|
138
|
-
rescue OptionParser::
|
149
|
+
rescue OptionParser::InvalidArgument, OptionParser::InvalidOption,
|
150
|
+
OptionParser::MissingArgument, OptionParser::NeedlessArgument => e
|
151
|
+
puts e.message
|
152
|
+
puts parser
|
153
|
+
exit
|
154
|
+
rescue OptionParser::AmbiguousOption => e
|
139
155
|
abort e.message
|
140
156
|
end
|
141
157
|
end
|
data/lib/websocket/config.rb
CHANGED
data/lib/websocket/encoding.rb
CHANGED
@@ -6,7 +6,7 @@
|
|
6
6
|
|
7
7
|
# =begin
|
8
8
|
#
|
9
|
-
# Copyright Nels Nelson 2016-
|
9
|
+
# Copyright Nels Nelson 2016-2024 but freely usable (see license)
|
10
10
|
#
|
11
11
|
# =end
|
12
12
|
|
@@ -36,8 +36,8 @@ module WebSocket
|
|
36
36
|
|
37
37
|
# The HttpStaticFileServerHandlerInstanceMethods module
|
38
38
|
module HttpStaticFileServerHandlerInstanceMethods
|
39
|
-
|
40
|
-
|
39
|
+
FORWARD_SLASH_BEFORE_EOL_PATTERN = %r{/$}
|
40
|
+
URI_FORWARD_SLASH_TEMPLATE = '%<uri>s/'.freeze
|
41
41
|
|
42
42
|
# rubocop: disable Metrics/AbcSize
|
43
43
|
# rubocop: disable Metrics/CyclomaticComplexity
|
@@ -69,10 +69,10 @@ module WebSocket
|
|
69
69
|
end
|
70
70
|
|
71
71
|
if File.directory? path
|
72
|
-
if
|
72
|
+
if FORWARD_SLASH_BEFORE_EOL_PATTERN.match?(uri)
|
73
73
|
send_listing(ctx, path)
|
74
74
|
else
|
75
|
-
send_redirect(ctx, format(
|
75
|
+
send_redirect(ctx, format(URI_FORWARD_SLASH_TEMPLATE, uri: uri))
|
76
76
|
end
|
77
77
|
return
|
78
78
|
end
|
@@ -149,7 +149,6 @@ module WebSocket
|
|
149
149
|
# rubocop: enable Metrics/PerceivedComplexity
|
150
150
|
|
151
151
|
def exceptionCaught(ctx, cause)
|
152
|
-
log.info "##{__method__} wtf2"
|
153
152
|
cause.printStackTrace()
|
154
153
|
return unless ctx.channel().isActive()
|
155
154
|
send_error(ctx, HttpResponseStatus::INTERNAL_SERVER_ERROR)
|