sanford 0.11.1 → 0.12.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.
data/lib/sanford/cli.rb CHANGED
@@ -23,7 +23,7 @@ module Sanford
23
23
  rescue CLIRB::HelpExit
24
24
  @kernel.puts help
25
25
  rescue CLIRB::VersionExit
26
- @kernel.puts "sanford #{Sanford::VERSION}"
26
+ @kernel.puts Sanford::VERSION
27
27
  rescue CLIRB::Error, Sanford::ConfigFile::InvalidError => exception
28
28
  @kernel.puts "#{exception.message}\n\n"
29
29
  @kernel.puts help
@@ -40,8 +40,9 @@ module Sanford
40
40
 
41
41
  def run!(*args)
42
42
  @cli.parse!(args)
43
- command = @cli.args.pop || 'run'
44
- config_file_path = @cli.args.pop || 'config.sanford'
43
+ config_file_path, command = @cli.args
44
+ config_file_path ||= 'config.sanford'
45
+ command ||= 'run'
45
46
  server = Sanford::ConfigFile.new(config_file_path).server
46
47
  case(command)
47
48
  when 'run'
@@ -58,9 +59,9 @@ module Sanford
58
59
  end
59
60
 
60
61
  def help
61
- "Usage: sanford [CONFIG_FILE] [COMMAND]\n" \
62
- "Commands: run, start, stop, restart" \
63
- "#{@cli}"
62
+ "Usage: sanford [CONFIG_FILE] [COMMAND] [options]\n\n" \
63
+ "Commands: run, start, stop, restart\n" \
64
+ "Options: #{@cli}"
64
65
  end
65
66
 
66
67
  end
data/lib/sanford/route.rb CHANGED
@@ -17,7 +17,13 @@ module Sanford
17
17
  end
18
18
 
19
19
  def run(request, server_data)
20
- SanfordRunner.new(self.handler_class, request, server_data).run
20
+ SanfordRunner.new(self.handler_class, {
21
+ :request => request,
22
+ :params => request.params,
23
+ :logger => server_data.logger,
24
+ :router => server_data.router,
25
+ :template_source => server_data.template_source
26
+ }).run
21
27
  end
22
28
 
23
29
  private
@@ -1,5 +1,11 @@
1
+ # need to define class immediately b/c of circular requires:
2
+ # - runner -> router -> route -> sanford_runner -> runner
3
+ module Sanford; end
4
+ class Sanford::Runner; end
5
+
1
6
  require 'sanford-protocol'
2
7
  require 'sanford/logger'
8
+ require 'sanford/router'
3
9
  require 'sanford/template_source'
4
10
 
5
11
  module Sanford
@@ -9,17 +15,28 @@ module Sanford
9
15
  ResponseArgs = Struct.new(:status, :data)
10
16
 
11
17
  attr_reader :handler_class, :handler
12
- attr_reader :request, :params, :logger, :template_source
18
+ attr_reader :request, :params, :logger, :router, :template_source
13
19
 
14
- def initialize(handler_class)
20
+ def initialize(handler_class, args = nil)
15
21
  @handler_class = handler_class
16
22
  @handler = @handler_class.new(self)
23
+
24
+ a = args || {}
25
+ @request = a[:request]
26
+ @params = a[:params] || {}
27
+ @logger = a[:logger] || Sanford::NullLogger.new
28
+ @router = a[:router] || Sanford::Router.new
29
+ @template_source = a[:template_source] || Sanford::NullTemplateSource.new
17
30
  end
18
31
 
19
32
  def run
20
33
  raise NotImplementedError
21
34
  end
22
35
 
36
+ def render(path, locals = nil)
37
+ self.template_source.render(path, self.handler, locals || {})
38
+ end
39
+
23
40
  # It's best to keep what `halt` and `catch_halt` return in the same format.
24
41
  # Currently this is a `ResponseArgs` object. This is so no matter how the
25
42
  # block returns (either by throwing or running normally), you get the same
@@ -2,19 +2,7 @@ require 'sanford/runner'
2
2
 
3
3
  module Sanford
4
4
 
5
- class SanfordRunner < Sanford::Runner
6
-
7
- def initialize(handler_class, request, server_data)
8
- @request = request
9
- @params = @request.params
10
- @logger = server_data.logger
11
- @template_source = server_data.template_source
12
-
13
- super(handler_class)
14
- end
15
-
16
- # call the handler init and the handler run - if the init halts, run won't
17
- # be called.
5
+ class SanfordRunner < Runner
18
6
 
19
7
  def run
20
8
  build_response do
@@ -172,11 +172,6 @@ module Sanford
172
172
  self.configuration.template_source(*args)
173
173
  end
174
174
 
175
- def build_template_source(path, &block)
176
- block ||= proc{ }
177
- self.template_source TemplateSource.new(path).tap(&block)
178
- end
179
-
180
175
  end
181
176
 
182
177
  class Connection
@@ -266,9 +261,10 @@ module Sanford
266
261
 
267
262
  def to_hash
268
263
  super.merge({
264
+ :init_procs => self.init_procs,
269
265
  :error_procs => self.error_procs,
270
- :routes => self.routes,
271
- :template_source => self.template_source
266
+ :router => self.router,
267
+ :routes => self.routes
272
268
  })
273
269
  end
274
270
 
@@ -10,24 +10,29 @@ module Sanford
10
10
  attr_reader :name
11
11
  attr_reader :ip, :port
12
12
  attr_reader :pid_file
13
- attr_reader :logger, :verbose_logging
14
13
  attr_reader :receives_keep_alive
15
- attr_reader :error_procs
16
- attr_reader :routes
17
- attr_reader :template_source
14
+ attr_reader :verbose_logging, :logger, :template_source
15
+ attr_reader :init_procs, :error_procs
16
+ attr_reader :router, :routes
18
17
 
19
18
  def initialize(args = nil)
20
19
  args ||= {}
21
- @name = args[:name]
22
- @ip = args[:ip]
23
- @port = args[:port]
20
+ @name = args[:name]
21
+ @ip = args[:ip]
22
+ @port = args[:port]
24
23
  @pid_file = args[:pid_file]
25
- @logger = args[:logger]
26
- @verbose_logging = !!args[:verbose_logging]
24
+
27
25
  @receives_keep_alive = !!args[:receives_keep_alive]
