lydia 0.1.3 → 0.1.4

Sign up to get free protection for your applications and to get access to all the features.
@@ -6,4 +6,4 @@ module Lydia
6
6
  super
7
7
  end
8
8
  end
9
- end
9
+ end
@@ -3,17 +3,17 @@ module Lydia
3
3
  def content_type(content)
4
4
  @response.header['Content-Type'] = content
5
5
  end
6
-
6
+
7
7
  def redirect(target, status = 302)
8
8
  [status, target]
9
9
  end
10
-
10
+
11
11
  def params
12
12
  @request.params
13
13
  end
14
-
14
+
15
15
  def send_file(_path, _mime_type = nil)
16
- raise NotImplementedError.new
16
+ raise(NotImplementedError, 'Send file not yet implemented.')
17
17
  end
18
18
  end
19
- end
19
+ end
@@ -1,4 +1,4 @@
1
1
  module Lydia
2
- class NotFound < StandardError
2
+ class NotFound < StandardError
3
3
  end
4
4
  end
@@ -1,6 +1,6 @@
1
1
  require 'rack/request'
2
2
 
3
3
  module Lydia
4
- class Request < Rack::Request
4
+ class Request < Rack::Request
5
5
  end
6
- end
6
+ end
@@ -2,46 +2,58 @@ require 'rack/response'
2
2
  require 'json'
3
3
 
4
4
  module Lydia
5
- class Response < Rack::Response
5
+ class Response < Rack::Response
6
6
  def initialize(*)
7
7
  super
8
8
  headers['Content-Type'] = 'text/html' if headers['Content-Type'].nil?
9
9
  end
10
-
10
+
11
11
  def build(input)
12
- case input.class.to_s
13
- when 'String'
14
- write input
15
- when 'Array'
16
- @status = input.first
17
- write input.last.is_a?(Array) ? input.last[0] : input.last
18
- headers.merge!(input[1]) if input.count == 3
19
- when 'Fixnum'
20
- @status = input
21
- when 'Hash'
22
- headers['Content-Type'] = 'application/json'
23
- write input.to_json
24
- else
25
- if input.respond_to?(:each)
26
- write input
27
- else
28
- raise ArgumentError.new("#{input.class} is not a valid allowed return type")
29
- end
12
+ input_class = input.class.to_s.downcase
13
+ if %w(string array fixnum hash).include?(input_class)
14
+ send("build_#{input_class}", input)
15
+ else
16
+ build_default(input)
30
17
  end
31
18
  finish
32
19
  end
33
-
20
+
34
21
  def finish(&block)
35
22
  @block = block
36
-
37
23
  if [204, 205, 304].include?(status.to_i)
38
- headers.delete 'Content-Length'
39
- headers.delete 'Content-Type'
24
+ headers.delete('Content-Length')
25
+ headers.delete('Content-Type')
40
26
  close
41
27
  [status.to_i, header, []]
42
28
  else
43
29
  [status.to_i, header, @body]
44
30
  end
45
- end
31
+ end
32
+
33
+ private
34
+
35
+ def build_string(input)
36
+ write(input)
37
+ end
38
+
39
+ def build_array(input)
40
+ @status, *, body = input
41
+ write(body.is_a?(Array) ? body[0] : body)
42
+ headers.merge!(input[1]) if input.count == 3
43
+ end
44
+
45
+ def build_fixnum(input)
46
+ @status = input
47
+ end
48
+
49
+ def build_hash(input)
50
+ headers['Content-Type'] = 'application/json'
51
+ write(input.to_json)
52
+ end
53
+
54
+ def build_default(input)
55
+ return write(input) if input.respond_to?(:each)
56
+ raise(ArgumentError, "#{input.class} is not a valid allowed return type")
57
+ end
46
58
  end
47
59
  end
@@ -1,9 +1,9 @@
1
1
  module Lydia
2
- class Route
2
+ class Route
3
3
  attr_reader :regexp, :params, :request_method, :namespace, :pattern, :options, :block
4
-
5
- WILDCARD_REGEX = /\/\*(.*)/.freeze
6
- NAMED_SEGMENTS_REGEX = /\/([^\/]*):([^:$\/]+)/.freeze
4
+
5
+ WILDCARD_REGEX = %r{\/\*(.*)}
6
+ NAMED_SEGMENTS_REGEX = %r{\/([^\/]*):([^:$\/]+)}
7
7
 
8
8
  def initialize(request_method, namespace, pattern, options = {}, &block)
9
9
  @request_method = request_method
@@ -11,27 +11,35 @@ module Lydia
11
11
  @pattern = pattern
12
12
  @options = options
13
13
  @block = block
