angelo 0.1.1 → 0.1.2
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG.md +14 -0
- data/Gemfile +1 -0
- data/angelo.gemspec +1 -0
- data/lib/angelo/base.rb +6 -1
- data/lib/angelo/rspec/helpers.rb +1 -1
- data/lib/angelo/server.rb +59 -1
- data/lib/angelo/version.rb +1 -1
- data/lib/angelo.rb +10 -0
- data/spec/angelo/erb_spec.rb +1 -3
- data/spec/angelo/mustermann_spec.rb +1 -3
- data/spec/angelo/static_spec.rb +59 -0
- data/spec/spec_helper.rb +2 -0
- data/spec/test_app_root/public/test.css +6 -0
- data/spec/test_app_root/public/test.html +1 -0
- data/spec/test_app_root/public/test.js +1 -0
- data/spec/test_app_root/public/what.png +0 -0
- data/spec/{angelo → test_app_root}/views/index.html.erb +0 -0
- data/spec/{angelo → test_app_root}/views/layout.html.erb +0 -0
- metadata +30 -7
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 667a3b95c269095d00f41d03cadfe1e3cc40f404
|
4
|
+
data.tar.gz: 9143b9fee78b9b06591516f147a29ce147169447
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 85107d56bb0446a5611a53eec5fd91b737f5e27362345bd9d87370d7183639da3254aa3101709297f9c7fcd90d15563e597de418255fcf14090a5bbb7b91c369
|
7
|
+
data.tar.gz: 8e248165128d31c5f4e891cf74d7508d982fc9798def4fea2fa022e6bf24fbcf77ce87b5d6b12c7e3e1eeef071bf24f123064386433ebbf03d1199b5c285fa3e
|
data/CHANGELOG.md
CHANGED
@@ -1,6 +1,20 @@
|
|
1
1
|
changelog
|
2
2
|
=========
|
3
3
|
|
4
|
+
### 0.1.2 5 mar 2014 burnout, denial
|
5
|
+
|
6
|
+
* basic static file support (i.e. /public files)
|
7
|
+
* basic ETag/If-None-Match support
|
8
|
+
|
9
|
+
### 0.1.1 3 mar 2014
|
10
|
+
|
11
|
+
* fix for params with no Content-Type header
|
12
|
+
|
13
|
+
### 0.1.0 24 feb 2014
|
14
|
+
|
15
|
+
* fix for socket paths with mustermann
|
16
|
+
* sorta common log-ish-ness
|
17
|
+
|
4
18
|
### 0.0.9 20 feb 2014
|
5
19
|
|
6
20
|
* memoize params
|
data/Gemfile
CHANGED
data/angelo.gemspec
CHANGED
data/lib/angelo/base.rb
CHANGED
@@ -32,10 +32,15 @@ module Angelo
|
|
32
32
|
end
|
33
33
|
|
34
34
|
def subclass.view_dir
|
35
|
-
v = self.class_variable_get(:@@views) rescue
|
35
|
+
v = self.class_variable_get(:@@views) rescue DEFAULT_VIEW_DIR
|
36
36
|
File.join root, v
|
37
37
|
end
|
38
38
|
|
39
|
+
def subclass.public_dir
|
40
|
+
p = self.class_variable_get(:@@public_dir) rescue DEFAULT_PUBLIC_DIR
|
41
|
+
File.join root, p
|
42
|
+
end
|
43
|
+
|
39
44
|
end
|
40
45
|
|
41
46
|
def compile! name, &block
|
data/lib/angelo/rspec/helpers.rb
CHANGED
data/lib/angelo/server.rb
CHANGED
@@ -1,3 +1,5 @@
|
|
1
|
+
require 'openssl'
|
2
|
+
|
1
3
|
module Angelo
|
2
4
|
|
3
5
|
class Server < Reel::Server
|
@@ -14,13 +16,21 @@ module Angelo
|
|
14
16
|
# RubyProf.resume
|
15
17
|
connection.each_request do |request|
|
16
18
|
meth = request.websocket? ? :socket : request.method.downcase.to_sym
|
17
|
-
|
19
|
+
dispatch! meth, connection, request
|
18
20
|
end
|
19
21
|
# RubyProf.pause
|
20
22
|
end
|
21
23
|
|
22
24
|
private
|
23
25
|
|
26
|
+
def dispatch! meth, connection, request
|
27
|
+
if staticable?(meth) and lp = local_path(request.path)
|
28
|
+
static! meth, connection, request, lp
|
29
|
+
else
|
30
|
+
route! meth, connection, request
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
24
34
|
def route! meth, connection, request
|
25
35
|
rs = @base.routes[meth][request.path]
|
26
36
|
if rs
|
@@ -34,6 +44,54 @@ module Angelo
|
|
34
44
|
end
|
35
45
|
end
|
36
46
|
|
47
|
+
def local_path path
|
48
|
+
if @base.public_dir
|
49
|
+
lp = File.join(@base.public_dir, path)
|
50
|
+
File.file?(lp) ? lp : nil
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
54
|
+
def staticable? meth
|
55
|
+
STATICABLE.include? meth
|
56
|
+
end
|
57
|
+
|
58
|
+
def static! meth, connection, request, local_path
|
59
|
+
etag = etag_for local_path
|
60
|
+
if request.headers[IF_NONE_MATCH_HEADER_KEY] == etag
|
61
|
+
Angelo.log connection, request, nil, :not_modified, 0
|
62
|
+
connection.respond :not_modified
|
63
|
+
else
|
64
|
+
headers = {
|
65
|
+
|
66
|
+
# Content-Type
|
67
|
+
#
|
68
|
+
CONTENT_TYPE_HEADER_KEY =>
|
69
|
+
(MIME::Types.type_for(File.extname(local_path))[0].content_type rescue HTML_TYPE),
|
70
|
+
|
71
|
+
# Content-Disposition
|
72
|
+
#
|
73
|
+
CONTENT_DISPOSITION_HEADER_KEY =>
|
74
|
+
DEFAULT_CONTENT_DISPOSITION + "; filename=#{File.basename local_path}",
|
75
|
+
|
76
|
+
# Content-Length
|
77
|
+
#
|
78
|
+
CONTENT_LENGTH_HEADER_KEY => File.size(local_path),
|
79
|
+
|
80
|
+
# ETag
|
81
|
+
#
|
82
|
+
ETAG_HEADER_KEY => etag
|
83
|
+
|
84
|
+
}
|
85
|
+
Angelo.log connection, request, nil, :ok, headers[CONTENT_LENGTH_HEADER_KEY]
|
86
|
+
connection.respond :ok, headers, (meth == :head ? nil : File.read(local_path))
|
87
|
+
end
|
88
|
+
end
|
89
|
+
|
90
|
+
def etag_for local_path
|
91
|
+
fs = File::Stat.new local_path
|
92
|
+
OpenSSL::Digest::SHA.hexdigest fs.ino.to_s + fs.size.to_s + fs.mtime.to_s
|
93
|
+
end
|
94
|
+
|
37
95
|
end
|
38
96
|
|
39
97
|
end
|
data/lib/angelo/version.rb
CHANGED
data/lib/angelo.rb
CHANGED
@@ -16,16 +16,26 @@ module Angelo
|
|
16
16
|
|
17
17
|
ROUTABLE = [:get, :post, :put, :delete, :socket]
|
18
18
|
HTTPABLE = [:get, :post, :put, :delete]
|
19
|
+
STATICABLE = [:get, :head]
|
19
20
|
|
20
21
|
CONTENT_TYPE_HEADER_KEY = 'Content-Type'
|
22
|
+
CONTENT_DISPOSITION_HEADER_KEY = 'Content-Disposition'
|
23
|
+
CONTENT_LENGTH_HEADER_KEY = 'Content-Length'
|
24
|
+
DEFAULT_CONTENT_DISPOSITION = 'attachment'
|
25
|
+
ETAG_HEADER_KEY = 'ETag'
|
26
|
+
IF_NONE_MATCH_HEADER_KEY = 'If-None-Match'
|
21
27
|
|
22
28
|
HTML_TYPE = 'text/html'
|
23
29
|
JSON_TYPE = 'application/json'
|
24
30
|
FORM_TYPE = 'application/x-www-form-urlencoded'
|
31
|
+
FILE_TYPE = 'application/octet-stream'
|
25
32
|
|
26
33
|
DEFAULT_ADDR = '127.0.0.1'
|
27
34
|
DEFAULT_PORT = 4567
|
28
35
|
|
36
|
+
DEFAULT_VIEW_DIR = 'views'
|
37
|
+
DEFAULT_PUBLIC_DIR = 'public'
|
38
|
+
|
29
39
|
DEFAULT_RESPONSE_HEADERS = {
|
30
40
|
CONTENT_TYPE_HEADER_KEY => HTML_TYPE
|
31
41
|
}
|
data/spec/angelo/erb_spec.rb
CHANGED
@@ -1,8 +1,6 @@
|
|
1
1
|
require_relative '../spec_helper'
|
2
2
|
require 'angelo/tilt/erb'
|
3
3
|
|
4
|
-
ROOT = File.expand_path '..', __FILE__
|
5
|
-
|
6
4
|
describe Angelo::Base do
|
7
5
|
describe Angelo::Tilt::ERB do
|
8
6
|
|
@@ -10,7 +8,7 @@ describe Angelo::Base do
|
|
10
8
|
|
11
9
|
include Angelo::Tilt::ERB
|
12
10
|
|
13
|
-
@root =
|
11
|
+
@root = TEST_APP_ROOT
|
14
12
|
|
15
13
|
def set_vars
|
16
14
|
@title = 'test'
|
@@ -3,8 +3,6 @@ if RUBY_VERSION =~ /^2\./
|
|
3
3
|
require_relative '../spec_helper'
|
4
4
|
require 'angelo/mustermann'
|
5
5
|
|
6
|
-
TILT_MM_TEST_ROOT = File.expand_path '..', __FILE__
|
7
|
-
|
8
6
|
describe Angelo::Mustermann do
|
9
7
|
|
10
8
|
describe 'pattern matching' do
|
@@ -63,7 +61,7 @@ if RUBY_VERSION =~ /^2\./
|
|
63
61
|
include Angelo::Tilt::ERB
|
64
62
|
include Angelo::Mustermann
|
65
63
|
|
66
|
-
@root =
|
64
|
+
@root = TEST_APP_ROOT
|
67
65
|
|
68
66
|
get '/:foo/things/:bar' do
|
69
67
|
@title = params[:foo]
|
@@ -0,0 +1,59 @@
|
|
1
|
+
require_relative '../spec_helper'
|
2
|
+
require 'openssl'
|
3
|
+
|
4
|
+
describe Angelo::Server do
|
5
|
+
|
6
|
+
describe 'serving static files' do
|
7
|
+
|
8
|
+
let(:test_css_etag) do
|
9
|
+
fs = File::Stat.new File.join(TEST_APP_ROOT, 'public', 'test.css')
|
10
|
+
OpenSSL::Digest::SHA.hexdigest fs.ino.to_s + fs.size.to_s + fs.mtime.to_s
|
11
|
+
end
|
12
|
+
|
13
|
+
define_app do
|
14
|
+
|
15
|
+
@root = TEST_APP_ROOT
|
16
|
+
|
17
|
+
get '/test.html' do
|
18
|
+
'you should not see this'
|
19
|
+
end
|
20
|
+
|
21
|
+
end
|
22
|
+
|
23
|
+
it 'serves static files for gets' do
|
24
|
+
get '/test.css'
|
25
|
+
expect(last_response.status).to be(200)
|
26
|
+
expect(last_response.headers['Content-Type']).to eq('text/css')
|
27
|
+
expect(last_response.headers['Content-Disposition']).to eq('attachment; filename=test.css')
|
28
|
+
expect(last_response.headers['Content-Length']).to eq('116')
|
29
|
+
expect(last_response.headers['Etag']).to eq(test_css_etag)
|
30
|
+
expect(last_response.body.length).to be(116)
|
31
|
+
expect(last_response.body).to eq(File.read(File.join TEST_APP_ROOT, 'public', 'test.css'))
|
32
|
+
end
|
33
|
+
|
34
|
+
it 'serves headers for static files on head' do
|
35
|
+
head '/test.css'
|
36
|
+
expect(last_response.status).to be(200)
|
37
|
+
expect(last_response.headers['Content-Type']).to eq('text/css')
|
38
|
+
expect(last_response.headers['Content-Disposition']).to eq('attachment; filename=test.css')
|
39
|
+
expect(last_response.headers['Content-Length']).to eq('116')
|
40
|
+
expect(last_response.headers['Etag']).to eq(test_css_etag)
|
41
|
+
expect(last_response.body.length).to be(0)
|
42
|
+
end
|
43
|
+
|
44
|
+
it 'serves static file over route' do
|
45
|
+
get '/test.html'
|
46
|
+
expect(last_response.status).to be(200)
|
47
|
+
expect(last_response.headers['Content-Type']).to eq('text/html')
|
48
|
+
expect(last_response.headers['Content-Disposition']).to eq('attachment; filename=test.html')
|
49
|
+
expect(last_response.body).to eq(File.read(File.join TEST_APP_ROOT, 'public', 'test.html'))
|
50
|
+
end
|
51
|
+
|
52
|
+
it 'not modifieds when if-none-match matched etag' do
|
53
|
+
get '/test.css', {}, {'If-None-Match' => test_css_etag}
|
54
|
+
expect(last_response.status).to be(304)
|
55
|
+
end
|
56
|
+
|
57
|
+
end
|
58
|
+
|
59
|
+
end
|
data/spec/spec_helper.rb
CHANGED
@@ -0,0 +1 @@
|
|
1
|
+
this is a different story
|
@@ -0,0 +1 @@
|
|
1
|
+
setTimeout(function(){ alert('hi'); }, 3000);
|
Binary file
|
File without changes
|
File without changes
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: angelo
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.1.
|
4
|
+
version: 0.1.2
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Kenichi Nakamura
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2014-03-
|
11
|
+
date: 2014-03-06 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: reel
|
@@ -24,6 +24,20 @@ dependencies:
|
|
24
24
|
- - '>='
|
25
25
|
- !ruby/object:Gem::Version
|
26
26
|
version: '0'
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: mime-types
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - '>='
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: '0'
|
34
|
+
type: :runtime
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - '>='
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: '0'
|
27
41
|
description: A Sinatra-esque DSL for Reel
|
28
42
|
email:
|
29
43
|
- kenichi.nakamura@gmail.com
|
@@ -51,11 +65,16 @@ files:
|
|
51
65
|
- spec/angelo/erb_spec.rb
|
52
66
|
- spec/angelo/mustermann_spec.rb
|
53
67
|
- spec/angelo/params_spec.rb
|
54
|
-
- spec/angelo/
|
55
|
-
- spec/angelo/views/layout.html.erb
|
68
|
+
- spec/angelo/static_spec.rb
|
56
69
|
- spec/angelo/websocket_spec.rb
|
57
70
|
- spec/angelo_spec.rb
|
58
71
|
- spec/spec_helper.rb
|
72
|
+
- spec/test_app_root/public/test.css
|
73
|
+
- spec/test_app_root/public/test.html
|
74
|
+
- spec/test_app_root/public/test.js
|
75
|
+
- spec/test_app_root/public/what.png
|
76
|
+
- spec/test_app_root/views/index.html.erb
|
77
|
+
- spec/test_app_root/views/layout.html.erb
|
59
78
|
homepage: https://github.com/kenichi/angelo
|
60
79
|
licenses:
|
61
80
|
- apache
|
@@ -84,9 +103,13 @@ test_files:
|
|
84
103
|
- spec/angelo/erb_spec.rb
|
85
104
|
- spec/angelo/mustermann_spec.rb
|
86
105
|
- spec/angelo/params_spec.rb
|
87
|
-
- spec/angelo/
|
88
|
-
- spec/angelo/views/layout.html.erb
|
106
|
+
- spec/angelo/static_spec.rb
|
89
107
|
- spec/angelo/websocket_spec.rb
|
90
108
|
- spec/angelo_spec.rb
|
91
109
|
- spec/spec_helper.rb
|
92
|
-
|
110
|
+
- spec/test_app_root/public/test.css
|
111
|
+
- spec/test_app_root/public/test.html
|
112
|
+
- spec/test_app_root/public/test.js
|
113
|
+
- spec/test_app_root/public/what.png
|
114
|
+
- spec/test_app_root/views/index.html.erb
|
115
|
+
- spec/test_app_root/views/layout.html.erb
|