26
+
27
+ @verbose_logging = !!args[:verbose_logging]
28
+ @logger = args[:logger]
29
+ @template_source = args[:template_source]
30
+
31
+ @init_procs = args[:init_procs] || []
28
32
  @error_procs = args[:error_procs] || []
33
+
34
+ @router = args[:router]
29
35
  @routes = build_routes(args[:routes] || [])
30
- @template_source = args[:template_source]
31
36
  end
32
37
 
33
38
  def route_for(name)
@@ -37,23 +37,18 @@ module Sanford
37
37
 
38
38
  def inspect
39
39
  reference = '0x0%x' % (self.object_id << 1)
40
- "#<#{self.class}:#{reference} @request=#{self.request.inspect}>"
40
+ "#<#{self.class}:#{reference} @request=#{request.inspect}>"
41
41
  end
42
42
 
43
43
  private
44
44
 
45
45
  # Helpers
46
46
 
47
- def render(path, options = nil)
48
- options ||= {}
49
- source = options['source'] || @sanford_runner.template_source
50
- source.render(path, self, options['locals'] || {})
51
- end
52
-
53
- def halt(*args); @sanford_runner.halt(*args); end
54
- def request; @sanford_runner.request; end
55
- def params; @sanford_runner.params; end
56
- def logger; @sanford_runner.logger; end
47
+ def render(*args); @sanford_runner.render(*args); end
48
+ def halt(*args); @sanford_runner.halt(*args); end
49
+ def request; @sanford_runner.request; end
50
+ def params; @sanford_runner.params; end
51
+ def logger; @sanford_runner.logger; end
57
52
 
58
53
  def run_callback(callback)
59
54
  (self.class.send("#{callback}_callbacks") || []).each do |callback|
@@ -1,14 +1,16 @@
1
1
  require 'pathname'
2
+ require 'sanford/logger'
2
3
 
3
4
  module Sanford
4
5
 
5
6
  class TemplateEngine
6
7
 
7
- attr_reader :source_path, :opts
8
+ attr_reader :source_path, :logger, :opts
8
9
 
9
10
  def initialize(opts = nil)
10
11
  @opts = opts || {}
11
12
  @source_path = Pathname.new(@opts['source_path'].to_s)
13
+ @logger = @opts['logger'] || Sanford::NullLogger.new
12
14
  end
13
15
 
14
16
  def render(path, service_handler, locals)
@@ -1,3 +1,4 @@
1
+ require 'sanford/logger'
1
2
  require 'sanford/template_engine'
2
3
 
3
4
  module Sanford
@@ -10,9 +11,12 @@ module Sanford
10
11
 
11
12
  attr_reader :path, :engines
12
13
 
13
- def initialize(path)
14
+ def initialize(path, logger = nil)
14
15
  @path = path.to_s
15
- @default_opts = { 'source_path' => @path }
16
+ @default_opts = {
17
+ 'source_path' => @path,
18
+ 'logger' => logger || Sanford::NullLogger.new
19
+ }
16
20
  @engines = Hash.new{ |h,k| Sanford::NullTemplateEngine.new(@default_opts) }
17
21
  end
18
22
 
@@ -25,6 +29,10 @@ module Sanford
25
29
  @engines[input_ext.to_s] = engine_class.new(engine_opts)
26
30
  end
27
31
 
32
+ def engine_for?(template_name)
33
+ @engines.keys.include?(get_template_ext(template_name))
34
+ end
35
+
28
36
  def render(template_path, service_handler, locals)
29
37
  engine = @engines[get_template_ext(template_path)]
30
38
  engine.render(template_path, service_handler, locals)
@@ -1,14 +1,12 @@
1
1
  require 'sanford-protocol'
2
- require 'sanford/logger'
3
2
  require 'sanford/runner'
4
3
  require 'sanford/service_handler'
5
- require 'sanford/template_source'
6
4
 
7
5
  module Sanford
8
6
 
9
7
  InvalidServiceHandlerError = Class.new(StandardError)
10
8
 
11
- class TestRunner < Sanford::Runner
9
+ class TestRunner < Runner
12
10
 
13
11
  attr_reader :response
14
12
 
@@ -17,14 +15,15 @@ module Sanford
17
15
  raise InvalidServiceHandlerError, "#{handler_class.inspect} is not a"\
18
16
  " Sanford::ServiceHandler"
19
17
  end
20
- args = (args || {}).dup
21
- @request = args.delete(:request)
22
- @params = args.delete(:params) || {}
23
- @logger = args.delete(:logger) || Sanford::NullLogger.new
24
- @template_source = args.delete(:template_source) ||
25
- Sanford::NullTemplateSource.new
26
18
 
27
- super(handler_class)
19
+ args = (args || {}).dup
20
+ super(handler_class, {
21
+ :request => args.delete(:request),
22
+ :params => args.delete(:params),
23
+ :logger => args.delete(:logger),
24
+ :router => args.delete(:router),
25
+ :template_source => args.delete(:template_source)
26
+ })
28
27
  args.each{ |key, value| @handler.send("#{key}=", value) }
29
28
 
30
29
  return_value = catch(:halt){ @handler.init; nil }
@@ -1,3 +1,3 @@
1
1
  module Sanford
2
- VERSION = "0.11.1"
2
+ VERSION = "0.12.0"
3
3
  end
data/sanford.gemspec CHANGED
@@ -20,7 +20,7 @@ Gem::Specification.new do |gem|
20
20
 
21
21
  gem.add_dependency("dat-tcp", ["~> 0.5"])
22
22
  gem.add_dependency("ns-options", ["~> 1.1"])
23
- gem.add_dependency("sanford-protocol", ["~> 0.9"])
23
+ gem.add_dependency("sanford-protocol", ["~> 0.10"])
24
24
 
25
- gem.add_development_dependency("assert", ["~> 2.11"])
25
+ gem.add_development_dependency("assert", ["~> 2.12"])
26
26
  end
@@ -1,6 +1,6 @@
1
1
  require 'pathname'
2
- require 'sanford'
3
2
  require 'sanford-protocol'
3
+ require 'sanford'
4
4
 
5
5
  if !defined?(ROOT_PATH)
6
6
  ROOT_PATH = Pathname.new(File.expand_path('../../..', __FILE__))
@@ -40,8 +40,9 @@ class AppServer
40
40
  service 'custom_error', 'CustomError'
41
41
  end
42
42
 
