gemini_server 0.1.0 → 0.2.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/README.md +17 -0
- data/lib/gemini_server/version.rb +1 -1
- data/lib/gemini_server.rb +33 -4
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: e067f64e27db63e071c57585ae24b7ae0cca9b4c408d0c18acf4b99b6e7ddc57
|
4
|
+
data.tar.gz: 30ab2fec9b37e2316dc9b96a9ff18cfe88a892a9d97c5fbbc40ede5336aaba30
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 34222c9438fda88020863ebf5c05dc454a43b02334fec1fe63af28594c418dc01d1024829ddbf275597af6fe72f196dd854e7b35932934e8805c411bfb5ed354
|
7
|
+
data.tar.gz: cd906abfa205f29f7470c7844043c266655c35d63da00aa95bcc27e9a2c418aced3f537ea2b44707d0353ff41dded57edb5c0e0c249f6f9bdba0583ffc5b00db
|
data/README.md
CHANGED
@@ -4,6 +4,23 @@ A simple server for the Gemini protocol, with an API inspired by Sinatra.
|
|
4
4
|
|
5
5
|
## Usage
|
6
6
|
|
7
|
+
Use the built-in executable to serve the current directory.
|
8
|
+
|
9
|
+
```
|
10
|
+
$ gem install gemini_server
|
11
|
+
Successfully installed gemini_server-0.1.0
|
12
|
+
1 gem installed
|
13
|
+
$ gemini_server -h
|
14
|
+
Usage: gemini_server [options]
|
15
|
+
-p, --port PORT Port to listen on
|
16
|
+
--cert-path PATH Path to cert file
|
17
|
+
--key-path PATH Path to key file
|
18
|
+
--charset CHARSET Charset of text/* files
|
19
|
+
--lang LANG Language of text/* files
|
20
|
+
```
|
21
|
+
|
22
|
+
Or require the library to declare custom routes in Ruby.
|
23
|
+
|
7
24
|
```ruby
|
8
25
|
require "gemini_server"
|
9
26
|
|
data/lib/gemini_server.rb
CHANGED
@@ -17,7 +17,7 @@ class GeminiServer
|
|
17
17
|
@views_folder = File.expand_path(options[:views_folder] || ".")
|
18
18
|
@charset = options[:charset]
|
19
19
|
@lang = options[:lang]
|
20
|
-
@ssl_cert, @ssl_key = self.load_cert_and_key(options)
|
20
|
+
@ssl_cert, @ssl_key, @ssl_chain = self.load_cert_and_key(options)
|
21
21
|
end
|
22
22
|
|
23
23
|
def route r, &blk
|
@@ -28,7 +28,7 @@ class GeminiServer
|
|
28
28
|
def listen host, port
|
29
29
|
Async do
|
30
30
|
endpoint = Async::IO::Endpoint.tcp(host, port)
|
31
|
-
endpoint = Async::IO::SSLEndpoint.new(endpoint, ssl_context: self.ssl_context(@ssl_cert, @ssl_key))
|
31
|
+
endpoint = Async::IO::SSLEndpoint.new(endpoint, ssl_context: self.ssl_context(@ssl_cert, @ssl_key, @ssl_chain))
|
32
32
|
|
33
33
|
["INT", "TERM"].each do |signal|
|
34
34
|
old_handler = Signal.trap(signal) do
|
@@ -151,6 +151,26 @@ class GeminiServer
|
|
151
151
|
LOG_FORMAT % [ip, username || '-', Time.now.strftime("%d/%b/%Y:%H:%M:%S %z"), path, status.to_s, body_size.to_s || '-', clock_time - start_time]
|
152
152
|
end
|
153
153
|
|
154
|
+
def parse_cert_and_chain input_text
|
155
|
+
# Only works in Ruby 3+
|
156
|
+
if OpenSSL::X509::Certificate.respond_to?(:load)
|
157
|
+
certs = OpenSSL::X509::Certificate.load(input_text)
|
158
|
+
return [certs.shift, certs]
|
159
|
+
end
|
160
|
+
|
161
|
+
# Fallback behavior for .pem certificates
|
162
|
+
certificate_pattern = /-----BEGIN CERTIFICATE-----.*?-----END CERTIFICATE-----/m
|
163
|
+
certs = input_text.scan(certificate_pattern).collect do |text|
|
164
|
+
OpenSSL::X509::Certificate.new(text)
|
165
|
+
end
|
166
|
+
|
167
|
+
# Fallback behavior if above regex yields 0 certs. E.g. with .der certs
|
168
|
+
# This won't parse any chain certs that might be present
|
169
|
+
certs = [OpenSSL::X509::Certificate.new(input_text)] if certs.empty?
|
170
|
+
|
171
|
+
[certs.shift, certs]
|
172
|
+
end
|
173
|
+
|
154
174
|
def load_cert_and_key options
|
155
175
|
found_cert = options[:cert] || if options[:cert_path]
|
156
176
|
File.open(options[:cert_path]) rescue nil
|
@@ -167,15 +187,24 @@ class GeminiServer
|
|
167
187
|
raise "SSL certificate not found" unless found_cert
|
168
188
|
raise "SSL key not found" unless found_key
|
169
189
|
|
190
|
+
if found_cert.is_a?(OpenSSL::X509::Certificate)
|
191
|
+
main_cert = found_cert
|
192
|
+
chain_list = []
|
193
|
+
else
|
194
|
+
main_cert, chain_list = parse_cert_and_chain found_cert.read
|
195
|
+
end
|
196
|
+
|
170
197
|
[
|
171
|
-
|
198
|
+
main_cert,
|
172
199
|
found_key.is_a?(OpenSSL::PKey::PKey) ? found_key : OpenSSL::PKey.read(found_key),
|
200
|
+
chain_list
|
173
201
|
]
|
174
202
|
end
|
175
203
|
|
176
|
-
def ssl_context cert, key
|
204
|
+
def ssl_context cert, key, chain
|
177
205
|
OpenSSL::SSL::SSLContext.new.tap do |context|
|
178
206
|
context.add_certificate(cert, key)
|
207
|
+
context.extra_chain_cert = chain
|
179
208
|
context.session_id_context = "gemini_server"
|
180
209
|
context.min_version = OpenSSL::SSL::TLS1_2_VERSION
|
181
210
|
context.max_version = OpenSSL::SSL::TLS1_3_VERSION
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: gemini_server
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.2.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Jess Bees
|
@@ -119,7 +119,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
119
119
|
- !ruby/object:Gem::Version
|
120
120
|
version: '0'
|
121
121
|
requirements: []
|
122
|
-
rubygems_version: 3.
|
122
|
+
rubygems_version: 3.2.32
|
123
123
|
signing_key:
|
124
124
|
specification_version: 4
|
125
125
|
summary: Simple server for the Gemini protocol
|