lydia 0.1.3 → 0.1.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.
@@ -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