43
- build_template_source ROOT_PATH.join('test/support').to_s do |s|
43
+ Sanford::TemplateSource.new(ROOT_PATH.join('test/support').to_s).tap do |s|
44
44
  s.engine 'erb', AppERBEngine
45
+ template_source s
45
46
  end
46
47
 
47
48
  error do |exception, server_data, request|
@@ -1,10 +1,23 @@
1
1
  require 'assert'
2
2
  require 'sanford/cli'
3
3
 
4
+ require 'sanford/server'
5
+
4
6
  class Sanford::CLI
5
7
 
6
8
  class UnitTests < Assert::Context
7
9
  desc "Sanford::CLI"
10
+ setup do
11
+ @cli_class = Sanford::CLI
12
+ end
13
+ subject{ @cli_class }
14
+
15
+ should have_imeths :run
16
+
17
+ end
18
+
19
+ class InitTests < UnitTests
20
+ desc "when init"
8
21
  setup do
9
22
  @kernel_spy = KernelSpy.new
10
23
  @file_path = Factory.file_path
@@ -14,48 +27,43 @@ class Sanford::CLI
14
27
  @config_file = FakeConfigFile.new(@server)
15
28
  Assert.stub(Sanford::ConfigFile, :new).with(@file_path){ @config_file }
16
29
 
30
+ @process_spy = ProcessSpy.new
31
+ @process_signal_spy = ProcessSignalSpy.new
32
+
17
33
  @cli = Sanford::CLI.new(@kernel_spy)
18
34
  end
19
35
  subject{ @cli }
20
36
 
21
- should have_cmeths :run
22
37
  should have_imeths :run
23
38
 
24
39
  end
25
40
 
26
- class CommandTests < UnitTests
41
+ class DefaultsTests < InitTests
27
42
  setup do
28
- @process_spy = ProcessSpy.new
29
- @process_signal_spy = ProcessSignalSpy.new
30
- end
31
-
32
- end
33
-
34
- class DefaultsTests < CommandTests
35
- desc "with no command or file path"
36
- setup do
37
- file_path = 'config.sanford'
38
- Assert.stub(Sanford::ConfigFile, :new).with(file_path){ @config_file }
43
+ Assert.stub(Sanford::ConfigFile, :new).with('config.sanford'){ @config_file }
39
44
  Assert.stub(Sanford::Process, :new).with(@server, :daemonize => false) do
40
45
  @process_spy
41
46
  end
47
+ end
42
48
 
43
- @cli.run
49
+ should "default the command when its not provided" do
50
+ subject.run(@file_path)
51
+ assert_true @process_spy.run_called
44
52
  end
45
53
 
46
- should "have defaulted the command and file path" do
54
+ should "default the command and file path when they aren't provided" do
55
+ subject.run
47
56
  assert_true @process_spy.run_called
48
57
  end
49
58
 
50
59
  end
51
60
 
52
- class RunTests < CommandTests
61
+ class RunTests < InitTests
53
62
  desc "with the run command"
54
63
  setup do
55
64
  Assert.stub(Sanford::Process, :new).with(@server, :daemonize => false) do
56
65
  @process_spy
57
66
  end
58
-
59
67
  @cli.run(@file_path, 'run')
60
68
  end
61
69
 
@@ -65,7 +73,7 @@ class Sanford::CLI
65
73
 
66
74
  end
67
75
 
68
- class StartTests < CommandTests
76
+ class StartTests < InitTests
69
77
  desc "with the start command"
70
78
  setup do
71
79
  Assert.stub(Sanford::Process, :new).with(@server, :daemonize => true) do
@@ -81,7 +89,7 @@ class Sanford::CLI
81
89
 
82
90
  end
83
91
 
84
- class StopTests < CommandTests
92
+ class StopTests < InitTests
85
93
  desc "with the stop command"
86
94
  setup do
87
95
  Assert.stub(Sanford::ProcessSignal, :new).with(@server, 'TERM') do
@@ -97,7 +105,7 @@ class Sanford::CLI
97
105
 
98
106
  end
99
107
 
100
- class RestartTests < CommandTests
108
+ class RestartTests < InitTests
101
109
  desc "with the restart command"
102
110
  setup do
103
111
  Assert.stub(Sanford::ProcessSignal, :new).with(@server, 'USR2') do
@@ -113,7 +121,7 @@ class Sanford::CLI
113
121
 
114
122
  end
115
123
 
116
- class InvalidCommandTests < UnitTests
124
+ class InvalidCommandTests < InitTests
117
125
  desc "with an invalid command"
118
126
  setup do
119
127
  @command = Factory.string
@@ -36,22 +36,32 @@ class Sanford::Route
36
36
  class RunTests < UnitTests
37
37
  desc "when run"
38
38
  setup do
39
- @route.validate!
40
- @request = Factory.string
41
- @server_data = Sanford::ServerData.new
39
+ @runner_spy = SanfordRunnerSpy.new
40
+ Assert.stub(Sanford::SanfordRunner, :new) do |*args|
41
+ @runner_spy.build(*args)
42
+ @runner_spy
43
+ end
42
44
 
43
- @runner_spy = RunnerSpy.new(Factory.text)
44
- Assert.stub(Sanford::SanfordRunner, :new).with(
45
- @route.handler_class,
46
- @request,
47
- @server_data
48
- ){ @runner_spy }
45
+ @request = OpenStruct.new('params' => 'some-params')
46
+ @server_data = Sanford::ServerData.new
49
47
 
48
+ @route.validate!
50
49
  @response = @route.run(@request, @server_data)
51
50
  end
52
51
  subject{ @response }
53
52
 
54
53
  should "build and run a sanford runner" do
54
+ assert_equal @route.handler_class, @runner_spy.handler_class
55
+
56
+ exp_args = {
57
+ :request => @request,
58
+ :params => @request.params,
59
+ :logger => @server_data.logger,
60
+ :router => @server_data.router,
61
+ :template_source => @server_data.template_source
62
+ }
63
+ assert_equal exp_args, @runner_spy.args
64
+
55
65
  assert_true @runner_spy.run_called
56
66
  end
57
67
 
@@ -75,18 +85,34 @@ class Sanford::Route
75
85
 
76
86
  TestHandler = Class.new
77
87
 
78
- class RunnerSpy
79
- attr_reader :response, :run_called
88
+ class SanfordRunnerSpy
80
89
 
