lydia 0.1.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.
- checksums.yaml +7 -0
- data/.gitignore +9 -0
- data/.rspec +2 -0
- data/.travis.yml +10 -0
- data/Gemfile +4 -0
- data/LICENSE.txt +21 -0
- data/README.md +56 -0
- data/Rakefile +6 -0
- data/bin/console +14 -0
- data/bin/setup +7 -0
- data/examples/hello_world.rb +6 -0
- data/lib/lydia.rb +10 -0
- data/lib/lydia/application.rb +53 -0
- data/lib/lydia/delegator.rb +12 -0
- data/lib/lydia/filters.rb +52 -0
- data/lib/lydia/halted.rb +9 -0
- data/lib/lydia/helpers.rb +19 -0
- data/lib/lydia/not_found.rb +4 -0
- data/lib/lydia/request.rb +6 -0
- data/lib/lydia/response.rb +33 -0
- data/lib/lydia/route.rb +36 -0
- data/lib/lydia/router.rb +86 -0
- data/lib/lydia/standard_pages.rb +18 -0
- data/lib/lydia/templates.rb +10 -0
- data/lib/lydia/version.rb +3 -0
- data/lydia.gemspec +31 -0
- data/spec/application_spec.rb +66 -0
- data/spec/delegator_spec.rb +31 -0
- data/spec/filters_spec.rb +89 -0
- data/spec/helpers_spec.rb +45 -0
- data/spec/middleware_spec.rb +41 -0
- data/spec/response_spec.rb +128 -0
- data/spec/router_spec.rb +297 -0
- data/spec/spec_helper.rb +4 -0
- data/spec/templates/template.erb +1 -0
- data/spec/templates_spec.rb +23 -0
- metadata +187 -0
@@ -0,0 +1,18 @@
|
|
1
|
+
module Lydia
|
2
|
+
module StandardPages
|
3
|
+
def not_found(env = nil)
|
4
|
+
message = "<html><body><h1>Not Found</h1><p>No route matches #{env['REQUEST_METHOD']} #{env['PATH_INFO']}</p></body></html>"
|
5
|
+
[404, {'Content-Type' => 'text/html', 'Content-Length' => message.length.to_s}, [message]]
|
6
|
+
end
|
7
|
+
|
8
|
+
def internal_server_error(_env = nil, exception = nil)
|
9
|
+
message = "<html><body><h1>Internal server error</h1><p>#{exception}</p></body></html>"
|
10
|
+
[500, {'Content-Type' => 'text/html', 'Content-Length' => message.length.to_s}, [message]]
|
11
|
+
end
|
12
|
+
|
13
|
+
def halted(_env = nil)
|
14
|
+
message = "<html><body><h1>Application halted</h1></body></html>"
|
15
|
+
[500, {'Content-Type' => 'text/html', 'Content-Length' => message.length.to_s}, [message]]
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
data/lydia.gemspec
ADDED
@@ -0,0 +1,31 @@
|
|
1
|
+
# coding: utf-8
|
2
|
+
lib = File.expand_path('../lib', __FILE__)
|
3
|
+
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
4
|
+
require 'lydia/version'
|
5
|
+
|
6
|
+
Gem::Specification.new do |spec|
|
7
|
+
spec.name = 'lydia'
|
8
|
+
spec.version = Lydia::VERSION
|
9
|
+
spec.authors = ['Mirko Mignini']
|
10
|
+
spec.email = ['mirko.mignini@gmail.com']
|
11
|
+
|
12
|
+
spec.summary = %q{Lightweight, fast and easy to use small ruby web framework.}
|
13
|
+
spec.description = %q{Lightweight, fast and easy to use small ruby web framework.}
|
14
|
+
spec.homepage = 'https://github.com/MirkoMignini/lydia'
|
15
|
+
spec.license = 'MIT'
|
16
|
+
|
17
|
+
spec.files = `git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) }
|
18
|
+
spec.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
|
19
|
+
spec.bindir = 'exe'
|
20
|
+
spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
|
21
|
+
spec.require_paths = ['lib']
|
22
|
+
|
23
|
+
spec.add_development_dependency 'bundler', '~> 1.10'
|
24
|
+
spec.add_development_dependency 'rspec'
|
25
|
+
spec.add_development_dependency 'coveralls'
|
26
|
+
spec.add_development_dependency 'rake'
|
27
|
+
spec.add_development_dependency 'rack-test'
|
28
|
+
|
29
|
+
spec.add_dependency 'rack'
|
30
|
+
spec.add_dependency 'tilt'
|
31
|
+
end
|
@@ -0,0 +1,66 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
require 'rack/test'
|
3
|
+
require 'rack/response'
|
4
|
+
require 'erb'
|
5
|
+
require 'lydia/application'
|
6
|
+
|
7
|
+
describe "Application" do
|
8
|
+
include Rack::Test::Methods
|
9
|
+
|
10
|
+
class API < Lydia::Application
|
11
|
+
get '/users' do
|
12
|
+
'Api call'
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
class TestApplication < Lydia::Application
|
17
|
+
use Rack::Lint
|
18
|
+
|
19
|
+
map '/api' do
|
20
|
+
run API
|
21
|
+
end
|
22
|
+
|
23
|
+
get '/response' do
|
24
|
+
respond_to?(:response).to_s
|
25
|
+
end
|
26
|
+
|
27
|
+
get '/empty' do
|
28
|
+
end
|
29
|
+
|
30
|
+
get '/rack_response' do
|
31
|
+
Rack::Response.new(['Rack response'])
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
def app
|
36
|
+
TestApplication
|
37
|
+
end
|
38
|
+
|
39
|
+
context 'Composition' do
|
40
|
+
it 'GET /api/users' do
|
41
|
+
get '/api/users'
|
42
|
+
expect(last_response.status).to eq(200)
|
43
|
+
expect(last_response.body).to eq('Api call')
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
context 'Response' do
|
48
|
+
it 'Response is handled' do
|
49
|
+
get '/response'
|
50
|
+
expect(last_response.status).to eq(200)
|
51
|
+
expect(last_response.body).to eq('true')
|
52
|
+
end
|
53
|
+
|
54
|
+
it 'Returns empty' do
|
55
|
+
get '/empty'
|
56
|
+
expect(last_response.status).to eq(200)
|
57
|
+
expect(last_response.body).to eq('')
|
58
|
+
end
|
59
|
+
|
60
|
+
it 'Returns Rack::Response' do
|
61
|
+
get '/rack_response'
|
62
|
+
expect(last_response.status).to eq(200)
|
63
|
+
expect(last_response.body).to eq('Rack response')
|
64
|
+
end
|
65
|
+
end
|
66
|
+
end
|
@@ -0,0 +1,31 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
require 'rack/test'
|
3
|
+
require 'lydia/delegator'
|
4
|
+
|
5
|
+
extend Lydia::Delegator
|
6
|
+
|
7
|
+
describe 'Delegator' do
|
8
|
+
include Rack::Test::Methods
|
9
|
+
|
10
|
+
class TestDelegator
|
11
|
+
extend Lydia::Delegator
|
12
|
+
|
13
|
+
get '/hello' do
|
14
|
+
'Hello world!'
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
def app
|
19
|
+
Lydia::Application.new
|
20
|
+
end
|
21
|
+
|
22
|
+
it 'Delegator initialize correctly' do
|
23
|
+
expect(1).to eq(1)
|
24
|
+
end
|
25
|
+
|
26
|
+
it 'Delegates to Application' do
|
27
|
+
get '/hello'
|
28
|
+
expect(last_response.status).to eq(200)
|
29
|
+
expect(last_response.body).to eq('Hello world!')
|
30
|
+
end
|
31
|
+
end
|
@@ -0,0 +1,89 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
require 'rack/test'
|
3
|
+
require 'lydia/application'
|
4
|
+
|
5
|
+
describe "Filters" do
|
6
|
+
include Rack::Test::Methods
|
7
|
+
|
8
|
+
class TestFilters < Lydia::Application
|
9
|
+
|
10
|
+
before do
|
11
|
+
@filter = 'before'
|
12
|
+
end
|
13
|
+
|
14
|
+
after do
|
15
|
+
@filter = 'after'
|
16
|
+
end
|
17
|
+
|
18
|
+
get '/filter' do
|
19
|
+
@filter
|
20
|
+
end
|
21
|
+
|
22
|
+
redirect '/redirect', to: '/redirected'
|
23
|
+
|
24
|
+
get '/redirected' do
|
25
|
+
'redirected'
|
26
|
+
end
|
27
|
+
|
28
|
+
namespace '/namespace' do
|
29
|
+
before do
|
30
|
+
@filter_nested = 'before'
|
31
|
+
end
|
32
|
+
|
33
|
+
after do
|
34
|
+
@filter_nested = 'after'
|
35
|
+
end
|
36
|
+
|
37
|
+
redirect '/redirect', to: '/redirected'
|
38
|
+
|
39
|
+
get '/redirected' do
|
40
|
+
'redirected in namespace'
|
41
|
+
end
|
42
|
+
|
43
|
+
get '/filter' do
|
44
|
+
"#{@filter} #{@filter_nested}"
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
def app
|
50
|
+
TestFilters.new
|
51
|
+
end
|
52
|
+
|
53
|
+
context 'Before & after' do
|
54
|
+
context 'Root' do
|
55
|
+
it 'works without pattern' do
|
56
|
+
get '/filter'
|
57
|
+
expect(last_response.status).to eq(200)
|
58
|
+
expect(last_response.body).to eq('before')
|
59
|
+
end
|
60
|
+
end
|
61
|
+
|
62
|
+
context 'Namespace' do
|
63
|
+
it 'works without pattern' do
|
64
|
+
get '/namespace/filter'
|
65
|
+
expect(last_response.status).to eq(200)
|
66
|
+
expect(last_response.body).to eq('before before')
|
67
|
+
end
|
68
|
+
end
|
69
|
+
end
|
70
|
+
|
71
|
+
context 'Redirect' do
|
72
|
+
context 'Root' do
|
73
|
+
it 'redirects' do
|
74
|
+
get '/redirect'
|
75
|
+
expect(last_response.status).to eq(200)
|
76
|
+
expect(last_response.body).to eq('redirected')
|
77
|
+
end
|
78
|
+
end
|
79
|
+
|
80
|
+
context 'Namespace' do
|
81
|
+
it 'redirects' do
|
82
|
+
get '/namespace/redirect'
|
83
|
+
expect(last_response.status).to eq(200)
|
84
|
+
expect(last_response.body).to eq('redirected in namespace')
|
85
|
+
end
|
86
|
+
end
|
87
|
+
end
|
88
|
+
|
89
|
+
end
|
@@ -0,0 +1,45 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
require 'rack/test'
|
3
|
+
require 'lydia/application'
|
4
|
+
|
5
|
+
describe "Helpers" do
|
6
|
+
include Rack::Test::Methods
|
7
|
+
|
8
|
+
class TestHelpers < Lydia::Application
|
9
|
+
get '/content_type' do
|
10
|
+
content_type 'application/json'
|
11
|
+
'body'
|
12
|
+
end
|
13
|
+
|
14
|
+
get '/redirect' do
|
15
|
+
redirect '/new_url'
|
16
|
+
end
|
17
|
+
|
18
|
+
get '/params' do
|
19
|
+
params['key']
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
def app
|
24
|
+
TestHelpers.new
|
25
|
+
end
|
26
|
+
|
27
|
+
it 'responds to content_type' do
|
28
|
+
get '/content_type'
|
29
|
+
expect(last_response.status).to eq(200)
|
30
|
+
expect(last_response.header['Content-Type']).to eq('application/json')
|
31
|
+
expect(last_response.body).to eq('body')
|
32
|
+
end
|
33
|
+
|
34
|
+
it 'Handles redirect' do
|
35
|
+
get '/redirect'
|
36
|
+
expect(last_response.status).to eq(302)
|
37
|
+
expect(last_response.body).to eq('/new_url')
|
38
|
+
end
|
39
|
+
|
40
|
+
it 'responds to params' do
|
41
|
+
get '/params', {key: 'value'}
|
42
|
+
expect(last_response.status).to eq(200)
|
43
|
+
expect(last_response.body).to eq('value')
|
44
|
+
end
|
45
|
+
end
|
@@ -0,0 +1,41 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
require 'rack/test'
|
3
|
+
require 'erb'
|
4
|
+
require 'json'
|
5
|
+
require 'lydia/application'
|
6
|
+
|
7
|
+
describe "Middleware" do
|
8
|
+
include Rack::Test::Methods
|
9
|
+
|
10
|
+
class UpcaseMiddleware
|
11
|
+
def initialize(app)
|
12
|
+
@app = app
|
13
|
+
end
|
14
|
+
|
15
|
+
def call(env)
|
16
|
+
result = @app.call(env)
|
17
|
+
result[2].body[0] = result[2].body[0].upcase
|
18
|
+
result
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
class TestMiddleware < Lydia::Application
|
23
|
+
use UpcaseMiddleware
|
24
|
+
|
25
|
+
get '/hello' do
|
26
|
+
'Hello world!'
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
def app
|
31
|
+
TestMiddleware.new
|
32
|
+
end
|
33
|
+
|
34
|
+
context 'Middleware stack' do
|
35
|
+
it 'is correctly handled' do
|
36
|
+
get '/hello'
|
37
|
+
expect(last_response.status).to eq(200)
|
38
|
+
expect(last_response.body).to eq('HELLO WORLD!')
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
@@ -0,0 +1,128 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
require 'lydia/response'
|
3
|
+
|
4
|
+
describe 'Response' do
|
5
|
+
let (:response) { Lydia::Response.new }
|
6
|
+
|
7
|
+
context 'initialization' do
|
8
|
+
it 'is created' do
|
9
|
+
expect(response).to_not be_nil
|
10
|
+
end
|
11
|
+
|
12
|
+
it 'contains default content type' do
|
13
|
+
expect(response.headers).to include('Content-Type' => 'text/html')
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
context 'build' do
|
18
|
+
it 'responds to build' do
|
19
|
+
expect(response).to respond_to(:build)
|
20
|
+
end
|
21
|
+
|
22
|
+
it 'builds using a string (body)' do
|
23
|
+
body = 'Hello world!'
|
24
|
+
result = response.build(body)
|
25
|
+
expect(result).to_not be_nil
|
26
|
+
expect(result).to be_an(Array)
|
27
|
+
expect(result[0]).to eq(200)
|
28
|
+
expect(result[1]).to include('Content-Type' => 'text/html')
|
29
|
+
expect(result[1]).to include('Content-Length' => body.length.to_s)
|
30
|
+
expect(result[2].body).to be_an(Array)
|
31
|
+
expect(result[2].body[0]).to eq(body)
|
32
|
+
end
|
33
|
+
|
34
|
+
it 'builds using a fixnum (status)' do
|
35
|
+
status = 204
|
36
|
+
result = response.build(status)
|
37
|
+
expect(result).to_not be_nil
|
38
|
+
expect(result).to be_an(Array)
|
39
|
+
expect(result[0]).to eq(204)
|
40
|
+
expect(result[1]).to_not include('Content-Type')
|
41
|
+
expect(result[1]).to_not include('Content-Length')
|
42
|
+
expect(result[2]).to be_an(Array)
|
43
|
+
expect(result[2][0]).to be_nil
|
44
|
+
end
|
45
|
+
|
46
|
+
it 'builds using a hash (body)' do
|
47
|
+
body = {hello: 'world'}
|
48
|
+
result = response.build(body)
|
49
|
+
expect(result).to_not be_nil
|
50
|
+
expect(result).to be_an(Array)
|
51
|
+
expect(result[0]).to eq(200)
|
52
|
+
expect(result[1]).to include('Content-Type' => 'application/json')
|
53
|
+
expect(result[1]).to include('Content-Length' => body.to_json.length.to_s)
|
54
|
+
expect(result[2].body).to be_an(Array)
|
55
|
+
expect(result[2].body[0]).to eq(body.to_json)
|
56
|
+
end
|
57
|
+
|
58
|
+
it 'builds using an array of two (body is array)' do
|
59
|
+
body = [201, ['Body']]
|
60
|
+
result = response.build(body)
|
61
|
+
expect(result).to_not be_nil
|
62
|
+
expect(result).to be_an(Array)
|
63
|
+
expect(result[0]).to eq(201)
|
64
|
+
expect(result[1]).to include('Content-Type' => 'text/html')
|
65
|
+
expect(result[1]).to include('Content-Length' => body[1][0].length.to_s)
|
66
|
+
expect(result[2].body).to be_an(Array)
|
67
|
+
expect(result[2].body[0]).to eq(body[1][0])
|
68
|
+
end
|
69
|
+
|
70
|
+
it 'builds using an array of two (body is noy an array)' do
|
71
|
+
body = [201, 'Body']
|
72
|
+
result = response.build(body)
|
73
|
+
expect(result).to_not be_nil
|
74
|
+
expect(result).to be_an(Array)
|
75
|
+
expect(result[0]).to eq(201)
|
76
|
+
expect(result[1]).to include('Content-Type' => 'text/html')
|
77
|
+
expect(result[1]).to include('Content-Length' => body[1].length.to_s)
|
78
|
+
expect(result[2].body).to be_an(Array)
|
79
|
+
expect(result[2].body[0]).to eq(body[1])
|
80
|
+
end
|
81
|
+
|
82
|
+
it 'builds using an array of three' do
|
83
|
+
body = [201, {'Authentication' => '12345'}, 'Body']
|
84
|
+
result = response.build(body)
|
85
|
+
expect(result).to_not be_nil
|
86
|
+
expect(result).to be_an(Array)
|
87
|
+
expect(result[0]).to eq(201)
|
88
|
+
expect(result[1]).to include('Content-Type' => 'text/html')
|
89
|
+
expect(result[1]).to include('Content-Length' => body[2].length.to_s)
|
90
|
+
expect(result[1]).to include('Authentication' => '12345')
|
91
|
+
expect(result[2].body).to be_an(Array)
|
92
|
+
expect(result[2].body[0]).to eq(body[2])
|
93
|
+
end
|
94
|
+
|
95
|
+
class Stream
|
96
|
+
def each
|
97
|
+
10.times { |i| yield "#{i}" }
|
98
|
+
end
|
99
|
+
end
|
100
|
+
|
101
|
+
context 'Stream' do
|
102
|
+
|
103
|
+
it 'builds a valid stream object' do
|
104
|
+
stream = ''
|
105
|
+
Stream.new.each{ |i| stream += i }
|
106
|
+
expect(stream).to eq('0123456789')
|
107
|
+
end
|
108
|
+
|
109
|
+
it 'builds using an object that responds to :each' do
|
110
|
+
result = response.build(Stream.new)
|
111
|
+
expect(result).to_not be_nil
|
112
|
+
expect(result).to be_an(Array)
|
113
|
+
expect(result[0]).to eq(200)
|
114
|
+
expect(result[1]).to include('Content-Type' => 'text/html')
|
115
|
+
expect(result[1]).to include('Content-Length')
|
116
|
+
expect(result[2].body).to be_an(Array)
|
117
|
+
expect(result[2].body[0]).to_not be_nil
|
118
|
+
end
|
119
|
+
|
120
|
+
end
|
121
|
+
|
122
|
+
it 'returns ArgumentError if object is not allowed' do
|
123
|
+
expect {
|
124
|
+
response.build(nil)
|
125
|
+
}.to raise_error(ArgumentError)
|
126
|
+
end
|
127
|
+
end
|
128
|
+
end
|