halcyon 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.
- data/AUTHORS +1 -0
- data/LICENSE +20 -0
- data/README +107 -0
- data/Rakefile +8 -6
- data/bin/halcyon +3 -204
- data/lib/halcyon.rb +55 -42
- data/lib/halcyon/application.rb +247 -0
- data/lib/halcyon/application/router.rb +86 -0
- data/lib/halcyon/client.rb +187 -35
- data/lib/halcyon/client/ssl.rb +38 -0
- data/lib/halcyon/controller.rb +154 -0
- data/lib/halcyon/exceptions.rb +67 -59
- data/lib/halcyon/logging.rb +31 -0
- data/lib/halcyon/logging/analogger.rb +31 -0
- data/lib/halcyon/logging/helpers.rb +37 -0
- data/lib/halcyon/logging/log4r.rb +25 -0
- data/lib/halcyon/logging/logger.rb +20 -0
- data/lib/halcyon/logging/logging.rb +19 -0
- data/lib/halcyon/runner.rb +141 -0
- data/lib/halcyon/runner/commands.rb +141 -0
- data/lib/halcyon/runner/helpers.rb +9 -0
- data/lib/halcyon/runner/helpers/command_helper.rb +71 -0
- data/spec/halcyon/application_spec.rb +70 -0
- data/spec/halcyon/client_spec.rb +63 -0
- data/spec/halcyon/controller_spec.rb +68 -0
- data/spec/halcyon/halcyon_spec.rb +63 -0
- data/spec/halcyon/logging_spec.rb +31 -0
- data/spec/halcyon/router_spec.rb +37 -12
- data/spec/halcyon/runner_spec.rb +54 -0
- data/spec/spec_helper.rb +75 -9
- data/support/generators/halcyon/USAGE +0 -0
- data/support/generators/halcyon/halcyon_generator.rb +52 -0
- data/support/generators/halcyon/templates/README +26 -0
- data/support/generators/halcyon/templates/Rakefile +32 -0
- data/support/generators/halcyon/templates/app/application.rb +43 -0
- data/support/generators/halcyon/templates/config/config.yml +36 -0
- data/support/generators/halcyon/templates/config/init/environment.rb +11 -0
- data/support/generators/halcyon/templates/config/init/hooks.rb +39 -0
- data/support/generators/halcyon/templates/config/init/requires.rb +10 -0
- data/support/generators/halcyon/templates/config/init/routes.rb +50 -0
- data/support/generators/halcyon/templates/lib/client.rb +77 -0
- data/support/generators/halcyon/templates/runner.ru +8 -0
- data/support/generators/halcyon_flat/USAGE +0 -0
- data/support/generators/halcyon_flat/halcyon_flat_generator.rb +52 -0
- data/support/generators/halcyon_flat/templates/README +26 -0
- data/support/generators/halcyon_flat/templates/Rakefile +32 -0
- data/support/generators/halcyon_flat/templates/app.rb +49 -0
- data/support/generators/halcyon_flat/templates/lib/client.rb +17 -0
- data/support/generators/halcyon_flat/templates/runner.ru +8 -0
- metadata +73 -20
- data/lib/halcyon/client/base.rb +0 -261
- data/lib/halcyon/client/exceptions.rb +0 -41
- data/lib/halcyon/client/router.rb +0 -106
- data/lib/halcyon/server.rb +0 -62
- data/lib/halcyon/server/auth/basic.rb +0 -107
- data/lib/halcyon/server/base.rb +0 -774
- data/lib/halcyon/server/exceptions.rb +0 -41
- data/lib/halcyon/server/router.rb +0 -103
- data/spec/halcyon/error_spec.rb +0 -55
- data/spec/halcyon/server_spec.rb +0 -105
@@ -1,41 +0,0 @@
|
|
1
|
-
#--
|
2
|
-
# Created by Matt Todd on 2007-12-14.
|
3
|
-
# Copyright (c) 2007. All rights reserved.
|
4
|
-
#++
|
5
|
-
|
6
|
-
#--
|
7
|
-
# module
|
8
|
-
#++
|
9
|
-
|
10
|
-
module Halcyon
|
11
|
-
class Server
|
12
|
-
class Base
|
13
|
-
module Exceptions #:nodoc:
|
14
|
-
|
15
|
-
#--
|
16
|
-
# Exception classes
|
17
|
-
#++
|
18
|
-
|
19
|
-
Halcyon::Exceptions::HTTP_ERROR_CODES.to_a.each do |http_error|
|
20
|
-
status, body = http_error
|
21
|
-
class_eval(
|
22
|
-
"class #{body.gsub(/( |\-)/,'')} < Halcyon::Exceptions::Base\n"+
|
23
|
-
" def initialize(s=#{status}, e='#{body}')\n"+
|
24
|
-
" super\n"+
|
25
|
-
" end\n"+
|
26
|
-
"end"
|
27
|
-
);
|
28
|
-
end
|
29
|
-
|
30
|
-
#--
|
31
|
-
# Exception Lookup
|
32
|
-
#++
|
33
|
-
|
34
|
-
def self.lookup(status)
|
35
|
-
self.const_get(Halcyon::Exceptions::HTTP_ERROR_CODES[status].gsub(/( |\-)/,''))
|
36
|
-
end
|
37
|
-
|
38
|
-
end
|
39
|
-
end
|
40
|
-
end
|
41
|
-
end
|
@@ -1,103 +0,0 @@
|
|
1
|
-
#--
|
2
|
-
# Created by Matt Todd on 2007-12-14.
|
3
|
-
# Copyright (c) 2007. All rights reserved.
|
4
|
-
#++
|
5
|
-
|
6
|
-
#--
|
7
|
-
# dependencies
|
8
|
-
#++
|
9
|
-
|
10
|
-
begin
|
11
|
-
%w(rubygems merb/core_ext merb/router uri).each {|dep|require dep}
|
12
|
-
rescue LoadError => e
|
13
|
-
abort "Merb must be installed for Routing to function. Please install Merb."
|
14
|
-
end
|
15
|
-
|
16
|
-
#--
|
17
|
-
# module
|
18
|
-
#++
|
19
|
-
|
20
|
-
module Halcyon
|
21
|
-
class Server
|
22
|
-
|
23
|
-
# = Routing
|
24
|
-
#
|
25
|
-
# Handles routing.
|
26
|
-
#
|
27
|
-
# == Usage
|
28
|
-
#
|
29
|
-
# class Xy < Halcyon::Server::Base
|
30
|
-
# route do |r|
|
31
|
-
# r.match('/path/to/match').to(:action => 'do_stuff')
|
32
|
-
# {:action => 'not_found'} # the default route
|
33
|
-
# end
|
34
|
-
# def do_stuff(params)
|
35
|
-
# [200, {}, 'OK']
|
36
|
-
# end
|
37
|
-
# end
|
38
|
-
#
|
39
|
-
# == Default Routes
|
40
|
-
#
|
41
|
-
# Supplying a default route if none of the others match is good practice,
|
42
|
-
# but is unnecessary as the predefined route is always, automatically,
|
43
|
-
# going to contain a redirection to the +not_found+ method which already
|
44
|
-
# exists in Halcyon::Server::Base. This method is freely overwritable, and
|
45
|
-
# is recommended for those that wish to handle unroutable requests
|
46
|
-
# themselves.
|
47
|
-
#
|
48
|
-
# In order to set a different default route, simply end the call to +route+
|
49
|
-
# with a hash containing the action (and optionally the module) to run.
|
50
|
-
#
|
51
|
-
# == The Hard Work
|
52
|
-
#
|
53
|
-
# The mechanics of the router are solely from the efforts of the Merb
|
54
|
-
# community. This functionality is completely ripped right out of Merb
|
55
|
-
# and makes it functional. All credit to them, and be sure to check out
|
56
|
-
# their great framework: if Halcyon isn't quite what you need, maybe Merb
|
57
|
-
# is.
|
58
|
-
#
|
59
|
-
# http://merbivore.com/
|
60
|
-
class Router < Merb::Router
|
61
|
-
|
62
|
-
# Retrieves the last value from the +route+ call in Halcyon::Server::Base
|
63
|
-
# and, if it's a Hash, sets it to +@@default_route+ to designate the
|
64
|
-
# failover route. If +route+ is not a Hash, though, the internal default
|
65
|
-
# should be used instead (as the last returned value is probably a Route
|
66
|
-
# object returned by the +r.match().to()+ call).
|
67
|
-
#
|
68
|
-
# Used exclusively internally.
|
69
|
-
def self.default_to route
|
70
|
-
@@default_route = route.is_a?(Hash) ? route : {:action => 'not_found'}
|
71
|
-
end
|
72
|
-
|
73
|
-
# Called internally by the Halcyon::Server::Base#call method to match
|
74
|
-
# the current request against the currently defined routes. Returns the
|
75
|
-
# params list defined in the +to+ routing definition, opting for the
|
76
|
-
# default route if no match is made.
|
77
|
-
def self.route(env)
|
78
|
-
# pull out the path requested (WEBrick keeps the host and port and protocol in REQUEST_URI)
|
79
|
-
# PATH_INFO is failover if REQUEST_URI is blank (like what Rack::MockRequest does)
|
80
|
-
uri = URI.parse(env['REQUEST_URI'] || env['PATH_INFO']).path
|
81
|
-
|
82
|
-
# prepare request
|
83
|
-
path = (uri ? uri.split('?').first : '').sub(/\/+/, '/')
|
84
|
-
path = path[0..-2] if (path[-1] == ?/) && path.size > 1
|
85
|
-
req = Struct.new(:path, :method).new(path, env['REQUEST_METHOD'].downcase.to_sym)
|
86
|
-
|
87
|
-
# perform match
|
88
|
-
route = self.match(req, {})
|
89
|
-
|
90
|
-
# make sure a route is returned even if no match is found
|
91
|
-
if route[0].nil?
|
92
|
-
#return default route
|
93
|
-
env['halcyon.logger'].debug "No route found. Using default." if env['halcyon.logger'].is_a? Logger
|
94
|
-
@@default_route
|
95
|
-
else
|
96
|
-
# params (including action and module if set) for the matching route
|
97
|
-
route[1]
|
98
|
-
end
|
99
|
-
end
|
100
|
-
|
101
|
-
end
|
102
|
-
end
|
103
|
-
end
|
data/spec/halcyon/error_spec.rb
DELETED
@@ -1,55 +0,0 @@
|
|
1
|
-
describe "Halcyon::Server Errors" do
|
2
|
-
|
3
|
-
before do
|
4
|
-
@app = Specr.new :port => 4000
|
5
|
-
end
|
6
|
-
|
7
|
-
it "should provide shorthand methods for errors which should throw an appropriate exception" do
|
8
|
-
begin
|
9
|
-
@app.not_found
|
10
|
-
rescue Halcyon::Exceptions::Base => e
|
11
|
-
e.status.should == 404
|
12
|
-
e.error.should == 'Not Found'
|
13
|
-
end
|
14
|
-
|
15
|
-
begin
|
16
|
-
@app.not_found('Missing')
|
17
|
-
rescue Halcyon::Exceptions::Base => e
|
18
|
-
e.status.should == 404
|
19
|
-
e.error.should == 'Missing'
|
20
|
-
end
|
21
|
-
end
|
22
|
-
|
23
|
-
it "supports numerous standard HTTP request error exceptions with lookup by status code" do
|
24
|
-
begin
|
25
|
-
Halcyon::Server::Base::Exceptions::NotFound.new
|
26
|
-
rescue Halcyon::Exceptions::Base => e
|
27
|
-
e.status.should == 404
|
28
|
-
e.error.should == 'Not Found'
|
29
|
-
end
|
30
|
-
|
31
|
-
Halcyon::Exceptions::HTTP_ERROR_CODES.each do |code, error|
|
32
|
-
begin
|
33
|
-
Halcyon::Server::Base::Exceptions.const_get(error.gsub(/( |\-)/,'')).new
|
34
|
-
rescue Halcyon::Exceptions::Base => e
|
35
|
-
e.status.should == code
|
36
|
-
e.error.should == error
|
37
|
-
end
|
38
|
-
begin
|
39
|
-
Halcyon::Server::Base::Exceptions.lookup(code).new
|
40
|
-
rescue Halcyon::Exceptions::Base => e
|
41
|
-
e.status.should == code
|
42
|
-
e.error.should == error
|
43
|
-
end
|
44
|
-
end
|
45
|
-
end
|
46
|
-
|
47
|
-
it "should have a short inheritence chain to make catching generically simple" do
|
48
|
-
begin
|
49
|
-
Halcyon::Server::Base::Exceptions::NotFound.new
|
50
|
-
rescue Halcon::Exceptions::Base => e
|
51
|
-
e.class.to_s.should == 'NotFound'
|
52
|
-
end
|
53
|
-
end
|
54
|
-
|
55
|
-
end
|
data/spec/halcyon/server_spec.rb
DELETED
@@ -1,105 +0,0 @@
|
|
1
|
-
describe "Halcyon::Server" do
|
2
|
-
|
3
|
-
before do
|
4
|
-
@app = Specr.new :port => 4000
|
5
|
-
end
|
6
|
-
|
7
|
-
it "should dispatch methods according to their respective routes" do
|
8
|
-
Rack::MockRequest.new(@app).get("/hello/Matt")
|
9
|
-
last_line = File.new(@app.instance_variable_get("@config")[:log_file]).readlines.last
|
10
|
-
last_line.should =~ /INFO \[\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2}\] \(\d+\) Specr#test :: \[200\] .* => greeter \(.+\)/
|
11
|
-
end
|
12
|
-
|
13
|
-
it "should provide various shorthand methods for simple responses but take custom response values" do
|
14
|
-
response = {:status => 200, :body => 'OK'}
|
15
|
-
@app.ok.should == response
|
16
|
-
@app.success.should == response
|
17
|
-
@app.standard_response.should == response
|
18
|
-
|
19
|
-
@app.ok('').should == {:status => 200, :body => ''}
|
20
|
-
@app.ok(['OK', 'Sure Thang', 'Correcto']).should == {:status => 200, :body => ['OK', 'Sure Thang', 'Correcto']}
|
21
|
-
end
|
22
|
-
|
23
|
-
it "should handle requests and respond with JSON" do
|
24
|
-
body = JSON.parse(Rack::MockRequest.new(@app).get("/").body)
|
25
|
-
body['status'].should == 200
|
26
|
-
body['body'].should == "Found"
|
27
|
-
end
|
28
|
-
|
29
|
-
it "should handle requests with param values in the URL" do
|
30
|
-
body = JSON.parse(Rack::MockRequest.new(@app).get("/hello/Matt").body)
|
31
|
-
body['status'].should == 200
|
32
|
-
body['body'].should == "Hello Matt"
|
33
|
-
end
|
34
|
-
|
35
|
-
it "should route unmatchable requests to the default route and return JSON with appropriate status" do
|
36
|
-
body = JSON.parse(Rack::MockRequest.new(@app).get("/garbage/request/url").body)
|
37
|
-
body['status'].should == 404
|
38
|
-
body['body'].should == "Not Found"
|
39
|
-
end
|
40
|
-
|
41
|
-
it "should log activity" do
|
42
|
-
prev_line = File.new(@app.instance_variable_get("@config")[:log_file]).readlines.last
|
43
|
-
Rack::MockRequest.new(@app).get("/url/that/will/not/be/found/#{rand}")
|
44
|
-
last_line = File.new(@app.instance_variable_get("@config")[:log_file]).readlines.last
|
45
|
-
last_line.should =~ /INFO \[\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2}\] \(\d+\) Specr#test :: \[404\] .* => not_found \(.+\)/
|
46
|
-
prev_line.should.not == last_line
|
47
|
-
end
|
48
|
-
|
49
|
-
it "should create a PID file while running with the correct process ID" do
|
50
|
-
pid_file = @app.instance_variable_get("@config")[:pid_file]
|
51
|
-
File.exist?(pid_file).should.be.true?
|
52
|
-
File.open(pid_file){|file|file.read.should == "#{$$}\n"}
|
53
|
-
end
|
54
|
-
|
55
|
-
it "should parse URI query params correctly" do
|
56
|
-
Rack::MockRequest.new(@app).get("/?query=value&lang=en-US")
|
57
|
-
@app.query_params.should == {:query => 'value', :lang => 'en-US'}
|
58
|
-
end
|
59
|
-
|
60
|
-
it "should parse the URI correctly" do
|
61
|
-
Rack::MockRequest.new(@app).get("http://localhost:4000/slaughterhouse/5")
|
62
|
-
@app.uri.should == '/slaughterhouse/5'
|
63
|
-
|
64
|
-
Rack::MockRequest.new(@app).get("/slaughterhouse/5")
|
65
|
-
@app.uri.should == '/slaughterhouse/5'
|
66
|
-
|
67
|
-
Rack::MockRequest.new(@app).get("")
|
68
|
-
@app.uri.should == '/'
|
69
|
-
end
|
70
|
-
|
71
|
-
it "should provide a quick way to find out what method the request was performed using" do
|
72
|
-
Rack::MockRequest.new(@app).get("/#{rand}")
|
73
|
-
@app.method.should == :get
|
74
|
-
|
75
|
-
Rack::MockRequest.new(@app).post("/#{rand}")
|
76
|
-
@app.method.should == :post
|
77
|
-
|
78
|
-
Rack::MockRequest.new(@app).put("/#{rand}")
|
79
|
-
@app.method.should == :put
|
80
|
-
|
81
|
-
Rack::MockRequest.new(@app).delete("/#{rand}")
|
82
|
-
@app.method.should == :delete
|
83
|
-
end
|
84
|
-
|
85
|
-
it "should provide convenient access to GET and POST data" do
|
86
|
-
Rack::MockRequest.new(@app).get("/#{rand}?foo=bar")
|
87
|
-
@app.get[:foo].should == 'bar'
|
88
|
-
|
89
|
-
Rack::MockRequest.new(@app).post("/#{rand}", :input => {:foo => 'bar'}.to_params)
|
90
|
-
@app.post[:foo].should == 'bar'
|
91
|
-
end
|
92
|
-
|
93
|
-
it "should deny all unacceptable requests" do
|
94
|
-
conf = @app.instance_variable_get("@config")
|
95
|
-
conf[:acceptable_requests] = Halcyon::Server::ACCEPTABLE_REQUESTS
|
96
|
-
|
97
|
-
Rack::MockRequest.new(@app).get("/#{rand}")
|
98
|
-
@app.acceptable_request! rescue Halcyon::Exceptions::Base
|
99
|
-
end
|
100
|
-
|
101
|
-
it "should record the correct environment details" do
|
102
|
-
@app.instance_eval { @config[:root].should == Dir.pwd }
|
103
|
-
end
|
104
|
-
|
105
|
-
end
|