81
- def initialize(response)
82
- @response = response
90
+ attr_reader :run_called
91
+ attr_reader :handler_class, :args
92
+ attr_reader :request, :params, :logger, :router, :template_source
93
+ attr_reader :response
94
+
95
+ def initialize
83
96
  @run_called = false
84
97
  end
85
98
 
99
+ def build(handler_class, args)
100
+ @handler_class, @args = handler_class, args
101
+
102
+ @request = args[:request]
103
+ @params = args[:params]
104
+ @logger = args[:logger]
105
+ @router = args[:router]
106
+ @template_source = args[:template_source]
107
+
108
+ @response = Factory.string
109
+ end
110
+
86
111
  def run
87
112
  @run_called = true
88
113
  @response
89
114
  end
115
+
90
116
  end
91
117
 
92
118
  end
@@ -1,7 +1,9 @@
1
1
  require 'assert'
2
2
  require 'sanford/runner'
3
3
 
4
- require 'sanford/server_data'
4
+ require 'sanford/logger'
5
+ require 'sanford/router'
6
+ require 'sanford/template_source'
5
7
  require 'sanford/service_handler'
6
8
 
7
9
  class Sanford::Runner
@@ -10,7 +12,6 @@ class Sanford::Runner
10
12
  desc "Sanford::Runner"
11
13
  setup do
12
14
  @handler_class = TestServiceHandler
13
-
14
15
  @runner_class = Sanford::Runner
15
16
  end
16
17
  subject{ @runner_class }
@@ -20,12 +21,13 @@ class Sanford::Runner
20
21
  class InitTests < UnitTests
21
22
  desc "when init"
22
23
  setup do
23
- @runner = @runner_class.new(@handler_class)
24
+ source = FakeTemplateSource.new
25
+ @runner = @runner_class.new(@handler_class, :template_source => source)
24
26
  end
25
27
  subject{ @runner }
26
28
 
27
29
  should have_readers :handler_class, :handler
28
- should have_readers :request, :params, :logger, :template_source
30
+ should have_readers :request, :params, :logger, :router, :template_source
29
31
  should have_imeths :run
30
32
  should have_imeths :halt
31
33
 
@@ -34,11 +36,30 @@ class Sanford::Runner
34
36
  assert_instance_of @handler_class, subject.handler
35
37
  end
36
38
 
37
- should "not set its request, params, logger or template source" do
38
- assert_nil subject.request
39
- assert_nil subject.params
40
- assert_nil subject.logger
41
- assert_nil subject.template_source
39
+ should "default its settings" do
40
+ runner = @runner_class.new(@handler_class)
41
+ assert_nil runner.request
42
+ assert_equal ::Hash.new, runner.params
43
+ assert_kind_of Sanford::NullLogger, runner.logger
44
+ assert_kind_of Sanford::Router, runner.router
45
+ assert_kind_of Sanford::NullTemplateSource, runner.template_source
46
+ end
47
+
48
+ should "not implement its run method" do
49
+ assert_raises(NotImplementedError){ subject.run }
50
+ end
51
+
52
+ should "use the template source to render" do
53
+ path = 'template.json'
54
+ locals = { 'something' => Factory.string }
55
+ exp = subject.template_source.render(path, subject.handler, locals)
56
+ assert_equal exp, subject.render(path, locals)
57
+ end
58
+
59
+ should "default its locals to an empty hash when rendering" do
60
+ path = Factory.file_path
61
+ exp = subject.template_source.render(path, subject.handler, {})
62
+ assert_equal exp, subject.render(path)
42
63
  end
43
64
 
44
65
  should "throw halt with response args using `halt`" do
@@ -67,14 +88,16 @@ class Sanford::Runner
67
88
  assert_equal data, result.data
68
89
  end
69
90
 
70
- should "raise a not implemented error when run" do
71
- assert_raises(NotImplementedError){ subject.run }
72
- end
73
-
74
91
  end
75
92
 
76
93
  class TestServiceHandler
77
94
  include Sanford::ServiceHandler
78
95
  end
79
96
 
97
+ class FakeTemplateSource
98
+ def render(path, service_handler, locals)
99
+ [path.to_s, service_handler.class.to_s, locals]
100
+ end
101
+ end
102
+
80
103
  end
@@ -1,7 +1,7 @@
1
1
  require 'assert'
2
2
  require 'sanford/sanford_runner'
3
3
 
4
- require 'sanford/server_data'
4
+ require 'sanford/runner'
5
5
  require 'sanford/service_handler'
6
6
 
7
7
  class Sanford::SanfordRunner
@@ -10,14 +10,6 @@ class Sanford::SanfordRunner
10
10
  desc "Sanford::SanfordRunner"
11
11
  setup do
12
12
  @handler_class = TestServiceHandler
13
- @request = Sanford::Protocol::Request.new(Factory.string, {
14
- :something => Factory.string
15
- })
16
- @server_data = Sanford::ServerData.new({
17
- :logger => Factory.string,
18
- :template_source => Factory.string
19
- })
20
-
21
13
  @runner_class = Sanford::SanfordRunner
22
14
  end
23
15
  subject{ @runner_class }
@@ -31,16 +23,11 @@ class Sanford::SanfordRunner
31
23
  class InitTests < UnitTests
32
24
  desc "when init"
33
25
  setup do
34
- @runner = @runner_class.new(@handler_class, @request, @server_data)
26
+ @runner = @runner_class.new(@handler_class)
35
27
  end
36
28
  subject{ @runner }
37
29
 
38
- should "know its request, params, logger and template source" do
39
- assert_equal @request, subject.request
40
- assert_equal @request.params, subject.params
41
- assert_equal @server_data.logger, subject.logger
42
- assert_equal @server_data.template_source, subject.template_source
43
- end
30
+ should have_imeths :run
44
31
 
45
32
  end
46
33
 
@@ -77,8 +64,9 @@ class Sanford::SanfordRunner
77
64
  class RunHaltInBeforeTests < UnitTests
78
65
  desc "running a handler that halts in a before callback"
79
66
  setup do
80
- req = Sanford::Protocol::Request.new(Factory.string, 'halt' => 'before')
81
- runner = @runner_class.new(@handler_class, req, @server_data).tap(&:run)
67
+ runner = @runner_class.new(@handler_class, :params => {
68
+ 'halt' => 'before'
69
+ }).tap(&:run)
82
70
  @handler = runner.handler
83
71
  end
