async-htty 0.4.0 → 0.5.0
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
- checksums.yaml.gz.sig +0 -0
- data/examples/raw_mode_probe.rb +3 -3
- data/lib/async/htty/environment/server.rb +31 -0
- data/lib/async/htty/server.rb +2 -2
- data/lib/async/htty/service/server.rb +62 -0
- data/lib/async/htty/version.rb +1 -1
- data/readme.md +4 -0
- data/releases.md +4 -0
- data/test/async/htty/server.rb +8 -8
- data.tar.gz.sig +0 -0
- metadata +5 -3
- metadata.gz.sig +0 -0
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: c05feb5444f1fb836e415c02bc4298c1999358b35c5f9775dc7da7f6d52f3c7c
|
|
4
|
+
data.tar.gz: 93215fb6565f7033e45b70e4c3f7831998e0b10e926afac2e098c8fb38cdbfd5
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: e662f9bad50e239ef015d27b45299f959ef16376fe03d2eac4790ed1cf4ccd96e970792123c1346e1cb69d99436a47783e886e4ccafbbdbebf52d8d568d991d0
|
|
7
|
+
data.tar.gz: 167fa6017a168cb7a6cfcd13fb1feaa4e02d41afdfa8dfb6e612d58fc3cee145ee38424d8efad8f3db236f6c8f3a0899f3271e7baaec9f6e2f00b753af796e0a
|
checksums.yaml.gz.sig
CHANGED
|
Binary file
|
data/examples/raw_mode_probe.rb
CHANGED
|
@@ -49,15 +49,15 @@ TEXT
|
|
|
49
49
|
STDIN.raw(min: 0, time: 1) do |input|
|
|
50
50
|
loop do
|
|
51
51
|
chunk = input.read_nonblock(32, exception: false)
|
|
52
|
-
|
|
52
|
+
|
|
53
53
|
case chunk
|
|
54
54
|
when :wait_readable, nil
|
|
55
55
|
# Keep the process alive while waiting for external signals.
|
|
56
56
|
next
|
|
57
57
|
else
|
|
58
58
|
bytes = chunk.bytes
|
|
59
|
-
puts "read #{bytes.length} byte(s): #{bytes.map
|
|
60
|
-
|
|
59
|
+
puts "read #{bytes.length} byte(s): #{bytes.map{|byte| format("0x%02X", byte)}.join(" ")}"
|
|
60
|
+
|
|
61
61
|
break if chunk.include?("q")
|
|
62
62
|
break if bytes.include?(3)
|
|
63
63
|
end
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
# Released under the MIT License.
|
|
4
|
+
# Copyright, 2026, by Samuel Williams.
|
|
5
|
+
|
|
6
|
+
require_relative "../service/server"
|
|
7
|
+
|
|
8
|
+
module Async
|
|
9
|
+
module HTTY
|
|
10
|
+
module Environment
|
|
11
|
+
# An async-service environment module for HTTY transport.
|
|
12
|
+
# Include this (or let Lively::Environment::Application include it)
|
|
13
|
+
# to replace Falcon with an HTTY server in the service lifecycle.
|
|
14
|
+
module Server
|
|
15
|
+
# Do not restart after the HTTY session ends.
|
|
16
|
+
# Unlike a TCP server, there is nothing to reconnect to once
|
|
17
|
+
# stdin/stdout closes.
|
|
18
|
+
# @returns [Hash]
|
|
19
|
+
def container_options
|
|
20
|
+
{count: 1, restart: false}
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
# Use the HTTY service server instead of Falcon's.
|
|
24
|
+
# @returns [Class]
|
|
25
|
+
def service_class
|
|
26
|
+
Async::HTTY::Service::Server
|
|
27
|
+
end
|
|
28
|
+
end
|
|
29
|
+
end
|
|
30
|
+
end
|
|
31
|
+
end
|
data/lib/async/htty/server.rb
CHANGED
|
@@ -28,7 +28,7 @@ module Async
|
|
|
28
28
|
def self.open(app = nil, input: $stdin, output: $stdout, error: $stderr, env: ENV, **options, &block)
|
|
29
29
|
app ||= block
|
|
30
30
|
server = self.new(app, **options)
|
|
31
|
-
|
|
31
|
+
|
|
32
32
|
case env["HTTY"]
|
|
33
33
|
when "0"
|
|
34
34
|
raise DisabledError, "HTTY is disabled!"
|
|
@@ -36,7 +36,7 @@ module Async
|
|
|
36
36
|
$stderr.puts "HTTY is not supported by this environment, visit https://htty.dev for more information."
|
|
37
37
|
raise UnsupportedError, "HTTY is not supported by this environment"
|
|
38
38
|
end
|
|
39
|
-
|
|
39
|
+
|
|
40
40
|
unless input.respond_to?(:tty?) && input.tty?
|
|
41
41
|
raise UnsupportedError, "HTTY requires a TTY input stream"
|
|
42
42
|
end
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
# Released under the MIT License.
|
|
4
|
+
# Copyright, 2026, by Samuel Williams.
|
|
5
|
+
|
|
6
|
+
require "async/service/generic"
|
|
7
|
+
require_relative "../server"
|
|
8
|
+
|
|
9
|
+
module Async
|
|
10
|
+
module HTTY
|
|
11
|
+
module Service
|
|
12
|
+
# An async-service managed service that runs an HTTY server.
|
|
13
|
+
# Mirrors Falcon::Service::Server but binds to stdin/stdout instead
|
|
14
|
+
# of a TCP endpoint. The container thread lifetime equals the HTTY session.
|
|
15
|
+
#
|
|
16
|
+
# We use Generic rather than Managed::Service because Managed::Service
|
|
17
|
+
# calls instance.ready! *after* run() returns. For HTTY, run() blocks for
|
|
18
|
+
# the entire session, so ready! would never be signalled while the session
|
|
19
|
+
# is live — causing the container controller to hang in wait_until_ready.
|
|
20
|
+
class Server < Async::Service::Generic
|
|
21
|
+
# Set up the container to run the HTTY server.
|
|
22
|
+
# Signals instance.ready! before the blocking accept loop so the
|
|
23
|
+
# controller does not stall waiting for startup confirmation.
|
|
24
|
+
#
|
|
25
|
+
# @parameter container [Async::Container::Generic]
|
|
26
|
+
def setup(container)
|
|
27
|
+
super
|
|
28
|
+
|
|
29
|
+
container.run(**@evaluator.container_options) do |instance|
|
|
30
|
+
Sync do
|
|
31
|
+
server = Async::HTTY::Server.new(@evaluator.middleware)
|
|
32
|
+
|
|
33
|
+
original_input = $stdin.dup
|
|
34
|
+
original_output = $stdout.dup
|
|
35
|
+
original_error = $stderr.dup
|
|
36
|
+
|
|
37
|
+
stream = ::Protocol::HTTY::Stream.new(original_input, original_output)
|
|
38
|
+
|
|
39
|
+
$stdin.reopen(File::NULL)
|
|
40
|
+
$stdout.reopen(File::NULL)
|
|
41
|
+
if path = ENV.fetch("HTTY_ERROR_LOG", nil)
|
|
42
|
+
$stderr.reopen(File.open(path, "a"))
|
|
43
|
+
else
|
|
44
|
+
$stderr.reopen(File::NULL)
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
instance.ready!
|
|
48
|
+
|
|
49
|
+
Async::HTTY::Server.with_raw_terminal(original_input) do
|
|
50
|
+
server.accept(stream)
|
|
51
|
+
end
|
|
52
|
+
ensure
|
|
53
|
+
$stdin.reopen(original_input) rescue nil
|
|
54
|
+
$stdout.reopen(original_output) rescue nil
|
|
55
|
+
$stderr.reopen(original_error) rescue nil
|
|
56
|
+
end
|
|
57
|
+
end
|
|
58
|
+
end
|
|
59
|
+
end
|
|
60
|
+
end
|
|
61
|
+
end
|
|
62
|
+
end
|
data/lib/async/htty/version.rb
CHANGED
data/readme.md
CHANGED
|
@@ -14,6 +14,10 @@ Please see the [project documentation](https://socketry.github.io/async-htty/) f
|
|
|
14
14
|
|
|
15
15
|
Please see the [project releases](https://socketry.github.io/async-htty/releases/index) for all releases.
|
|
16
16
|
|
|
17
|
+
### v0.5.0
|
|
18
|
+
|
|
19
|
+
- Add `Async::HTTY::Service::Server` and `Async::HTTY::Environment::Server`.
|
|
20
|
+
|
|
17
21
|
### v0.4.0
|
|
18
22
|
|
|
19
23
|
- Suppress errors from `send_goaway` during connection cleanup to prevent shutdown exceptions from propagating.
|
data/releases.md
CHANGED
data/test/async/htty/server.rb
CHANGED
|
@@ -209,15 +209,15 @@ describe Async::HTTY::Server do
|
|
|
209
209
|
|
|
210
210
|
expect(Async::HTTY::DisabledError).to be < Async::HTTY::UnsupportedError
|
|
211
211
|
end
|
|
212
|
-
|
|
212
|
+
|
|
213
213
|
it "raises a typed error when stdin is not a tty" do
|
|
214
214
|
input = Async::HTTY::FakeFile.new
|
|
215
215
|
output = Async::HTTY::FakeFile.new
|
|
216
|
-
|
|
216
|
+
|
|
217
217
|
expect do
|
|
218
218
|
subject.open(Protocol::HTTP::Middleware::Okay, input: input, output: output, error: error, env: env)
|
|
219
219
|
end.to raise_exception(Async::HTTY::UnsupportedError, message: be =~ /TTY input/)
|
|
220
|
-
|
|
220
|
+
|
|
221
221
|
expect(input.reopen_events).to be == []
|
|
222
222
|
expect(output.reopen_events).to be == []
|
|
223
223
|
end
|
|
@@ -238,12 +238,12 @@ describe Async::HTTY::Server do
|
|
|
238
238
|
|
|
239
239
|
expect(error_output.string).to be(:include?, "https://htty.dev")
|
|
240
240
|
end
|
|
241
|
-
|
|
241
|
+
|
|
242
242
|
it "opens a server within its own async context when no task is provided" do
|
|
243
243
|
input = Async::HTTY::FakeFile.new(tty: true)
|
|
244
244
|
output = Async::HTTY::FakeFile.new
|
|
245
245
|
accepted = false
|
|
246
|
-
|
|
246
|
+
|
|
247
247
|
server = Object.new
|
|
248
248
|
server.define_singleton_method(:each) do
|
|
249
249
|
end
|
|
@@ -254,15 +254,15 @@ describe Async::HTTY::Server do
|
|
|
254
254
|
end
|
|
255
255
|
server.define_singleton_method(:close) do
|
|
256
256
|
end
|
|
257
|
-
|
|
257
|
+
|
|
258
258
|
protocol = Object.new
|
|
259
259
|
protocol.define_singleton_method(:server) do |stream|
|
|
260
260
|
accepted = true
|
|
261
261
|
server
|
|
262
262
|
end
|
|
263
|
-
|
|
263
|
+
|
|
264
264
|
subject.open(Protocol::HTTP::Middleware::Okay, input: input, output: output, error: error, env: env, protocol: protocol)
|
|
265
|
-
|
|
265
|
+
|
|
266
266
|
expect(accepted).to be == true
|
|
267
267
|
end
|
|
268
268
|
end
|
data.tar.gz.sig
CHANGED
|
Binary file
|
metadata
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: async-htty
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.
|
|
4
|
+
version: 0.5.0
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Samuel Williams
|
|
@@ -86,14 +86,14 @@ dependencies:
|
|
|
86
86
|
requirements:
|
|
87
87
|
- - "~>"
|
|
88
88
|
- !ruby/object:Gem::Version
|
|
89
|
-
version: '0.
|
|
89
|
+
version: '0.4'
|
|
90
90
|
type: :runtime
|
|
91
91
|
prerelease: false
|
|
92
92
|
version_requirements: !ruby/object:Gem::Requirement
|
|
93
93
|
requirements:
|
|
94
94
|
- - "~>"
|
|
95
95
|
- !ruby/object:Gem::Version
|
|
96
|
-
version: '0.
|
|
96
|
+
version: '0.4'
|
|
97
97
|
executables: []
|
|
98
98
|
extensions: []
|
|
99
99
|
extra_rdoc_files: []
|
|
@@ -102,11 +102,13 @@ files:
|
|
|
102
102
|
- examples/hello_world.rb
|
|
103
103
|
- examples/raw_mode_probe.rb
|
|
104
104
|
- lib/async/htty.rb
|
|
105
|
+
- lib/async/htty/environment/server.rb
|
|
105
106
|
- lib/async/htty/error.rb
|
|
106
107
|
- lib/async/htty/protocol.rb
|
|
107
108
|
- lib/async/htty/protocol/htty.rb
|
|
108
109
|
- lib/async/htty/protocol/htty/server.rb
|
|
109
110
|
- lib/async/htty/server.rb
|
|
111
|
+
- lib/async/htty/service/server.rb
|
|
110
112
|
- lib/async/htty/version.rb
|
|
111
113
|
- license.md
|
|
112
114
|
- readme.md
|
metadata.gz.sig
CHANGED
|
Binary file
|