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.
Files changed (60) hide show
  1. data/AUTHORS +1 -0
  2. data/LICENSE +20 -0
  3. data/README +107 -0
  4. data/Rakefile +8 -6
  5. data/bin/halcyon +3 -204
  6. data/lib/halcyon.rb +55 -42
  7. data/lib/halcyon/application.rb +247 -0
  8. data/lib/halcyon/application/router.rb +86 -0
  9. data/lib/halcyon/client.rb +187 -35
  10. data/lib/halcyon/client/ssl.rb +38 -0
  11. data/lib/halcyon/controller.rb +154 -0
  12. data/lib/halcyon/exceptions.rb +67 -59
  13. data/lib/halcyon/logging.rb +31 -0
  14. data/lib/halcyon/logging/analogger.rb +31 -0
  15. data/lib/halcyon/logging/helpers.rb +37 -0
  16. data/lib/halcyon/logging/log4r.rb +25 -0
  17. data/lib/halcyon/logging/logger.rb +20 -0
  18. data/lib/halcyon/logging/logging.rb +19 -0
  19. data/lib/halcyon/runner.rb +141 -0
  20. data/lib/halcyon/runner/commands.rb +141 -0
  21. data/lib/halcyon/runner/helpers.rb +9 -0
  22. data/lib/halcyon/runner/helpers/command_helper.rb +71 -0
  23. data/spec/halcyon/application_spec.rb +70 -0
  24. data/spec/halcyon/client_spec.rb +63 -0
  25. data/spec/halcyon/controller_spec.rb +68 -0
  26. data/spec/halcyon/halcyon_spec.rb +63 -0
  27. data/spec/halcyon/logging_spec.rb +31 -0
  28. data/spec/halcyon/router_spec.rb +37 -12
  29. data/spec/halcyon/runner_spec.rb +54 -0
  30. data/spec/spec_helper.rb +75 -9
  31. data/support/generators/halcyon/USAGE +0 -0
  32. data/support/generators/halcyon/halcyon_generator.rb +52 -0
  33. data/support/generators/halcyon/templates/README +26 -0
  34. data/support/generators/halcyon/templates/Rakefile +32 -0
  35. data/support/generators/halcyon/templates/app/application.rb +43 -0
  36. data/support/generators/halcyon/templates/config/config.yml +36 -0
  37. data/support/generators/halcyon/templates/config/init/environment.rb +11 -0
  38. data/support/generators/halcyon/templates/config/init/hooks.rb +39 -0
  39. data/support/generators/halcyon/templates/config/init/requires.rb +10 -0
  40. data/support/generators/halcyon/templates/config/init/routes.rb +50 -0
  41. data/support/generators/halcyon/templates/lib/client.rb +77 -0
  42. data/support/generators/halcyon/templates/runner.ru +8 -0
  43. data/support/generators/halcyon_flat/USAGE +0 -0
  44. data/support/generators/halcyon_flat/halcyon_flat_generator.rb +52 -0
  45. data/support/generators/halcyon_flat/templates/README +26 -0
  46. data/support/generators/halcyon_flat/templates/Rakefile +32 -0
  47. data/support/generators/halcyon_flat/templates/app.rb +49 -0
  48. data/support/generators/halcyon_flat/templates/lib/client.rb +17 -0
  49. data/support/generators/halcyon_flat/templates/runner.ru +8 -0
  50. metadata +73 -20
  51. data/lib/halcyon/client/base.rb +0 -261
  52. data/lib/halcyon/client/exceptions.rb +0 -41
  53. data/lib/halcyon/client/router.rb +0 -106
  54. data/lib/halcyon/server.rb +0 -62
  55. data/lib/halcyon/server/auth/basic.rb +0 -107
  56. data/lib/halcyon/server/base.rb +0 -774
  57. data/lib/halcyon/server/exceptions.rb +0 -41
  58. data/lib/halcyon/server/router.rb +0 -103
  59. data/spec/halcyon/error_spec.rb +0 -55
  60. 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
@@ -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
@@ -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