84
72
  subject{ @handler }
@@ -97,8 +85,9 @@ class Sanford::SanfordRunner
97
85
  class RunHandlerHaltInitTests < UnitTests
98
86
  desc "running a handler that halts in init"
99
87
  setup do
100
- req = Sanford::Protocol::Request.new(Factory.string, 'halt' => 'init')
101
- runner = @runner_class.new(@handler_class, req, @server_data).tap(&:run)
88
+ runner = @runner_class.new(@handler_class, :params => {
89
+ 'halt' => 'init'
90
+ }).tap(&:run)
102
91
  @handler = runner.handler
103
92
  end
104
93
  subject{ @handler }
@@ -117,8 +106,9 @@ class Sanford::SanfordRunner
117
106
  class RunHandlerHaltRunTests < UnitTests
118
107
  desc "running a handler that halts in run"
119
108
  setup do
120
- req = Sanford::Protocol::Request.new(Factory.string, 'halt' => 'run')
121
- runner = @runner_class.new(@handler_class, req, @server_data).tap(&:run)
109
+ runner = @runner_class.new(@handler_class, :params => {
110
+ 'halt' => 'run'
111
+ }).tap(&:run)
122
112
  @handler = runner.handler
123
113
  end
124
114
  subject{ @handler }
@@ -137,8 +127,9 @@ class Sanford::SanfordRunner
137
127
  class RunHandlerHaltAfterTests < UnitTests
138
128
  desc "running a handler that halts in a after callback"
139
129
  setup do
140
- req = Sanford::Protocol::Request.new(Factory.string, 'halt' => 'after')
141
- runner = @runner_class.new(@handler_class, req, @server_data).tap(&:run)
130
+ runner = @runner_class.new(@handler_class, :params => {
131
+ 'halt' => 'after'
132
+ }).tap(&:run)
142
133
  @handler = runner.handler
143
134
  end
144
135
  subject{ @handler }
@@ -162,23 +153,13 @@ class Sanford::SanfordRunner
162
153
  attr_reader :init_call_order, :run_call_order
163
154
  attr_reader :response_data
164
155
 
165
- before do
166
- @first_before_call_order = next_call_order
167
- halt_if('before')
168
- end
156
+ before{ @first_before_call_order = next_call_order; halt_if('before') }
169
157
  before{ @second_before_call_order = next_call_order }
170
158
 
171
- after do
172
- @first_after_call_order = next_call_order
173
- halt_if('after')
174
- end
159
+ after{ @first_after_call_order = next_call_order; halt_if('after') }
175
160
  after{ @second_after_call_order = next_call_order }
176
161
 
177
- def init!
178
- @init_call_order = next_call_order
179
- halt_if('init')
180
- end
181
-
162
+ def init!; @init_call_order = next_call_order; halt_if('init'); end
182
163
  def run!
183
164
  @run_call_order = next_call_order
184
165
  halt_if('run')
@@ -187,11 +168,7 @@ class Sanford::SanfordRunner
187
168
 
188
169
  private
189
170
 
190
- def next_call_order
191
- @order ||= 0
192
- @order += 1
193
- end
194
-
171
+ def next_call_order; @order ||= 0; @order += 1; end
195
172
  def halt_if(value)
196
173
  halt Factory.integer if params['halt'] == value
197
174
  end
@@ -8,25 +8,35 @@ class Sanford::ServerData
8
8
  class UnitTests < Assert::Context
9
9
  desc "Sanford::ServerData"
10
10
  setup do
11
- @name = Factory.string
12
- @ip = Factory.string
13
- @port = Factory.integer
11
+ @name = Factory.string
12
+ @ip = Factory.string
13
+ @port = Factory.integer
14
14
  @pid_file = Factory.file_path
15
- @logger = Factory.string
16
- @verbose_logging = Factory.boolean
15
+
17
16
  @receives_keep_alive = Factory.boolean
18
- @error_procs = [ proc{ } ]
19
- @route = Sanford::Route.new(Factory.string, TestHandler.to_s).tap(&:validate!)
17
+
18
+ @verbose_logging = Factory.boolean
19
+ @logger = Factory.string
20
+ @template_source = Factory.string
21
+
22
+ @init_procs = [ proc{} ]
23
+ @error_procs = [ proc{} ]
24
+
25
+ @router = Factory.string
26
+ @route = Sanford::Route.new(Factory.string, TestHandler.to_s).tap(&:validate!)
20
27
 
21
28
  @server_data = Sanford::ServerData.new({
22
- :name => @name,
23
- :ip => @ip,
24
- :port => @port,
29
+ :name => @name,
30
+ :ip => @ip,
31
+ :port => @port,
25
32
  :pid_file => @pid_file,
26
- :logger => @logger,
27
- :verbose_logging => @verbose_logging,
28
33
  :receives_keep_alive => @receives_keep_alive,
34
+ :verbose_logging => @verbose_logging,
35
+ :logger => @logger,
36
+ :template_source => @template_source,
37
+ :init_procs => @init_procs,
29
38
  :error_procs => @error_procs,
39
+ :router => @router,
30
40
  :routes => [ @route ]
31
41
  })
32
42
  end
@@ -35,20 +45,27 @@ class Sanford::ServerData
35
45
  should have_readers :name
36
46
  should have_readers :ip, :port
37
47
  should have_readers :pid_file
38
- should have_readers :logger, :verbose_logging
39
48
  should have_readers :receives_keep_alive
40
- should have_readers :error_procs
41
- should have_readers :routes
49
+ should have_readers :verbose_logging, :logger, :template_source
50
+ should have_readers :init_procs, :error_procs
51
+ should have_readers :router, :routes
42
52
 
43
53
  should "know its attributes" do
44
- assert_equal @name, subject.name
45
- assert_equal @ip, subject.ip
46
- assert_equal @port, subject.port
54
+ assert_equal @name, subject.name
55
+ assert_equal @ip, subject.ip
56
+ assert_equal @port, subject.port
47
57
  assert_equal @pid_file, subject.pid_file
48
- assert_equal @logger, subject.logger
49
- assert_equal @verbose_logging, subject.verbose_logging
58
+
50
59
  assert_equal @receives_keep_alive, subject.receives_keep_alive
60
+
61
+ assert_equal @verbose_logging, subject.verbose_logging
62
+ assert_equal @logger, subject.logger
63
+ assert_equal @template_source, subject.template_source
64
+
65
+ assert_equal @init_procs, subject.error_procs
51
66
  assert_equal @error_procs, subject.error_procs