14
- if pattern.is_a? String
15
- path = (namespace || '') + pattern
16
- if path.match(WILDCARD_REGEX)
17
- result = path.gsub(WILDCARD_REGEX, '(?:/(.*)|)')
18
- elsif path.match(NAMED_SEGMENTS_REGEX)
19
- result = path.gsub(NAMED_SEGMENTS_REGEX, '/\1(?<\2>[^.$/]+)')
20
- else
21
- result = path
22
- end
23
- @regexp = Regexp.new("\\A#{result}\\z")
24
- elsif pattern.is_a?(Regexp)
25
- @regexp = Regexp.new((namespace || '') + pattern.to_s)
26
- else
27
- raise ArgumentError.new('Pattern must be a string or a regex')
28
- end
14
+ @regexp = init_regexp
29
15
  end
30
16
 
31
17
  def match?(env)
32
- match = @regexp.match("#{env['PATH_INFO']}")
33
- @params = Hash[match.names.map(&:to_sym).zip(match.captures)] if match && match.names.size
18
+ match = @regexp.match((env['PATH_INFO']).to_s)
19
+ if match && match.names.size
20
+ @params = Hash[match.names.map(&:to_sym).zip(match.captures)]
21
+ end
34
22
  match
35
23
  end
36
- end
24
+
25
+ private
26
+
27
+ def init_regexp
28
+ return regexp_from_string if @pattern.is_a? String
29
+ return Regexp.new((@namespace || '') + @pattern.to_s) if @pattern.is_a?(Regexp)
30
+ raise(ArgumentError, 'Pattern must be a string or a regex')
31
+ end
32
+
33
+ def regexp_from_string
34
+ path = (@namespace || '') + @pattern
35
+ result = if path.match(WILDCARD_REGEX)
36
+ path.gsub(WILDCARD_REGEX, '(?:/(.*)|)')
37
+ elsif path.match(NAMED_SEGMENTS_REGEX)
38
+ path.gsub(NAMED_SEGMENTS_REGEX, '/\1(?<\2>[^.$/]+)')
39
+ else
40
+ path
41
+ end
42
+ Regexp.new("\\A#{result}\\z")
43
+ end
44
+ end
37
45
  end
@@ -8,20 +8,20 @@ require 'rack/response'
8
8
  module Lydia
9
9
  class Router
10
10
  include StandardPages
11
-
11
+
12
12
  attr_reader :request, :response, :env
13
-
14
- class << self
13
+
14
+ class << self
15
15
  def routes
16
16
  @routes ||= Hash.new { |h, k| h[k] = [] }
17
17
  end
18
-
18
+
19
19
  %w(HEAD GET PATCH PUT POST DELETE OPTIONS).each do |request_method|
20
20
  define_method(request_method.downcase) do |pattern, options = {}, &block|
21
21
  routes[request_method] << Route.new(request_method, @namespace, pattern, options, &block)
22
22
  end
23
23
  end
24
-
24
+
25
25
  def namespace(pattern, _options = {})
26
26
  prev_namespace = @namespace ||= ''
27
27
  @namespace += pattern
@@ -29,58 +29,57 @@ module Lydia
29
29
  @namespace = prev_namespace
30
30
  end
31
31
  end
32
-
32
+
33
33
  def next_route
34
34
  throw :next_route
35
- end
36
-
35
+ end
36
+
37
37
  def halt(input = nil)
38
- raise Halted.new(input || halted)
38
+ raise(Halted.new(input || halted), 'Halt')
39
39
  end
40
-
40
+
41
41
  def call(env)
42
42
  dup._call(env)
43
43
  end
44
-
44
+
45
45
  def _call(env)
46
46
  @env = env
47
47
  @request = new_request(env)
48
48
  @response = new_response
49
49
  process
50
50
  end
51
-
51
+
52
52
  def new_request(env)
53
53
  Rack::Request.new(env)
54
54
  end
55
-
55
+
56
56
  def new_response(body = [], status = 200, header = {})
57
57
  Rack::Response.new(body, status, header)
58
58
  end
59
-
59
+
60
60
  def process
61
61
  dispatch(env)
62
- rescue NotFound
63
- not_found(env)
64
- rescue Halted => exception
65
- exception.content
66
- rescue StandardError => exception
67
- internal_server_error(env, exception)
62
+ rescue NotFound
63
+ not_found(env)
64
+ rescue Halted => exception
65
+ exception.content
66
+ rescue StandardError => exception
67
+ internal_server_error(env, exception)
68
68
  end
69
-
69
+
70
70
  def routes
71
71
  self.class.routes
72
72
  end
73
-
73
+
74
74
  def dispatch(env)
75
75
  routes[env['REQUEST_METHOD']].each do |route|
76
- if route.match?(env)
77
- @request.params.merge!(route.params) if route.params
78
- catch(:next_route) do
79
- return instance_eval(&route.block)
80
- end
76
+ next unless route.match?(env)
77
+ @request.params.merge!(route.params) if route.params
78
+ catch(:next_route) do
79
+ return instance_eval(&route.block)
81
80
  end
82
81
  end
83
- raise NotFound
84
- end
82
+ raise(NotFound, 'Not found')
83
+ end
85
84
  end
