halcyon 0.3.7
Sign up to get free protection for your applications and to get access to all the features.
- data/Rakefile +135 -0
- data/bin/halcyon +152 -0
- data/lib/halcyon.rb +54 -0
- data/lib/halcyon/client.rb +43 -0
- data/lib/halcyon/client/base.rb +236 -0
- data/lib/halcyon/client/exceptions.rb +53 -0
- data/lib/halcyon/client/router.rb +106 -0
- data/lib/halcyon/exceptions.rb +19 -0
- data/lib/halcyon/server.rb +55 -0
- data/lib/halcyon/server/base.rb +392 -0
- data/lib/halcyon/server/exceptions.rb +53 -0
- data/lib/halcyon/server/router.rb +100 -0
- data/lib/halcyon/support/hashext.rb +59 -0
- metadata +104 -0
@@ -0,0 +1,53 @@
|
|
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
|
+
# Base Halcyon Exception
|
17
|
+
#++
|
18
|
+
|
19
|
+
class Base < Exception #:nodoc:
|
20
|
+
attr_accessor :status, :error
|
21
|
+
def initialize(status, error)
|
22
|
+
@status = status
|
23
|
+
@error = error
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
#--
|
28
|
+
# Exception classes
|
29
|
+
#++
|
30
|
+
|
31
|
+
Halcyon::Exceptions::HTTP_ERROR_CODES.to_a.each do |http_error|
|
32
|
+
status, body = http_error
|
33
|
+
class_eval(
|
34
|
+
"class #{body.gsub(/ /,'')} < Base\n"+
|
35
|
+
" def initialize(s=#{status}, e='#{body}')\n"+
|
36
|
+
" super s, e\n"+
|
37
|
+
" end\n"+
|
38
|
+
"end"
|
39
|
+
);
|
40
|
+
end
|
41
|
+
|
42
|
+
#--
|
43
|
+
# Exception Lookup
|
44
|
+
#++
|
45
|
+
|
46
|
+
def self.lookup(status)
|
47
|
+
self.const_get(Halcyon::Exceptions::HTTP_ERROR_CODES[status].gsub(/ /,'').to_sym)
|
48
|
+
end
|
49
|
+
|
50
|
+
end
|
51
|
+
end
|
52
|
+
end
|
53
|
+
end
|
@@ -0,0 +1,100 @@
|
|
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).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
|
+
uri = env['REQUEST_URI']
|
79
|
+
|
80
|
+
# prepare request
|
81
|
+
path = (uri ? uri.split('?').first : '').sub(/\/+/, '/')
|
82
|
+
path = path[0..-2] if (path[-1] == ?/) && path.size > 1
|
83
|
+
req = Struct.new(:path, :method).new(path, env['REQUEST_METHOD'].downcase.to_sym)
|
84
|
+
|
85
|
+
# perform match
|
86
|
+
route = self.match(req, {})
|
87
|
+
|
88
|
+
# make sure a route is returned even if no match is found
|
89
|
+
if route[0].nil?
|
90
|
+
#return default route
|
91
|
+
@@default_route
|
92
|
+
else
|
93
|
+
# params (including action and module if set) for the matching route
|
94
|
+
route[1]
|
95
|
+
end
|
96
|
+
end
|
97
|
+
|
98
|
+
end
|
99
|
+
end
|
100
|
+
end
|
@@ -0,0 +1,59 @@
|
|
1
|
+
# Pulled out from http://dev.rubyonrails.org/browser/trunk/activesupport/lib/active_support/core_ext/hash/keys.rb
|
2
|
+
module HashExt #:nodoc:
|
3
|
+
module Keys #:nodoc:
|
4
|
+
# Return a new hash with all keys converted to strings.
|
5
|
+
def stringify_keys
|
6
|
+
inject({}) do |options, (key, value)|
|
7
|
+
options[key.to_s] = value
|
8
|
+
options
|
9
|
+
end
|
10
|
+
end
|
11
|
+
|
12
|
+
# Destructively convert all keys to strings.
|
13
|
+
def stringify_keys!
|
14
|
+
keys.each do |key|
|
15
|
+
unless key.class.to_s == "String" # weird hack to make the tests run when string_ext_test.rb is also running
|
16
|
+
self[key.to_s] = self[key]
|
17
|
+
delete(key)
|
18
|
+
end
|
19
|
+
end
|
20
|
+
self
|
21
|
+
end
|
22
|
+
|
23
|
+
# Return a new hash with all keys converted to symbols.
|
24
|
+
def symbolize_keys
|
25
|
+
inject({}) do |options, (key, value)|
|
26
|
+
value = value.symbolize_keys if value.respond_to? :symbolize_keys # recursive # MT 2007-12-04
|
27
|
+
options[key.to_sym || key] = value
|
28
|
+
options
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
# Destructively convert all keys to symbols.
|
33
|
+
def symbolize_keys!
|
34
|
+
keys.each do |key|
|
35
|
+
unless key.is_a?(Symbol) || (new_key = key.to_sym).nil?
|
36
|
+
self[new_key] = self[key]
|
37
|
+
self[new_key].symbolize_keys! if self[new_key].respond_to? :symbolize_keys!
|
38
|
+
delete(key)
|
39
|
+
end
|
40
|
+
end
|
41
|
+
self
|
42
|
+
end
|
43
|
+
|
44
|
+
alias_method :to_options, :symbolize_keys
|
45
|
+
alias_method :to_options!, :symbolize_keys!
|
46
|
+
|
47
|
+
# Validate all keys in a hash match *valid keys, raising ArgumentError on a mismatch.
|
48
|
+
# Note that keys are NOT treated indifferently, meaning if you use strings for keys but assert symbol
|
49
|
+
# as keys, this will fail.
|
50
|
+
# examples:
|
51
|
+
# { :name => "Rob", :years => "28" }.assert_valid_keys(:name, :age) # => raises "ArgumentError: Unknown key(s): years"
|
52
|
+
# { :name => "Rob", :age => "28" }.assert_valid_keys("name", "age") # => raises "ArgumentError: Unknown key(s): years, name"
|
53
|
+
# { :name => "Rob", :age => "28" }.assert_valid_keys(:name, :age) # => passes, raises nothing
|
54
|
+
def assert_valid_keys(*valid_keys)
|
55
|
+
unknown_keys = keys - [valid_keys].flatten
|
56
|
+
raise(ArgumentError, "Unknown key(s): #{unknown_keys.join(", ")}") unless unknown_keys.empty?
|
57
|
+
end
|
58
|
+
end
|
59
|
+
end
|
metadata
ADDED
@@ -0,0 +1,104 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: halcyon
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.3.7
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Matt Todd
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
|
12
|
+
date: 2007-12-16 00:00:00 -05:00
|
13
|
+
default_executable:
|
14
|
+
dependencies:
|
15
|
+
- !ruby/object:Gem::Dependency
|
16
|
+
name: rack
|
17
|
+
version_requirement:
|
18
|
+
version_requirements: !ruby/object:Gem::Requirement
|
19
|
+
requirements:
|
20
|
+
- - ">="
|
21
|
+
- !ruby/object:Gem::Version
|
22
|
+
version: 0.2.0
|
23
|
+
version:
|
24
|
+
- !ruby/object:Gem::Dependency
|
25
|
+
name: json
|
26
|
+
version_requirement:
|
27
|
+
version_requirements: !ruby/object:Gem::Requirement
|
28
|
+
requirements:
|
29
|
+
- - ">="
|
30
|
+
- !ruby/object:Gem::Version
|
31
|
+
version: 1.1.1
|
32
|
+
version:
|
33
|
+
- !ruby/object:Gem::Dependency
|
34
|
+
name: merb
|
35
|
+
version_requirement:
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - ">="
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: 0.4.1
|
41
|
+
version:
|
42
|
+
description: A JSON App Server Framework
|
43
|
+
email: chiology@gmail.com
|
44
|
+
executables:
|
45
|
+
- halcyon
|
46
|
+
extensions: []
|
47
|
+
|
48
|
+
extra_rdoc_files:
|
49
|
+
- lib
|
50
|
+
files:
|
51
|
+
- lib
|
52
|
+
- Rakefile
|
53
|
+
- lib/halcyon
|
54
|
+
- lib/halcyon/client
|
55
|
+
- lib/halcyon/client/base.rb
|
56
|
+
- lib/halcyon/client/exceptions.rb
|
57
|
+
- lib/halcyon/client/router.rb
|
58
|
+
- lib/halcyon/client.rb
|
59
|
+
- lib/halcyon/exceptions.rb
|
60
|
+
- lib/halcyon/server
|
61
|
+
- lib/halcyon/server/base.rb
|
62
|
+
- lib/halcyon/server/exceptions.rb
|
63
|
+
- lib/halcyon/server/router.rb
|
64
|
+
- lib/halcyon/server.rb
|
65
|
+
- lib/halcyon/support
|
66
|
+
- lib/halcyon/support/hashext.rb
|
67
|
+
- lib/halcyon.rb
|
68
|
+
has_rdoc: true
|
69
|
+
homepage: http://halcyon.rubyforge.org
|
70
|
+
post_install_message:
|
71
|
+
rdoc_options:
|
72
|
+
- --all
|
73
|
+
- --quiet
|
74
|
+
- --op
|
75
|
+
- rdoc
|
76
|
+
- --line-numbers
|
77
|
+
- --inline-source
|
78
|
+
- --title
|
79
|
+
- "\"Halcyon documentation\""
|
80
|
+
- --exclude
|
81
|
+
- "\"^(_darcs|spec|pkg)/\""
|
82
|
+
require_paths:
|
83
|
+
- lib
|
84
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
85
|
+
requirements:
|
86
|
+
- - ">="
|
87
|
+
- !ruby/object:Gem::Version
|
88
|
+
version: 1.8.6
|
89
|
+
version:
|
90
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
91
|
+
requirements:
|
92
|
+
- - ">="
|
93
|
+
- !ruby/object:Gem::Version
|
94
|
+
version: "0"
|
95
|
+
version:
|
96
|
+
requirements: []
|
97
|
+
|
98
|
+
rubyforge_project:
|
99
|
+
rubygems_version: 0.9.5
|
100
|
+
signing_key:
|
101
|
+
specification_version: 2
|
102
|
+
summary: A JSON App Server Framework
|
103
|
+
test_files: []
|
104
|
+
|