67
+
68
+ assert_equal @router, subject.router
52
69
  end
53
70
 
54
71
  should "build a routes lookup hash" do
@@ -73,10 +90,17 @@ class Sanford::ServerData
73
90
  assert_nil server_data.ip
74
91
  assert_nil server_data.port
75
92
  assert_nil server_data.pid_file
76
- assert_nil server_data.logger
77
- assert_false server_data.verbose_logging
93
+
78
94
  assert_false server_data.receives_keep_alive
95
+
96
+ assert_false server_data.verbose_logging
97
+ assert_nil server_data.logger
98
+ assert_nil server_data.template_source
99
+
100
+ assert_equal [], server_data.init_procs
79
101
  assert_equal [], server_data.error_procs
102
+
103
+ assert_nil server_data.router
80
104
  assert_equal({}, server_data.routes)
81
105
  end
82
106
 
@@ -23,8 +23,7 @@ module Sanford::Server
23
23
  should have_imeths :receives_keep_alive
24
24
  should have_imeths :verbose_logging, :logger
25
25
  should have_imeths :init, :error
26
- should have_imeths :router
27
- should have_imeths :template_source, :build_template_source
26
+ should have_imeths :router, :template_source
28
27
 
29
28
  should "know its configuration" do
30
29
  config = subject.configuration
@@ -117,20 +116,6 @@ module Sanford::Server
117
116
  assert_equal new_template_source, subject.template_source
118
117
  end
119
118
 
120
- should "allow setting its template source with a path and block" do
121
- new_path = Factory.string
122
- yielded = nil
123
- subject.build_template_source(new_path){ |s| yielded = s }
124
- assert_equal new_path, subject.configuration.template_source.path
125
- assert_equal subject.configuration.template_source, yielded
126
- end
127
-
128
- should "allow setting its template source with only a path" do
129
- new_path = Factory.string
130
- subject.build_template_source(new_path)
131
- assert_equal new_path, subject.configuration.template_source.path
132
- end
133
-
134
119
  end
135
120
 
136
121
  class InitTests < UnitTests
@@ -448,13 +433,12 @@ module Sanford::Server
448
433
  assert_equal subject.router.routes, subject.routes
449
434
  end
450
435
 
451
- should "include its routes, error procs and template source in its hash" do
436
+ should "include its init/error procs and router/routes in its `to_hash`" do
452
437
  config_hash = subject.to_hash
438
+ assert_equal subject.init_procs, config_hash[:init_procs]
453
439
  assert_equal subject.error_procs, config_hash[:error_procs]
440
+ assert_equal subject.router, config_hash[:router]
454
441
  assert_equal subject.routes, config_hash[:routes]
455
- template_source = subject.template_source
456
- assert_instance_of template_source.class, config_hash[:template_source]
457
- assert_equal template_source.path, config_hash[:template_source].path
458
442
  end
459
443
 
460
444
  should "call its init procs when validated" do
@@ -144,9 +144,9 @@ module Sanford::ServiceHandler
144
144
  should have_imeths :init, :init!, :run, :run!
145
145
 
146
146
  should "know its request, params and logger" do
147
- assert_equal @runner.request, subject.request
148
- assert_equal @runner.params, subject.params
149
- assert_equal @runner.logger, subject.logger
147
+ assert_equal @runner.request, subject.public_request
148
+ assert_equal @runner.params, subject.public_params
149
+ assert_equal @runner.logger, subject.public_logger
150
150
  end
151
151
 
152
152
  should "call `init!` and its before/after init callbacks using `init`" do
@@ -170,36 +170,21 @@ module Sanford::ServiceHandler
170
170
  should "have a custom inspect" do
171
171
  reference = '0x0%x' % (subject.object_id << 1)
172
172
  expected = "#<#{subject.class}:#{reference} " \
173
- "@request=#{subject.request.inspect}>"
173
+ "@request=#{@runner.request.inspect}>"
174
174
  assert_equal expected, subject.inspect
175
175
  end
176
176
 
177
- should "demeter its runner's halt" do
178
- code = Factory.integer
179
- result = subject.halt(code)
180
- assert_includes [ code ], @runner.halt_calls
181
- end
182
-
183
- should "use the runner template source to render the template by default" do
177
+ should "delegate its runner's `render` method" do
184
178
  path = Factory.file_path
185
179
  locals = { 'something' => Factory.string }
186
- result = subject.render(path, 'locals' => locals)
187
- assert_equal [ path, TestServiceHandler.to_s, locals ], result
188
- end
189
-
190
- should "default its locals to an empty hash using `render`" do
191
- path = Factory.file_path
192
- result = subject.render(path)
193
- assert_equal [ path, TestServiceHandler.to_s, {} ], result
180
+ result = subject.render(path, locals)
181
+ assert_equal [path, locals], @runner.render_calls.last
194
182
  end
195
183
 
196
- should "allow passing a source to its options using `render`" do
197
- path = Factory.file_path
198
- source_class = Class.new do
199
- def render(path, service_handler, locals); path; end
200
- end
201
- result = subject.render(path, 'source' => source_class.new)
202
- assert_equal path, result
184
+ should "delegate its runner's `halt` method" do
185
+ code = Factory.integer
186
+ result = subject.halt(code)
187
+ assert_equal [code], @runner.halt_calls.last
203
188
  end
204
189
 
205
190
  should "raise a not implemented error when `run!` by default" do
@@ -220,7 +205,7 @@ module Sanford::ServiceHandler
220
205
  # these methods are made public so they can be tested, they are being tested
221
206
  # because they are used by classes that mixin this, essentially they are
222
207
  # "public" to classes that use the mixin
223
- public :render, :halt, :request, :params, :logger
208
+ public :render, :halt
224
209
 
225
210
  before_init{ @first_before_init_call_order = next_call_order }
226
211
  before_init{ @second_before_init_call_order = next_call_order }
@@ -242,6 +227,18 @@ module Sanford::ServiceHandler
242
227
  @run_call_order = next_call_order
243
228
  end
244
229
 
230
+ def public_request
231
+ request
232
+ end
233
+
234
+ def public_params
235
+ params
236
+ end
237
+
238
+ def public_logger
239
+ logger
240
+ end
241
+
245
242
  private
246
243
 
