angelo 0.0.4
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/.gitignore +2 -0
- data/CHANGELOG +20 -0
- data/Gemfile +5 -0
- data/LICENSE +13 -0
- data/README.md +78 -0
- data/angelo.gemspec +16 -0
- data/example/foo/foo.rb +60 -0
- data/example/foo/views/index.html.erb +20 -0
- data/example/foo/views/layout.html.erb +10 -0
- data/lib/angelo/base.rb +106 -0
- data/lib/angelo/params_parser.rb +48 -0
- data/lib/angelo/responder/websocket.rb +38 -0
- data/lib/angelo/responder.rb +87 -0
- data/lib/angelo/server.rb +47 -0
- data/lib/angelo/tilt/erb.rb +76 -0
- data/lib/angelo/version.rb +3 -0
- data/lib/angelo.rb +33 -0
- metadata +79 -0
data/.gitignore
ADDED
data/CHANGELOG
ADDED
@@ -0,0 +1,20 @@
|
|
1
|
+
changelog
|
2
|
+
=========
|
3
|
+
|
4
|
+
### 0.0.3 30 oct 2013
|
5
|
+
|
6
|
+
|
7
|
+
* added tilt/erb
|
8
|
+
* added before/after
|
9
|
+
* added content_type/headers
|
10
|
+
* better websockets error handling
|
11
|
+
|
12
|
+
### 0.0.2 29 oct 2013
|
13
|
+
|
14
|
+
* added websockets helper
|
15
|
+
|
16
|
+
### 0.0.1 28 oct 2013
|
17
|
+
|
18
|
+
* initial release
|
19
|
+
* get/post/put/delete/options support
|
20
|
+
* socket support
|
data/Gemfile
ADDED
data/LICENSE
ADDED
@@ -0,0 +1,13 @@
|
|
1
|
+
Copyright 2013 Kenichi Nakamura
|
2
|
+
|
3
|
+
Licensed under the Apache License, Version 2.0 (the "License");
|
4
|
+
you may not use this file except in compliance with the License.
|
5
|
+
You may obtain a copy of the License at
|
6
|
+
|
7
|
+
http://www.apache.org/licenses/LICENSE-2.0
|
8
|
+
|
9
|
+
Unless required by applicable law or agreed to in writing, software
|
10
|
+
distributed under the License is distributed on an "AS IS" BASIS,
|
11
|
+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
12
|
+
See the License for the specific language governing permissions and
|
13
|
+
limitations under the License.
|
data/README.md
ADDED
@@ -0,0 +1,78 @@
|
|
1
|
+
Angelo
|
2
|
+
======
|
3
|
+
|
4
|
+
A Sinatra-esque DSL for Reel.
|
5
|
+
|
6
|
+
__SUPER ALPHA!__
|
7
|
+
|
8
|
+
### Quick example
|
9
|
+
|
10
|
+
```ruby
|
11
|
+
require 'angelo'
|
12
|
+
|
13
|
+
class Foo < Angelo::Base
|
14
|
+
|
15
|
+
TEST = {foo: "bar", baz: 123, bat: false}.to_json
|
16
|
+
|
17
|
+
def pong; 'pong'; end
|
18
|
+
def foo; params[:foo]; end
|
19
|
+
|
20
|
+
get '/ping' do
|
21
|
+
pong
|
22
|
+
end
|
23
|
+
|
24
|
+
post '/foo' do
|
25
|
+
foo
|
26
|
+
end
|
27
|
+
|
28
|
+
post '/bar' do
|
29
|
+
params.to_json
|
30
|
+
end
|
31
|
+
|
32
|
+
post '/emit' do
|
33
|
+
websockets.each {|ws| ws.write TEST}
|
34
|
+
params.to_json
|
35
|
+
end
|
36
|
+
|
37
|
+
socket '/ws' do |s|
|
38
|
+
websockets << s
|
39
|
+
while msg = s.read
|
40
|
+
5.times { s.write TEST }
|
41
|
+
s.write foo.to_json
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
end
|
46
|
+
|
47
|
+
Foo.run
|
48
|
+
```
|
49
|
+
|
50
|
+
### Tilt / ERB
|
51
|
+
|
52
|
+
To make `erb` available in route blocks
|
53
|
+
|
54
|
+
1. add `tilt` to your `Gemfile`:
|
55
|
+
|
56
|
+
```ruby
|
57
|
+
gem 'tilt'
|
58
|
+
```
|
59
|
+
|
60
|
+
2. require `angelo/tilt/erb`
|
61
|
+
3. include `Angelo::Tilt::ERB` in your app
|
62
|
+
|
63
|
+
```ruby
|
64
|
+
class Foo < Angelo::Base
|
65
|
+
include Angelo::Tilt::ERB
|
66
|
+
|
67
|
+
@@views = 'some/other/path' # defaults to './views'
|
68
|
+
|
69
|
+
get '/' do
|
70
|
+
erb :index
|
71
|
+
end
|
72
|
+
|
73
|
+
end
|
74
|
+
```
|
75
|
+
|
76
|
+
### License
|
77
|
+
|
78
|
+
see LICENSE
|
data/angelo.gemspec
ADDED
@@ -0,0 +1,16 @@
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
2
|
+
require File.expand_path('../lib/angelo/version', __FILE__)
|
3
|
+
|
4
|
+
Gem::Specification.new do |gem|
|
5
|
+
gem.authors = ["Kenichi Nakamura"]
|
6
|
+
gem.email = ["kenichi.nakamura@gmail.com"]
|
7
|
+
gem.description = gem.summary = "A Sinatra-esque DSL for Reel"
|
8
|
+
gem.homepage = "https://github.com/kenichi/angelo"
|
9
|
+
gem.files = `git ls-files | grep -Ev '^(myapp|examples)'`.split("\n")
|
10
|
+
gem.test_files = `git ls-files -- test/*`.split("\n")
|
11
|
+
gem.name = "angelo"
|
12
|
+
gem.require_paths = ["lib"]
|
13
|
+
gem.version = Angelo::VERSION
|
14
|
+
gem.license = 'apache'
|
15
|
+
gem.add_dependency 'reel'
|
16
|
+
end
|
data/example/foo/foo.rb
ADDED
@@ -0,0 +1,60 @@
|
|
1
|
+
$:.unshift File.expand_path '../../../lib', __FILE__
|
2
|
+
|
3
|
+
require 'angelo'
|
4
|
+
require 'angelo/tilt/erb'
|
5
|
+
|
6
|
+
class Foo < Angelo::Base
|
7
|
+
include Angelo::Tilt::ERB
|
8
|
+
|
9
|
+
TEST = {foo: "bar", baz: 123, bat: false}.to_json
|
10
|
+
|
11
|
+
def pong; 'pong'; end
|
12
|
+
def foo; params[:foo]; end
|
13
|
+
def time_ms; Time.now.to_f * 1000.0; end
|
14
|
+
|
15
|
+
before do
|
16
|
+
info "request: #{request.method} #{request.path}"
|
17
|
+
@foo = request.path
|
18
|
+
@timing = time_ms
|
19
|
+
end
|
20
|
+
|
21
|
+
after do
|
22
|
+
info "timing: #{time_ms - @timing}ms"
|
23
|
+
end
|
24
|
+
|
25
|
+
get '/' do
|
26
|
+
@name = params[:name]
|
27
|
+
@host = request.headers['Host']
|
28
|
+
erb :index, locals: {zzz: 'word'}
|
29
|
+
end
|
30
|
+
|
31
|
+
get '/ping' do
|
32
|
+
debug "@foo: #{@foo}"
|
33
|
+
pong
|
34
|
+
end
|
35
|
+
|
36
|
+
post '/foo' do
|
37
|
+
foo
|
38
|
+
end
|
39
|
+
|
40
|
+
post '/bar' do
|
41
|
+
content_type = :json
|
42
|
+
params
|
43
|
+
end
|
44
|
+
|
45
|
+
post '/emit' do
|
46
|
+
websockets.each {|ws| ws.write TEST}
|
47
|
+
params.to_json
|
48
|
+
end
|
49
|
+
|
50
|
+
socket '/ws' do |s|
|
51
|
+
websockets << s
|
52
|
+
while msg = s.read
|
53
|
+
5.times { s.write TEST }
|
54
|
+
s.write foo.to_json
|
55
|
+
end
|
56
|
+
end
|
57
|
+
|
58
|
+
end
|
59
|
+
|
60
|
+
Foo.run unless $0 == 'irb'
|
@@ -0,0 +1,20 @@
|
|
1
|
+
hi <%= @name %><br/>
|
2
|
+
this is a local - <%= zzz %><br/>
|
3
|
+
<br/>
|
4
|
+
<a href="#" onclick="openws();">websocket!</a>
|
5
|
+
<br/>
|
6
|
+
<a href="#" onclick="emit();">emit!</a>
|
7
|
+
|
8
|
+
<script>
|
9
|
+
var ws;
|
10
|
+
function openws() {
|
11
|
+
ws = new WebSocket('ws://<%= @host %>/ws');
|
12
|
+
ws.onmessage = function(e) { console.log(e.data); };
|
13
|
+
ws.onopen = function(e) {
|
14
|
+
ws.send('hi');
|
15
|
+
};
|
16
|
+
}
|
17
|
+
function emit() {
|
18
|
+
$.post('/emit', {data: {"foo": "bar"}});
|
19
|
+
}
|
20
|
+
</script>
|
data/lib/angelo/base.rb
ADDED
@@ -0,0 +1,106 @@
|
|
1
|
+
module Angelo
|
2
|
+
|
3
|
+
class Base
|
4
|
+
include ParamsParser
|
5
|
+
include Celluloid::Logger
|
6
|
+
|
7
|
+
extend Forwardable
|
8
|
+
def_delegator :@responder, :request
|
9
|
+
|
10
|
+
attr_accessor :responder
|
11
|
+
|
12
|
+
class << self
|
13
|
+
|
14
|
+
attr_accessor :app_file
|
15
|
+
|
16
|
+
def inherited subclass
|
17
|
+
subclass.app_file = caller(1).map {|l| l.split(/:(?=|in )/, 3)[0,1]}.flatten[0]
|
18
|
+
|
19
|
+
def subclass.root
|
20
|
+
@root ||= File.expand_path '..', app_file
|
21
|
+
@root
|
22
|
+
end
|
23
|
+
|
24
|
+
def subclass.view_dir
|
25
|
+
v = self.class_variable_get(:@@views) rescue 'views'
|
26
|
+
File.join root, v
|
27
|
+
end
|
28
|
+
|
29
|
+
end
|
30
|
+
|
31
|
+
def compile! name, &block
|
32
|
+
define_method name, &block
|
33
|
+
method = instance_method name
|
34
|
+
remove_method name
|
35
|
+
method
|
36
|
+
end
|
37
|
+
|
38
|
+
def routes
|
39
|
+
@routes ||= {}
|
40
|
+
[:get, :post, :put, :delete, :options, :socket].each do |m|
|
41
|
+
@routes[m] ||= {}
|
42
|
+
end
|
43
|
+
@routes
|
44
|
+
end
|
45
|
+
|
46
|
+
def before &block
|
47
|
+
# @before = compile! :before, &block
|
48
|
+
define_method :before, &block
|
49
|
+
end
|
50
|
+
|
51
|
+
def after &block
|
52
|
+
# @after = compile! :after, &block
|
53
|
+
define_method :after, &block
|
54
|
+
end
|
55
|
+
|
56
|
+
[:get, :post, :put, :delete, :options].each do |m|
|
57
|
+
define_method m do |path, &block|
|
58
|
+
routes[m][path] = Responder.new &block
|
59
|
+
end
|
60
|
+
end
|
61
|
+
|
62
|
+
def socket path, &block
|
63
|
+
routes[:socket][path] = WebsocketResponder.new &block
|
64
|
+
end
|
65
|
+
|
66
|
+
def websockets
|
67
|
+
if @websockets.nil?
|
68
|
+
@websockets = []
|
69
|
+
def @websockets.each &block
|
70
|
+
super do |ws|
|
71
|
+
begin
|
72
|
+
yield ws
|
73
|
+
rescue Reel::SocketError => rse
|
74
|
+
warn "#{rse.class} - #{rse.message}"
|
75
|
+
delete ws
|
76
|
+
end
|
77
|
+
end
|
78
|
+
end
|
79
|
+
end
|
80
|
+
@websockets.reject! &:closed?
|
81
|
+
@websockets
|
82
|
+
end
|
83
|
+
|
84
|
+
def run host = '127.0.0.1', port = 4567
|
85
|
+
@server = Angelo::Server.new self, host, port
|
86
|
+
sleep
|
87
|
+
end
|
88
|
+
|
89
|
+
end
|
90
|
+
|
91
|
+
def before; end;
|
92
|
+
def after; end;
|
93
|
+
|
94
|
+
def params
|
95
|
+
@params ||= case request.method
|
96
|
+
when GET; parse_query_string
|
97
|
+
when POST; parse_post_body
|
98
|
+
end
|
99
|
+
@params
|
100
|
+
end
|
101
|
+
|
102
|
+
def websockets; self.class.websockets; end
|
103
|
+
|
104
|
+
end
|
105
|
+
|
106
|
+
end
|
@@ -0,0 +1,48 @@
|
|
1
|
+
require 'cgi'
|
2
|
+
|
3
|
+
module Angelo
|
4
|
+
|
5
|
+
module ParamsParser
|
6
|
+
|
7
|
+
EMPTY_JSON = '{}'.freeze
|
8
|
+
SEMICOLON = ';'.freeze
|
9
|
+
|
10
|
+
def parse_formencoded str
|
11
|
+
str.split('&').reduce(Responder.symhash) do |p, kv|
|
12
|
+
key, value = kv.split('=').map {|s| CGI.escape s}
|
13
|
+
p[key] = value
|
14
|
+
p
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
def parse_query_string
|
19
|
+
parse_formencoded(request.query_string || '')
|
20
|
+
end
|
21
|
+
|
22
|
+
def parse_post_body
|
23
|
+
body = request.body.to_s
|
24
|
+
case
|
25
|
+
when form_encoded?
|
26
|
+
body = parse_formencoded body
|
27
|
+
when json?
|
28
|
+
body = EMPTY_JSON if body.empty?
|
29
|
+
body = JSON.parse body
|
30
|
+
end
|
31
|
+
parse_query_string.merge! body
|
32
|
+
end
|
33
|
+
|
34
|
+
def form_encoded?
|
35
|
+
content_type? FORM_TYPE
|
36
|
+
end
|
37
|
+
|
38
|
+
def json?
|
39
|
+
content_type? JSON_TYPE
|
40
|
+
end
|
41
|
+
|
42
|
+
def content_type? type
|
43
|
+
request.headers[CONTENT_TYPE_HEADER_KEY].split(SEMICOLON).include? type
|
44
|
+
end
|
45
|
+
|
46
|
+
end
|
47
|
+
|
48
|
+
end
|
@@ -0,0 +1,38 @@
|
|
1
|
+
module Angelo
|
2
|
+
|
3
|
+
class WebsocketResponder < Responder
|
4
|
+
|
5
|
+
def params
|
6
|
+
@params ||= parse_query_string
|
7
|
+
@params
|
8
|
+
end
|
9
|
+
|
10
|
+
def request= request
|
11
|
+
@params = nil
|
12
|
+
@request = request
|
13
|
+
@websocket = @request.websocket
|
14
|
+
handle_request
|
15
|
+
end
|
16
|
+
|
17
|
+
def handle_request
|
18
|
+
begin
|
19
|
+
if @response_handler
|
20
|
+
@bound_response_handler ||= @response_handler.bind @base
|
21
|
+
@bound_response_handler[@websocket]
|
22
|
+
else
|
23
|
+
raise NotImplementedError
|
24
|
+
end
|
25
|
+
rescue IOError => ioe
|
26
|
+
error "#{ioe.class} - #{ioe.message}"
|
27
|
+
@websocket.close
|
28
|
+
@base.websockets.delete @websocket
|
29
|
+
rescue => e
|
30
|
+
error e.message
|
31
|
+
::STDERR.puts e.backtrace
|
32
|
+
@connection.close
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
end
|
37
|
+
|
38
|
+
end
|
@@ -0,0 +1,87 @@
|
|
1
|
+
module Angelo
|
2
|
+
|
3
|
+
class Responder
|
4
|
+
include Celluloid::Logger
|
5
|
+
|
6
|
+
class << self
|
7
|
+
|
8
|
+
def symhash
|
9
|
+
Hash.new {|hash,key| hash[key.to_s] if Symbol === key }
|
10
|
+
end
|
11
|
+
|
12
|
+
end
|
13
|
+
|
14
|
+
attr_writer :connection
|
15
|
+
attr_reader :request
|
16
|
+
|
17
|
+
def initialize &block
|
18
|
+
@response_handler = Base.compile! :request_handler, &block
|
19
|
+
end
|
20
|
+
|
21
|
+
def base= base
|
22
|
+
@base = base
|
23
|
+
@base.responder = self
|
24
|
+
end
|
25
|
+
|
26
|
+
def request= request
|
27
|
+
@params = nil
|
28
|
+
@request = request
|
29
|
+
handle_request
|
30
|
+
respond
|
31
|
+
end
|
32
|
+
|
33
|
+
def handle_request
|
34
|
+
begin
|
35
|
+
if @response_handler
|
36
|
+
@base.before
|
37
|
+
@body = @response_handler.bind(@base).call || ''
|
38
|
+
@base.after
|
39
|
+
else
|
40
|
+
raise NotImplementedError
|
41
|
+
end
|
42
|
+
rescue => e
|
43
|
+
error_message = case
|
44
|
+
when respond_with?(:json)
|
45
|
+
{ error: e.message }.to_json
|
46
|
+
else
|
47
|
+
e.message
|
48
|
+
end
|
49
|
+
@connection.respond :internal_server_error, headers, error_message
|
50
|
+
@connection.close
|
51
|
+
error "#{e.class} - #{e.message}"
|
52
|
+
::STDERR.puts e.backtrace
|
53
|
+
end
|
54
|
+
end
|
55
|
+
|
56
|
+
def headers hs = nil
|
57
|
+
@headers ||= {}
|
58
|
+
@headers.merge! hs if hs
|
59
|
+
@headers
|
60
|
+
end
|
61
|
+
|
62
|
+
def content_type= type
|
63
|
+
case type
|
64
|
+
when :json
|
65
|
+
headers CONTENT_TYPE_HEADER_KEY => JSON_TYPE
|
66
|
+
else
|
67
|
+
raise ArgumentError.new "invalid content_type: #{type}"
|
68
|
+
end
|
69
|
+
end
|
70
|
+
|
71
|
+
def respond_with? type
|
72
|
+
case headers[CONTENT_TYPE_HEADER_KEY]
|
73
|
+
when JSON_TYPE
|
74
|
+
type == :json
|
75
|
+
else
|
76
|
+
type == :html
|
77
|
+
end
|
78
|
+
end
|
79
|
+
|
80
|
+
def respond
|
81
|
+
@body = @body.to_json if respond_with? :json
|
82
|
+
@connection.respond :ok, DEFAULT_RESPONSE_HEADERS.merge(headers), @body
|
83
|
+
end
|
84
|
+
|
85
|
+
end
|
86
|
+
|
87
|
+
end
|
@@ -0,0 +1,47 @@
|
|
1
|
+
module Angelo
|
2
|
+
|
3
|
+
class Server < Reel::Server
|
4
|
+
include Celluloid::Logger
|
5
|
+
|
6
|
+
def initialize base, host = '127.0.0.1', port = 4567
|
7
|
+
@base = base
|
8
|
+
info "Angelo listening on #{host}:#{port}"
|
9
|
+
super host, port, &method(:on_connection)
|
10
|
+
end
|
11
|
+
|
12
|
+
def on_connection connection
|
13
|
+
connection.each_request do |request|
|
14
|
+
if request.websocket?
|
15
|
+
debug "got websocket request..."
|
16
|
+
route_websocket connection, request
|
17
|
+
else
|
18
|
+
route_request connection, request
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
private
|
24
|
+
|
25
|
+
def route_request connection, request
|
26
|
+
route! request.method.downcase.to_sym, connection, request
|
27
|
+
end
|
28
|
+
|
29
|
+
def route_websocket connection, request
|
30
|
+
route! :socket, connection, request
|
31
|
+
end
|
32
|
+
|
33
|
+
def route! meth, connection, request
|
34
|
+
rs = @base.routes[meth][request.path]
|
35
|
+
if rs
|
36
|
+
responder = rs.dup
|
37
|
+
responder.base = @base.new
|
38
|
+
responder.connection = connection
|
39
|
+
responder.request = request
|
40
|
+
else
|
41
|
+
connection.respond :not_found, DEFAULT_RESPONSE_HEADERS, NOT_FOUND
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
end
|
46
|
+
|
47
|
+
end
|
@@ -0,0 +1,76 @@
|
|
1
|
+
require 'erb'
|
2
|
+
require 'tilt'
|
3
|
+
|
4
|
+
module Angelo
|
5
|
+
module Tilt
|
6
|
+
module ERB
|
7
|
+
|
8
|
+
# hrm, sneaky
|
9
|
+
#
|
10
|
+
def self.included base
|
11
|
+
base.extend ClassMethods
|
12
|
+
end
|
13
|
+
|
14
|
+
module ClassMethods
|
15
|
+
|
16
|
+
DEFAULT_LAYOUT = 'layout.html.erb'.freeze
|
17
|
+
|
18
|
+
def view_glob *glob
|
19
|
+
File.join view_dir, *glob
|
20
|
+
end
|
21
|
+
|
22
|
+
def templatify *glob
|
23
|
+
Dir[view_glob *glob].reduce({}) do |h,v|
|
24
|
+
sym = v.gsub view_dir + '/', ''
|
25
|
+
return h if (block_given? && yield(v))
|
26
|
+
sym.gsub! '/', '_'
|
27
|
+
sym.gsub! /\.\w+?\.erb$/, ''
|
28
|
+
h[sym.to_sym] = ::Tilt::ERBTemplate.new v
|
29
|
+
h
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
def templates
|
34
|
+
@templates ||= templatify('**', '*.erb'){|v| v =~ /^layouts\//}
|
35
|
+
@templates
|
36
|
+
end
|
37
|
+
|
38
|
+
def layout_templates
|
39
|
+
@layout_templates ||= templatify 'layouts', '*.erb'
|
40
|
+
@layout_templates
|
41
|
+
end
|
42
|
+
|
43
|
+
def default_layout
|
44
|
+
if @default_layout.nil?
|
45
|
+
l = view_glob(DEFAULT_LAYOUT)
|
46
|
+
@default_layout = ::Tilt::ERBTemplate.new l if File.exist? l
|
47
|
+
end
|
48
|
+
@default_layout
|
49
|
+
end
|
50
|
+
|
51
|
+
end
|
52
|
+
|
53
|
+
def erb view, opts = {locals: {}}
|
54
|
+
locals = Hash === opts[:locals] ? opts[:locals] : {}
|
55
|
+
render = ->{self.class.templates[view].render self, locals}
|
56
|
+
case opts[:layout]
|
57
|
+
when false
|
58
|
+
render[]
|
59
|
+
when Symbol
|
60
|
+
if lt = self.class.layout_templates[opts[:layout]]
|
61
|
+
lt.render self, locals, &render
|
62
|
+
else
|
63
|
+
raise ArgumentError.new "unknown layout - :#{opts[:layout]}"
|
64
|
+
end
|
65
|
+
else
|
66
|
+
if self.class.default_layout
|
67
|
+
self.class.default_layout.render self, locals, &render
|
68
|
+
else
|
69
|
+
render[]
|
70
|
+
end
|
71
|
+
end
|
72
|
+
end
|
73
|
+
|
74
|
+
end
|
75
|
+
end
|
76
|
+
end
|
data/lib/angelo.rb
ADDED
@@ -0,0 +1,33 @@
|
|
1
|
+
require 'reel'
|
2
|
+
require 'json'
|
3
|
+
require 'pry'
|
4
|
+
require 'pry-nav'
|
5
|
+
|
6
|
+
module Angelo
|
7
|
+
|
8
|
+
GET = 'GET'.freeze
|
9
|
+
POST = 'POST'.freeze
|
10
|
+
PUT = 'PUT'.freeze
|
11
|
+
DELETE = 'DELETE'.freeze
|
12
|
+
OPTIONS = 'OPTIONS'.freeze
|
13
|
+
|
14
|
+
CONTENT_TYPE_HEADER_KEY = 'Content-Type'.freeze
|
15
|
+
|
16
|
+
HTML_TYPE = 'text/html'.freeze
|
17
|
+
JSON_TYPE = 'application/json'.freeze
|
18
|
+
FORM_TYPE = 'application/x-www-form-urlencoded'.freeze
|
19
|
+
|
20
|
+
DEFAULT_RESPONSE_HEADERS = {
|
21
|
+
CONTENT_TYPE_HEADER_KEY => HTML_TYPE
|
22
|
+
}
|
23
|
+
|
24
|
+
NOT_FOUND = 'Not Found'.freeze
|
25
|
+
|
26
|
+
end
|
27
|
+
|
28
|
+
require 'angelo/version'
|
29
|
+
require 'angelo/params_parser'
|
30
|
+
require 'angelo/server'
|
31
|
+
require 'angelo/base'
|
32
|
+
require 'angelo/responder'
|
33
|
+
require 'angelo/responder/websocket'
|
metadata
ADDED
@@ -0,0 +1,79 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: angelo
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.0.4
|
5
|
+
prerelease:
|
6
|
+
platform: ruby
|
7
|
+
authors:
|
8
|
+
- Kenichi Nakamura
|
9
|
+
autorequire:
|
10
|
+
bindir: bin
|
11
|
+
cert_chain: []
|
12
|
+
date: 2013-10-31 00:00:00.000000000 Z
|
13
|
+
dependencies:
|
14
|
+
- !ruby/object:Gem::Dependency
|
15
|
+
name: reel
|
16
|
+
requirement: !ruby/object:Gem::Requirement
|
17
|
+
none: false
|
18
|
+
requirements:
|
19
|
+
- - ! '>='
|
20
|
+
- !ruby/object:Gem::Version
|
21
|
+
version: '0'
|
22
|
+
type: :runtime
|
23
|
+
prerelease: false
|
24
|
+
version_requirements: !ruby/object:Gem::Requirement
|
25
|
+
none: false
|
26
|
+
requirements:
|
27
|
+
- - ! '>='
|
28
|
+
- !ruby/object:Gem::Version
|
29
|
+
version: '0'
|
30
|
+
description: A Sinatra-esque DSL for Reel
|
31
|
+
email:
|
32
|
+
- kenichi.nakamura@gmail.com
|
33
|
+
executables: []
|
34
|
+
extensions: []
|
35
|
+
extra_rdoc_files: []
|
36
|
+
files:
|
37
|
+
- .gitignore
|
38
|
+
- CHANGELOG
|
39
|
+
- Gemfile
|
40
|
+
- LICENSE
|
41
|
+
- README.md
|
42
|
+
- angelo.gemspec
|
43
|
+
- example/foo/foo.rb
|
44
|
+
- example/foo/views/index.html.erb
|
45
|
+
- example/foo/views/layout.html.erb
|
46
|
+
- lib/angelo.rb
|
47
|
+
- lib/angelo/base.rb
|
48
|
+
- lib/angelo/params_parser.rb
|
49
|
+
- lib/angelo/responder.rb
|
50
|
+
- lib/angelo/responder/websocket.rb
|
51
|
+
- lib/angelo/server.rb
|
52
|
+
- lib/angelo/tilt/erb.rb
|
53
|
+
- lib/angelo/version.rb
|
54
|
+
homepage: https://github.com/kenichi/angelo
|
55
|
+
licenses:
|
56
|
+
- apache
|
57
|
+
post_install_message:
|
58
|
+
rdoc_options: []
|
59
|
+
require_paths:
|
60
|
+
- lib
|
61
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
62
|
+
none: false
|
63
|
+
requirements:
|
64
|
+
- - ! '>='
|
65
|
+
- !ruby/object:Gem::Version
|
66
|
+
version: '0'
|
67
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
68
|
+
none: false
|
69
|
+
requirements:
|
70
|
+
- - ! '>='
|
71
|
+
- !ruby/object:Gem::Version
|
72
|
+
version: '0'
|
73
|
+
requirements: []
|
74
|
+
rubyforge_project:
|
75
|
+
rubygems_version: 1.8.23
|
76
|
+
signing_key:
|
77
|
+
specification_version: 3
|
78
|
+
summary: A Sinatra-esque DSL for Reel
|
79
|
+
test_files: []
|