86
- end
85
+ end
@@ -1,18 +1,21 @@
1
- module Lydia
1
+ module Lydia
2
2
  module StandardPages
3
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]]
4
+ message = '<html><body>'\
5
+ '<h1>Not Found</h1>'\
6
+ "<p>No route matches #{env['REQUEST_METHOD']} #{env['PATH_INFO']}</p>"\
7
+ '</body></html>'
8
+ [404, { 'Content-Type' => 'text/html', 'Content-Length' => message.length.to_s }, [message]]
6
9
  end
7
10
 
8
11
  def internal_server_error(_env = nil, exception = nil)
9
12
  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]]
13
+ [500, { 'Content-Type' => 'text/html', 'Content-Length' => message.length.to_s }, [message]]
11
14
  end
12
-
15
+
13
16
  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]]
17
+ message = '<html><body><h1>Application halted</h1></body></html>'
18
+ [500, { 'Content-Type' => 'text/html', 'Content-Length' => message.length.to_s }, [message]]
16
19
  end
17
20
  end
18
21
  end
@@ -1,3 +1,3 @@
1
1
  module Lydia
2
- VERSION = "0.1.3"
2
+ VERSION = '0.1.4'.freeze
3
3
  end
@@ -9,12 +9,14 @@ Gem::Specification.new do |spec|
9
9
  spec.authors = ['Mirko Mignini']
10
10
  spec.email = ['mirko.mignini@gmail.com']
11
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.}
12
+ spec.summary = 'Lightweight, fast and easy to use small ruby web framework.'
13
+ spec.description = 'Lightweight, fast and easy to use small ruby web framework.'
14
14
  spec.homepage = 'https://github.com/MirkoMignini/lydia'
15
15
  spec.license = 'MIT'
16
16
 
17
- spec.files = `git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) }
17
+ spec.files = `git ls-files -z`.split("\x0").reject do |f|
18
+ f.match(%r{^(test|spec|features)/})
19
+ end
18
20
  spec.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
19
21
  spec.bindir = 'exe'
20
22
  spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
@@ -26,7 +28,9 @@ Gem::Specification.new do |spec|
26
28
  spec.add_development_dependency 'rake'
27
29
  spec.add_development_dependency 'rack-test'
28
30
  spec.add_development_dependency 'haml'
29
-
30
- spec.add_dependency 'rack', '~> 1.6.4'
31
+ spec.add_development_dependency 'rubocop'
32
+ spec.add_development_dependency 'rubocop-rspec'
33
+
34
+ spec.add_dependency 'rack', '~> 2.0.1'
31
35
  spec.add_dependency 'tilt'
32
36
  end
@@ -4,7 +4,7 @@ require 'rack/response'
4
4
  require 'erb'
5
5
  require 'lydia/application'
6
6
 
7
- describe "Application" do
7
+ describe 'Application' do
8
8
  include Rack::Test::Methods
9
9
 
10
10
  class API < Lydia::Application
@@ -12,30 +12,30 @@ describe "Application" do
12
12
  'Api call'
13
13
  end
14
14
  end
15
-
16
- class TestApplication < Lydia::Application
15
+
16
+ class TestApplication < Lydia::Application
17
17
  use Rack::Lint
18
18
 
19
19
  map '/api' do
20
20
  run API.new
21
21
  end
22
-
22
+
23
23
  get '/response' do
24
24
  respond_to?(:response).to_s
25
- end
26
-
25
+ end
26
+
27
27
  get '/empty' do
28
28
  end
29
-
29
+
30
30
  get '/rack_response' do
31
31
  Rack::Response.new(['Rack response'])
32
32
  end
33
33
  end
34
-
34
+
35
35
  def app
36
36
  TestApplication.new
37
37
  end
38
-
38
+
39
39
  context 'Composition' do
40
40
  it 'GET /api/users' do
41
41
  get '/api/users'
@@ -43,24 +43,24 @@ describe "Application" do
43
43
  expect(last_response.body).to eq('Api call')
44
44
  end
45
45
  end
46
-
47
- context 'Response' do
46
+
47
+ context 'Response' do
48
48
  it 'Response is handled' do
49
49
  get '/response'
50
50
  expect(last_response.status).to eq(200)
51
51
  expect(last_response.body).to eq('true')
52
52
  end
53
-
53
+
54
54
  it 'Returns empty' do
55
55
  get '/empty'
56
56
  expect(last_response.status).to eq(200)
57
- expect(last_response.body).to eq('')
57
+ expect(last_response.body).to eq('')
58
58
  end
59
-
59
+
60
60
  it 'Returns Rack::Response' do
61
61
  get '/rack_response'
62
62
  expect(last_response.status).to eq(200)
63
- expect(last_response.body).to eq('Rack response')
63
+ expect(last_response.body).to eq('Rack response')
64
64
  end
65
65
  end
66
- end
66
+ end