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