247
244
  def next_call_order
@@ -251,26 +248,17 @@ module Sanford::ServiceHandler
251
248
  end
252
249
 
253
250
  class FakeRunner
254
- attr_accessor :request, :params, :logger, :template_source
255
- attr_reader :halt_calls
251
+ attr_accessor :request, :params, :logger
252
+ attr_reader :render_calls, :halt_calls
256
253
 
257
254
  def initialize
258
255
  @request = Factory.string
259
256
  @params = Factory.string
260
257
  @logger = Factory.string
261
- @template_source = FakeTemplateSource.new
262
258
  end
263
259
 
264
- def halt(*args)
265
- @halt_calls ||= []
266
- @halt_calls << args
267
- end
268
- end
269
-
270
- class FakeTemplateSource
271
- def render(path, service_handler, locals)
272
- [path.to_s, service_handler.class.to_s, locals]
273
- end
260
+ def render(*args); @render_calls ||= []; @render_calls << args; end
261
+ def halt(*args); @halt_calls ||= []; @halt_calls << args; end
274
262
  end
275
263
 
276
264
  end
@@ -2,6 +2,7 @@ require 'assert'
2
2
  require 'sanford/template_engine'
3
3
 
4
4
  require 'pathname'
5
+ require 'sanford/logger'
5
6
  require 'test/support/factory'
6
7
 
7
8
  class Sanford::TemplateEngine
@@ -17,7 +18,7 @@ class Sanford::TemplateEngine
17
18
  end
18
19
  subject{ @engine }
19
20
 
20
- should have_readers :source_path, :opts
21
+ should have_readers :source_path, :logger, :opts
21
22
  should have_imeths :render
22
23
 
23
24
  should "default its source path" do
@@ -29,6 +30,16 @@ class Sanford::TemplateEngine
29
30
  assert_equal Pathname.new(@source_path.to_s), engine.source_path
30
31
  end
31
32
 
33
+ should "default its logger" do
34
+ assert_instance_of Sanford::NullLogger, subject.logger
35
+ end
36
+
37
+ should "allow custom loggers" do
38
+ logger = 'a-logger'
39
+ engine = Sanford::TemplateEngine.new('logger' => logger)
40
+ assert_equal logger, engine.logger
41
+ end
42
+
32
43
  should "default the opts if none given" do
33
44
  exp_opts = {}
34
45
  assert_equal exp_opts, Sanford::TemplateEngine.new.opts
@@ -1,6 +1,7 @@
1
1
  require 'assert'
2
2
  require 'sanford/template_source'
3
3
 
4
+ require 'sanford/logger'
4
5
  require 'sanford/template_engine'
5
6
 
6
7
  class Sanford::TemplateSource
@@ -19,12 +20,13 @@ class Sanford::TemplateSource
19
20
  class InitTests < Assert::Context
20
21
  setup do
21
22
  @source_path = ROOT_PATH.join('test/support').to_s
22
- @source = Sanford::TemplateSource.new(@source_path)
23
+ @logger = 'a-logger'
24
+ @source = Sanford::TemplateSource.new(@source_path, @logger)
23
25
  end
24
26
  subject{ @source }
25
27
 
26
28
  should have_readers :path, :engines
27
- should have_imeths :engine, :render
29
+ should have_imeths :engine, :engine_for?, :render
28
30
 
29
31
  should "know its path" do
30
32
  assert_equal @source_path.to_s, subject.path
@@ -44,20 +46,34 @@ class Sanford::TemplateSource
44
46
  assert_kind_of @test_engine, subject.engines['test']
45
47
  end
46
48
 
47
- should "register with the source path as a default option" do
49
+ should "register with default options" do
48
50
  subject.engine 'test', @test_engine
49
- exp_opts = { 'source_path' => subject.path }
51
+ exp_opts = {
52
+ 'source_path' => subject.path,
53
+ 'logger' => @logger
54
+ }
50
55
  assert_equal exp_opts, subject.engines['test'].opts
51
56
 
57
+ source = Sanford::TemplateSource.new(@source_path)
58
+ source.engine 'test', @test_engine
59
+ assert_kind_of Sanford::NullLogger, source.engines['test'].opts['logger']
60
+
52
61
  subject.engine 'test', @test_engine, 'an' => 'opt'
53
62
  exp_opts = {
54
63
  'source_path' => subject.path,
55
- 'an' => 'opt'
64
+ 'logger' => @logger,
65
+ 'an' => 'opt'
56
66
  }
57
67
  assert_equal exp_opts, subject.engines['test'].opts
58
68
 
59
- subject.engine 'test', @test_engine, 'source_path' => 'something'
60
- exp_opts = { 'source_path' => 'something' }
69
+ subject.engine('test', @test_engine, {
70
+ 'source_path' => 'something',
71
+ 'logger' => 'another'
72
+ })
73
+ exp_opts = {
74
+ 'source_path' => 'something',
75
+ 'logger' => 'another'
76
+ }
61
77
  assert_equal exp_opts, subject.engines['test'].opts
62
78
  end
63
79
 
@@ -69,6 +85,13 @@ class Sanford::TemplateSource
69
85
  assert_kind_of Sanford::NullTemplateEngine, subject.engines['rb']
70
86
  end
71
87
 
88
+ should "know if it has an engine registered for a given template name" do
89
+ assert_false subject.engine_for?('test_template')
90
+
91
+ subject.engine 'test', @test_engine
92
+ assert_true subject.engine_for?('test_template')
93
+ end
94
+
72
95
  end
73
96
 
74
97
  class RenderTests < InitTests
@@ -7,12 +7,6 @@ class Sanford::TestRunner
7
7
  desc "Sanford::TestRunner"
8
8
  setup do
9
9
  @handler_class = TestServiceHandler
10
- @request = Sanford::Protocol::Request.new(Factory.string, {})
11
- @params = { :something => Factory.string }
12
- @logger = Factory.string
13
- @template_source = Factory.string
14
- @handler_flag = Factory.boolean
15
-
16
10
  @runner_class = Sanford::TestRunner
17
11
  end
18
12
  subject{ @runner_class }
@@ -26,12 +20,13 @@ class Sanford::TestRunner
26
20
  class InitTests < UnitTests
27
21
  desc "when init"
28
22
  setup do
