halcyon 0.4.0 → 0.5.0

Sign up to get free protection for your applications and to get access to all the features.
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