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
data/AUTHORS ADDED
@@ -0,0 +1 @@
1
+ * Matt Todd <chiology@gmail.com>
data/LICENSE ADDED
@@ -0,0 +1,20 @@
1
+ Copyright (c) 2007 Matt Todd <http://purl.org/net/maraby>.
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining a copy
4
+ of this software and associated documentation files (the "Software"), to
5
+ deal in the Software without restriction, including without limitation the
6
+ rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
7
+ sell copies of the Software, and to permit persons to whom the Software is
8
+ furnished to do so, subject to the following conditions:
9
+
10
+ The above copyright notice and this permission notice shall be included in
11
+ all copies or substantial portions of the Software.
12
+
13
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
16
+ THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
17
+ IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
18
+ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
19
+
20
+ http://www.opensource.org/licenses/mit-license.php
data/README ADDED
@@ -0,0 +1,107 @@
1
+ = Halcyon
2
+ == JSON Application Framework
3
+
4
+ A JSON Web Application Framework for developing lightweight applications
5
+ interfaced via JSON-encoded HTTP requests. This is ideal for back end
6
+ applications serving functionality for other applications.
7
+
8
+ Halcyon consists of two parts, the server application and the client. The
9
+ server application is similar to a Merb or Rails app, without the need for
10
+ implementing views, and the client is used to facilitate talking to the
11
+ application from other applications.
12
+
13
+
14
+ == On Rack
15
+
16
+ Halcyon is a Rack application, meaning that it can sit right along with any
17
+ other Rack app, such as a Merb or Rails app, and can be manipulated by any
18
+ kind of Rack middleware/filter. This means that interfacing with Halcyon in
19
+ unconventional ways is trivial since the Rack specification makes communicating
20
+ with Rack apps dead simple.
21
+
22
+
23
+ == Development
24
+
25
+ Halcyon is actively being developed by a very small community of developers and
26
+ contributors. Halcyon has seen a good deal of paradigm shift up until the 0.5.0
27
+ release, but with that release its internal API has stabilized and should
28
+ remain fairly backwards compatible from here on.
29
+
30
+ The changes made on the way to the 0.5.0 codebase were to remove all of the
31
+ server-like code to make Halcyon more application-centric and also to model
32
+ application development and structure to be more Rails- or Merb-like, though
33
+ this was just the natural evolution of Halcyon's design.
34
+
35
+
36
+ == Installation
37
+
38
+ A Gem of Halcyon is available. You can install it with:
39
+
40
+ $ sudo gem install halcyon
41
+
42
+ The latest development release can be installed with RubyGems:
43
+
44
+ $ sudo gem install halcyon --source http://halcyon.rubyforge.org/latest/
45
+
46
+ Alternatively, you can install the latest development efforts from the git
47
+ repository, located at http://github.com/mtodd/halcyon:
48
+
49
+ $ git clone git://github.com/mtodd/halcyon.git
50
+ $ cd halcyon; rake install
51
+
52
+ Don't forget to install the JSON gem for improved performance:
53
+
54
+ $ sudo gem install json
55
+
56
+ More in depth documentation can be found at
57
+ http://halcyon.rubyforge.org/docs/installation.html.
58
+
59
+
60
+ == Usage
61
+
62
+ After installing a Halcyon app, you can generate a new app, similar to the
63
+ <tt>rails</tt> or <tt>merb-gen app</tt> commands, with this:
64
+
65
+ $ halcyon init app_name
66
+
67
+ This will create a directory and generate a skeletal Halcyon application. You
68
+ can run this application without changing anything; here's how:
69
+
70
+ $ cd app_name
71
+ $ halcyon start -p 4647
72
+
73
+ A great tutorial to dive right into using Halcyon and writing apps is located
74
+ at http://halcyon.rubyforge.org/docs/tutorial.html. This will step you through
75
+ what to do, what to expect, and what it means.
76
+
77
+
78
+ == Contact
79
+
80
+ Please mail bugs, suggestions and patches to <mailto:chiology@gmail.com>.
81
+
82
+ You are also welcome to join the #halcyon channel on irc.freenode.net.
83
+
84
+ Our website is up so stop by and check out what's going down. Our address is
85
+ http://halcyon.rubyforge.org/. On there you will find information about our
86
+ mailing list as well, so do stop by.
87
+
88
+
89
+ == Thanks To
90
+
91
+ * Bill Marquette, typo correction, reviewing examples
92
+ * Elliott Cable, missing dependency, Thin testing
93
+ * ramstedt, Mongrel on JRuby port numericality issue (#14)
94
+ * Ben Simpson, PHP Client bug fixes
95
+ * Eivind Uggedal, dependencies for Router support of resources
96
+
97
+
98
+ == Links
99
+
100
+ Halcyon:: <http://halcyon.rubyforge.org/>
101
+ Aurora:: <http://aurora.rubyforge.org/>
102
+
103
+ Rack:: <http://rack.rubyforge.org/>
104
+ Merb:: <http://merbivore.com/>
105
+ JSON:: <http://json.rubyforge.org/>
106
+
107
+ Matt Todd:: <http://maraby.org/>
data/Rakefile CHANGED
@@ -4,7 +4,7 @@ $:.unshift(File.expand_path(File.join(File.dirname(__FILE__), "lib")))
4
4
 
5
5
  include FileUtils
6
6
 
7
- require 'lib/halcyon'
7
+ require 'halcyon'
8
8
 
9
9
  project = {
10
10
  :name => "halcyon",
@@ -21,13 +21,14 @@ project = {
21
21
  --op rdoc
22
22
  --line-numbers
23
23
  --inline-source
24
- --title "Halcyon\ Documentation"
24
+ --title "Halcyon\ API"
25
25
  --exclude "^(_darcs|spec|pkg|.svn)/"
26
26
  ],
27
27
  :dependencies => {
28
- 'json_pure' => '>=1.1.1',
29
- 'rack' => '>=0.2.0',
30
- 'merb' => '>=0.4.1'
28
+ 'json_pure' => '>=1.1.2',
29
+ 'rack' => '>=0.3.0',
30
+ 'merb' => '>=0.9.2',
31
+ 'rubigen' => '>=1.2.4'
31
32
  },
32
33
  :requirements => 'install the json gem to get faster JSON parsing',
33
34
  :ruby_version_required => '>=1.8.6'
@@ -37,6 +38,7 @@ BASEDIR = File.expand_path(File.dirname(__FILE__))
37
38
 
38
39
  spec = Gem::Specification.new do |s|
39
40
  s.name = project[:name]
41
+ s.rubyforge_project = project[:name]
40
42
  s.version = project[:version]
41
43
  s.platform = Gem::Platform::RUBY
42
44
  s.has_rdoc = true
@@ -55,7 +57,7 @@ spec = Gem::Specification.new do |s|
55
57
  }
56
58
  s.requirements << project[:requirements]
57
59
  s.required_ruby_version = project[:ruby_version_required]
58
- s.files = (project[:rdoc_files] + %w[Rakefile] + Dir["{spec,lib}/**/*"]).uniq
60
+ s.files = (project[:rdoc_files] + %w[Rakefile README LICENSE AUTHORS] + Dir["{spec,lib,example,support}/**/*"]).uniq
59
61
  end
60
62
 
61
63
  Rake::GemPackageTask.new(spec) do |p|
data/bin/halcyon CHANGED
@@ -1,205 +1,4 @@
1
- #!/usr/bin/env ruby -wKU
2
- #--
3
- # Created by Matt Todd on 2007-10-25.
4
- # Copyright (c) 2007. All rights reserved.
5
- #++
1
+ #!/usr/bin/env ruby
6
2
 
7
- # Blatantly stolen from Chris Neukirchen's rackup utility for running Rack
8
- # apps. (Forgive me, it just made too much sense to use your Rack bootstrap
9
- # code for my Rack bootstrap.)
10
-
11
- #--
12
- # dependencies
13
- #++
14
-
15
- %w(rubygems halcyon/server optparse).each{|dep|require dep}
16
-
17
- #--
18
- # default options
19
- #++
20
-
21
- $debug = false
22
- $test = false
23
- options = Halcyon::Server::DEFAULT_OPTIONS
24
-
25
- #--
26
- # parse options
27
- #++
28
-
29
- opts = OptionParser.new("", 24, ' ') do |opts|
30
- opts.banner << "Halcyon, JSON Server Framework\n"
31
- opts.banner << "http://halcyon.rubyforge.org/\n"
32
- opts.banner << "\n"
33
- opts.banner << "Usage: halcyon [options] appname\n"
34
- opts.banner << "\n"
35
- opts.banner << "Put -c or --config first otherwise it will overwrite higher precedence options."
36
-
37
- opts.separator ""
38
- opts.separator "Options:"
39
-
40
- opts.on("-d", "--debug", "set debugging flag (set $debug to true)") { $debug = true }
41
- opts.on("-D", "--Debug", "enable verbose debugging (set $debug and $DEBUG to true)") { $debug = true; $DEBUG = true }
42
- opts.on("-w", "--warn", "turn warnings on for your script") { $-w = true }
43
-
44
- opts.on("-I", "--include PATH", "specify $LOAD_PATH (multiples OK)") do |path|
45
- $:.unshift(*path.split(":"))
46
- end
47
-
48
- opts.on("-r", "--require LIBRARY", "require the library, before executing your script") do |library|
49
- require library
50
- end
51
-
52
- opts.on("-c", "--config PATH", "load configuration (YAML) from PATH") do |conf_file|
53
- if File.exist?(conf_file)
54
- require 'yaml'
55
-
56
- # load the config file
57
- begin
58
- conf = YAML.load_file(conf_file)
59
- rescue Errno::EACCES
60
- abort("Can't access #{conf_file}, try 'sudo #{$0}'")
61
- end
62
-
63
- # store config file path so SIGHUP and SIGUSR2 will reload the config in case it changes
64
- options[:config_file] = conf_file
65
-
66
- # parse config
67
- case conf
68
- when String
69
- # config file given was just the commandline options
70
- ARGV.replace(conf.split)
71
- opts.parse! ARGV
72
- when Hash
73
- conf.symbolize_keys!
74
- options = options.merge(conf)
75
- when Array
76
- # TODO (MT) support multiple servers (or at least specifying which
77
- # server's configuration to load)
78
- warn "Your configuration file is setup for multiple servers. This is not a supported feature yet."
79
- warn "However, we've pulled the first server entry as this server's configuration."
80
- # an array of server configurations
81
- # default to the first entry since multiple server configurations isn't
82
- # precisely worked out yet.
83
- options = options.merge(conf[0])
84
- else
85
- abort "Config file in an unsupported format. Config files must be YAML or the commandline flags"
86
- end
87
- else
88
- abort "Config file failed to load. #{conf_file} was not found. Correct the path and try again."
89
- end
90
- end
91
-
92
- opts.on("-s", "--server SERVER", "serve using SERVER (default: #{options[:server]})") do |serv|
93
- options[:server] = serv
94
- end
95
-
96
- opts.on("-o", "--host HOST", "listen on HOST (default: #{options[:host]})") do |host|
97
- options[:host] = host
98
- end
99
-
100
- opts.on("-p", "--port PORT", "use PORT (default: #{options[:port]})") do |port|
101
- options[:port] = port
102
- end
103
-
104
- opts.on("-l", "--logfile PATH", "log access to PATH (default: #{options[:log_file]})") do |log_file|
105
- options[:log_file] = log_file
106
- end
107
-
108
- opts.on("-L", "--loglevel LEVEL", "log level (default: #{options[:log_level]})") do |log_file|
109
- options[:log_level] = log_file
110
- end
111
-
112
- opts.on("-P", "--pidfile PATH", "save PID to PATH (default: #{options[:pid_file]})") do |log_file|
113
- options[:pid_file] = log_file
114
- end
115
-
116
- opts.on("-e", "--env ENVIRONMENT", "use ENVIRONMENT for defaults (default: #{options[:environment]})") do |env|
117
- options[:environment] = env
118
- end
119
-
120
- opts.on_tail("-h", "--help", "Show this message") do
121
- puts opts
122
- exit
123
- end
124
-
125
- opts.on_tail("-v", "--version", "Show version") do
126
- # require 'halcyon'
127
- puts "Halcyon #{Halcyon::Server.version}"
128
- exit
129
- end
130
-
131
- begin
132
- opts.parse! ARGV
133
- rescue OptionParser::InvalidOption => e
134
- abort "You used an unsupported option. Try: halcyon -h"
135
- end
136
- end
137
-
138
- abort "Halcyon needs an app to run. Try: halcyon -h" if ARGV.empty?
139
- options[:app] = ARGV.shift
140
-
141
- #--
142
- # load app
143
- #++
144
-
145
- if !File.exists?("#{options[:app]}.rb")
146
- abort "Halcyon did not find the app #{options[:app]}. Check your path and try again."
147
- end
148
-
149
- require options[:app]
150
- appname = File.basename(options[:app]).capitalize.gsub(/_([a-z])/){|m|m[1].chr.capitalize}
151
- begin
152
- app = Object.const_get(appname)
153
- rescue NameError => e
154
- abort "Unable to load #{appname}. Please ensure your server is so named."
155
- end
156
-
157
- #--
158
- # prepare server
159
- #++
160
- begin
161
- # attempt to require the server
162
- begin; require options[:server].capitalize; rescue LoadError; end
163
-
164
- # get the appropriate Rack Handler
165
- server = Rack::Handler.const_get(options[:server].capitalize)
166
- rescue NameError
167
- servers = {
168
- 'cgi' => 'CGI',
169
- 'fastcgi' => 'FastCGI',
170
- 'lsws' => 'LSWS',
171
- 'mongrel' => 'Mongrel',
172
- 'webrick' => 'WEBrick',
173
- 'thin' => 'Thin'
174
- }
175
- abort "Unsupported server (missing Rack Handler). Did you mean to specify #{options[:server]}?" unless servers.key? options[:server]
176
- server = Rack::Handler.const_get(servers[options[:server]])
177
- end
178
-
179
- #--
180
- # prepare app environment
181
- #++
182
-
183
- case options[:environment]
184
- when "development"
185
- app = Rack::Builder.new {
186
- use Rack::CommonLogger, STDERR unless server.name =~ /CGI/
187
- use Rack::ShowExceptions
188
- use Rack::Reloader
189
- use Rack::Lint
190
- run app.new(options)
191
- }.to_app
192
- when "deployment"
193
- app = Rack::Builder.new {
194
- use Rack::CommonLogger, STDERR unless server.name =~ /CGI/
195
- run app.new(options)
196
- }.to_app
197
- else
198
- app = app.new(options)
199
- end
200
-
201
- #--
202
- # start server
203
- #++
204
-
205
- server.run app, :Port => Integer(options[:port])
3
+ require File.join(File.dirname(__FILE__), '..', 'lib', 'halcyon')
4
+ Halcyon::Runner.run! ARGV
data/lib/halcyon.rb CHANGED
@@ -1,54 +1,67 @@
1
- #!/usr/bin/env ruby
2
- #--
3
- # Created by Matt Todd on 2007-12-14.
4
- # Copyright (c) 2007. All rights reserved.
5
- #++
6
-
7
1
  $:.unshift File.dirname(__FILE__)
8
2
 
9
- #--
10
- # dependencies
11
- #++
12
-
13
- %w(rubygems merb/core_ext).each {|dep|require dep}
14
-
15
- #--
16
- # module
17
- #++
3
+ %w(rubygems rack merb-core/core_ext merb-core/vendor/facets merb-core/dispatch/router json uri).each {|dep|require dep}
18
4
 
5
+ # Provides global values, like the root of the current application directory,
6
+ # the current logger, the application name, and the framework version.
7
+ #
8
+ # Examples
9
+ # Halcyon.app #=> AppName
10
+ # Halcyon.root #=> Dir.pwd
11
+ # Halcyon.config #=> {:allow_from => :all, :logging => {...}, ...}
12
+ # Halcyon.paths #=> {:config => Halcyon.root/'config', ...}
13
+ # Halcyon.logger #=> #<Logger>
14
+ # Halcyon.version #=> "0.5.0"
19
15
  module Halcyon
20
- VERSION = [0,4,0]
21
- def self.version
22
- VERSION.join('.')
23
- end
24
16
 
25
- # = Introduction
26
- #
27
- # Halcyon is a JSON Web Server Framework intended to be used for fast, small
28
- # data transactions, like for AJAX-intensive sites or for special services like
29
- # authentication centralized for numerous web apps in the same cluster.
30
- #
31
- # The possibilities are pretty limitless: the goal of Halcyon was simply to be
32
- # lightweight, fast, simple to implement and use, and able to be extended.
33
- #
34
- # == Usage
35
- #
36
- # For documentation on using Halcyon, check out the Halcyon::Server::Base and
37
- # Halcyon::Client::Base classes which contain much more usage documentation.
38
- def introduction
39
- abort "READ THE DAMNED RDOCS!"
40
- end
17
+ VERSION = [0,5,0] unless defined?(Halcyon::VERSION)
41
18
 
42
- #--
43
- # Module Autoloading
44
- #++
19
+ autoload :Application, 'halcyon/application'
20
+ autoload :Client, 'halcyon/client'
21
+ autoload :Controller, 'halcyon/controller'
22
+ autoload :Exceptions, 'halcyon/exceptions'
23
+ autoload :Logging, 'halcyon/logging'
24
+ autoload :Runner, 'halcyon/runner'
45
25
 
46
- class Server
47
- module Auth
48
- autoload :Basic, 'halcyon/server/auth/basic'
26
+ class << self
27
+
28
+ attr_accessor :app
29
+ attr_accessor :logger
30
+ attr_accessor :config
31
+ attr_accessor :paths
32
+
33
+ def version
34
+ VERSION.join('.')
35
+ end
36
+
37
+ # The root directory of the current application.
38
+ #
39
+ # Returns String:root_directory
40
+ def root
41
+ self.config[:root] || Dir.pwd rescue Dir.pwd
49
42
  end
43
+
44
+ def configurable(attribute)
45
+ eval <<-"end;"
46
+ def #{attribute.to_s}
47
+ Halcyon.config[:#{attribute.to_s}]
48
+ end
49
+ def #{attribute.to_s}=(value)
50
+ value = value.to_mash if value.is_a?(Hash)
51
+ Halcyon.config[:#{attribute.to_s}] = value
52
+ end
53
+ end;
54
+ end
55
+ alias_method :configurable_attr, :configurable
56
+
50
57
  end
51
58
 
59
+ # Creates <tt>Halcyon.db</tt> to alias <tt>Halcyon.config[:db]</tt>.
60
+ # Also creates the complementary assignment method, <tt>Halcyon.db=</tt>
61
+ # that aliases <tt>Halcyon.config[:db]=</tt>.
62
+ configurable_attr :db
63
+
52
64
  end
53
65
 
54
- %w(halcyon/exceptions).each {|dep|require dep}
66
+ # Include the klass#logger and klass.logger accessor methods into Object.
67
+ Object.send(:include, Halcyon::Logging::Helpers)