23
+ @params = { Factory.string => Factory.integer }
29
24
  @args = {
30
- :request => @request,
31
- :params => @params,
32
- :logger => @logger,
33
- :template_source => @template_source,
34
- :flag => @handler_flag
25
+ :request => 'a-request',
26
+ :params => @params,
27
+ :logger => 'a-logger',
28
+ :router => 'a-router',
29
+ :template_source => 'a-source'
35
30
  }
36
31
  @runner = @runner_class.new(@handler_class, @args)
37
32
  end
@@ -40,31 +35,23 @@ class Sanford::TestRunner
40
35
  should have_readers :response
41
36
  should have_imeths :run
42
37
 
43
- should "know its attributes" do
44
- assert_equal @request, subject.request
45
- assert_equal @params, subject.params
46
- assert_equal @logger, subject.logger
47
- assert_equal @template_source, subject.template_source
48
- end
49
-
50
- should "write extra args to its service handler" do
51
- assert_equal @handler_flag, subject.handler.flag
38
+ should "raise an invalid error when not passed a service handler" do
39
+ assert_raises(Sanford::InvalidServiceHandlerError) do
40
+ @runner_class.new(Class.new)
41
+ end
52
42
  end
53
43
 
54
- should "not alter the args passed to it" do
55
- assert_equal @request, @args[:request]
56
- assert_equal @params, @args[:params]
57
- assert_equal @logger, @args[:logger]
58
- assert_equal @template_source, @args[:template_source]
59
- assert_equal @handler_flag, @args[:flag]
44
+ should "super its standard attributes" do
45
+ assert_equal 'a-request', subject.request
46
+ assert_equal @params, subject.params
47
+ assert_equal 'a-logger', subject.logger
48
+ assert_equal 'a-router', subject.router
49
+ assert_equal 'a-source', subject.template_source
60
50
  end
61
51
 
62
- should "default its request, logger, params and template source" do
63
- test_runner = @runner_class.new(@handler_class)
64
- assert_nil test_runner.request
65
- assert_equal({}, test_runner.params)
66
- assert_instance_of Sanford::NullLogger, test_runner.logger
67
- assert_instance_of Sanford::NullTemplateSource, test_runner.template_source
52
+ should "write any non-standard args on the handler" do
53
+ runner = @runner_class.new(@handler_class, :custom_value => 42)
54
+ assert_equal 42, runner.handler.custom_value
68
55
  end
69
56
 
70
57
  should "not have called its service handlers before callbacks" do
@@ -79,12 +66,6 @@ class Sanford::TestRunner
79
66
  assert_nil subject.response
80
67
  end
81
68
 
82
- should "raise an invalid error when not passed a service handler" do
83
- assert_raises(Sanford::InvalidServiceHandlerError) do
84
- @runner_class.new(Class.new)
85
- end
86
- end
87
-
88
69
  end
89
70
 
90
71
  class RunTests < InitTests
@@ -169,7 +150,7 @@ class Sanford::TestRunner
169
150
 
170
151
  attr_reader :before_called, :after_called
171
152
  attr_reader :init_called, :run_called
172
- attr_accessor :flag, :response
153
+ attr_accessor :custom_value, :response
173
154
 
174
155
  before{ @before_called = true }
175
156
  after{ @after_called = true }
metadata CHANGED
@@ -1,13 +1,13 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: sanford
3
3
  version: !ruby/object:Gem::Version
4
- hash: 49
4
+ hash: 47
5
5
  prerelease:
6
6
  segments:
7
7
  - 0
8
- - 11
9
- - 1
10
- version: 0.11.1
8
+ - 12
9
+ - 0
10
+ version: 0.12.0
11
11
  platform: ruby
12
12
  authors:
13
13
  - Collin Redding
@@ -16,7 +16,7 @@ autorequire:
16
16
  bindir: bin
17
17
  cert_chain: []
18
18
 
19
- date: 2014-06-30 00:00:00 Z
19
+ date: 2014-12-05 00:00:00 Z
20
20
  dependencies:
21
21
  - !ruby/object:Gem::Dependency
22
22
  requirement: &id001 !ruby/object:Gem::Requirement
@@ -29,9 +29,9 @@ dependencies:
29
29
  - 0
30
30
  - 5
31
31
  version: "0.5"
32
- version_requirements: *id001
33
32
  type: :runtime
34
33
  name: dat-tcp
34
+ version_requirements: *id001
35
35
  prerelease: false
36
36
  - !ruby/object:Gem::Dependency
37
37
  requirement: &id002 !ruby/object:Gem::Requirement
@@ -44,9 +44,9 @@ dependencies:
44
44
  - 1
45
45
  - 1
46
46
  version: "1.1"
47
- version_requirements: *id002
48
47
  type: :runtime
49
48
  name: ns-options
49
+ version_requirements: *id002
50
50
  prerelease: false
51
51
  - !ruby/object:Gem::Dependency
52
52
  requirement: &id003 !ruby/object:Gem::Requirement
@@ -54,14 +54,14 @@ dependencies:
54
54
  requirements:
55
55
  - - ~>
56
56
  - !ruby/object:Gem::Version
57
- hash: 25
57
+ hash: 31
58
58
  segments:
59
59
  - 0
60
- - 9
61
- version: "0.9"
62
- version_requirements: *id003
60
+ - 10
61
+ version: "0.10"
63
62
  type: :runtime
64
63
  name: sanford-protocol
64
+ version_requirements: *id003
65
65
  prerelease: false
66
66
  - !ruby/object:Gem::Dependency
67
67
  requirement: &id004 !ruby/object:Gem::Requirement
@@ -69,14 +69,14 @@ dependencies:
69
69
  requirements:
70
70
  - - ~>
71
71
  - !ruby/object:Gem::Version
72
- hash: 21
72
+ hash: 27
73
73
  segments:
74
74
  - 2
75
- - 11
76
- version: "2.11"
77
- version_requirements: *id004
75
+ - 12
76
+ version: "2.12"
78
77
  type: :development
79
78
  name: assert
79
+ version_requirements: *id004
80
80
  prerelease: false
81
81
  description: Sanford TCP protocol server for hosting services
82
82
  email:
@@ -184,7 +184,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
184
184
  requirements: []
185
185
 
186
186
  rubyforge_project:
187
- rubygems_version: 1.8.29
187
+ rubygems_version: 1.8.25
188
188
  signing_key:
189
189
  specification_version: 3
190
190
  summary: Sanford TCP protocol server for hosting services