chespirito 0.0.2 → 0.0.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.
- checksums.yaml +4 -4
- data/README.md +10 -8
- data/chespirito.gemspec +1 -1
- data/lib/chespirito/app.rb +15 -13
- data/lib/chespirito/controller.rb +1 -1
- data/lib/chespirito/request.rb +22 -1
- data/lib/chespirito/routes/route.rb +23 -0
- data/lib/chespirito/routes/route_constraint_checker.rb +33 -0
- data/lib/chespirito/routes/route_utils.rb +14 -0
- data/lib/chespirito/routes/router.rb +65 -0
- metadata +10 -7
- data/lib/chespirito/router.rb +0 -34
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: c26d5cfd95f22fdb7fa89e0f16c36cc551f757c4009c42dbd36c95798f27c252
|
4
|
+
data.tar.gz: '09c340a8e1776bf4d33e578ba6475110d84703d2c5a0fc79b3bfff6f45859a75'
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 75895b71b94768410da2bae31f1969dc7fde2b374c6d45ca9128049b97d7b3571163fe56ebb3f54a36f0f6c0b38cd178d9157dbba71abe403a30e8eeeb9c24d7
|
7
|
+
data.tar.gz: 21684e74e4478c61fe5f56b85c4a31d72e95489fb5a3ebb68a19cada1e46dca52b89e1aac2502632d15b85494cb66e6cc57b769196fe1b01f5649bfb2ea98617
|
data/README.md
CHANGED
@@ -8,12 +8,13 @@
|
|
8
8
|
[](https://github.com/rubocop/rubocop)
|
9
9
|
[](https://rubystyle.guide)
|
10
10
|
```
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
|
15
|
-
|
16
|
-
|
11
|
+
( ) _ _ ( )_
|
12
|
+
___ | |__ __ ___ _ _ (_) _ __ (_)| ,_) _
|
13
|
+
/'___)| _ `\ /'__`\/',__)( '_`\ | |( '__)| || | /'_`\
|
14
|
+
( (___ | | | |( ___/\__, \| (_) )| || | | || |_ ( (_) )
|
15
|
+
`\____)(_) (_)`\____)(____/| ,__/'(_)(_) (_)`\__)`\___/'
|
16
|
+
| |
|
17
|
+
(_)
|
17
18
|
```
|
18
19
|
|
19
20
|
[chespirito](https://rubygems.org/gems/chespirito) is a dead simple, yet Rack-compatible, web framework written in Ruby.
|
@@ -54,6 +55,7 @@ Usage: make <target>
|
|
54
55
|
## Boostrapping an application using Chespirito and Adelnor
|
55
56
|
|
56
57
|
1. Install the gems:
|
58
|
+
|
57
59
|
```bash
|
58
60
|
$ gem install chespirito adelnor
|
59
61
|
```
|
@@ -89,7 +91,7 @@ class HelloController < Chespirito::Controller
|
|
89
91
|
end
|
90
92
|
```
|
91
93
|
|
92
|
-
4. Run the app using Adelnor (or you can choose
|
94
|
+
4. Run the app using Adelnor (or you can choose another web server like Puma, Unicorn, etc):
|
93
95
|
|
94
96
|
```ruby
|
95
97
|
Adelnor::Server.run MyApp.application, 3000
|
@@ -99,4 +101,4 @@ Adelnor::Server.run MyApp.application, 3000
|
|
99
101
|
|
100
102
|
----
|
101
103
|
|
102
|
-
[ASCII art generator](http://
|
104
|
+
[ASCII art generator](http://www.network-science.de/ascii/)
|
data/chespirito.gemspec
CHANGED
@@ -2,7 +2,7 @@
|
|
2
2
|
|
3
3
|
Gem::Specification.new do |spec|
|
4
4
|
spec.name = 'chespirito'
|
5
|
-
spec.version = '0.0.
|
5
|
+
spec.version = '0.0.4'
|
6
6
|
spec.summary = 'Chespirito Ruby web framework'
|
7
7
|
spec.description = 'A dead simple, yet Rack-compatible, web framework written in Ruby'
|
8
8
|
spec.authors = ['Leandro Proença']
|
data/lib/chespirito/app.rb
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
require_relative './request'
|
4
|
-
require_relative './router'
|
4
|
+
require_relative './routes/router'
|
5
5
|
|
6
6
|
module Chespirito
|
7
7
|
class App
|
@@ -15,23 +15,25 @@ module Chespirito
|
|
15
15
|
new.tap { |app| yield(app) }
|
16
16
|
end
|
17
17
|
|
18
|
-
def register_route(
|
19
|
-
attrs => [verb, path, trait]
|
20
|
-
|
18
|
+
def register_route(verb, path, trait)
|
21
19
|
@router.register_route(verb, path, trait)
|
22
20
|
end
|
23
21
|
|
24
|
-
def
|
22
|
+
def register_system_route(key, trait)
|
23
|
+
@router.register_system_route(key, trait)
|
24
|
+
end
|
25
|
+
|
26
|
+
def dispatch(request) = @router.dispatch(request)
|
25
27
|
|
26
28
|
def call(env)
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
29
|
+
request = ::Chespirito::Request.build(env)
|
30
|
+
response = dispatch(request)
|
31
|
+
|
32
|
+
[
|
33
|
+
response.status,
|
34
|
+
response.headers,
|
35
|
+
[response.body]
|
36
|
+
]
|
35
37
|
end
|
36
38
|
end
|
37
39
|
|
@@ -11,7 +11,7 @@ module Chespirito
|
|
11
11
|
@response = ::Chespirito::Response.new
|
12
12
|
end
|
13
13
|
|
14
|
-
def self.
|
14
|
+
def self.process(action, request)
|
15
15
|
new(request)
|
16
16
|
.tap { |controller| controller.send(action.to_sym) }
|
17
17
|
.then { |controller| controller.response }
|
data/lib/chespirito/request.rb
CHANGED
@@ -2,6 +2,7 @@
|
|
2
2
|
|
3
3
|
require 'rack'
|
4
4
|
require 'json'
|
5
|
+
require 'cgi'
|
5
6
|
|
6
7
|
module Chespirito
|
7
8
|
class Request
|
@@ -19,7 +20,9 @@ module Chespirito
|
|
19
20
|
def self.build(env)
|
20
21
|
rack_request = Rack::Request.new(env)
|
21
22
|
|
22
|
-
body_params = rack_request.post? ? (
|
23
|
+
body_params = rack_request.post? ? parse_body_params(rack_request.body.read,
|
24
|
+
rack_request.env['Content-Type']) : {}
|
25
|
+
|
23
26
|
params = rack_request.params.merge(body_params)
|
24
27
|
|
25
28
|
new(
|
@@ -30,5 +33,23 @@ module Chespirito
|
|
30
33
|
cookies: rack_request.cookies
|
31
34
|
)
|
32
35
|
end
|
36
|
+
|
37
|
+
def self.parse_body_params(body_data, content_type)
|
38
|
+
case content_type
|
39
|
+
in 'application/json'; JSON.parse(body_data)
|
40
|
+
in 'application/x-www-form-urlencoded'
|
41
|
+
CGI.unescape(body_data).split('&').each_with_object({}) do |param, hash|
|
42
|
+
key, value = param.split('=')
|
43
|
+
hash[key] = value
|
44
|
+
end
|
45
|
+
else {}
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
def add_param!(name, value)
|
50
|
+
@params ||= {}
|
51
|
+
|
52
|
+
@params[name] = value
|
53
|
+
end
|
33
54
|
end
|
34
55
|
end
|
@@ -0,0 +1,23 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Chespirito
|
4
|
+
class Route
|
5
|
+
attr_reader :verb, :path, :controller_klass, :action
|
6
|
+
|
7
|
+
def initialize(*attrs)
|
8
|
+
@verb, @path, @trait = attrs
|
9
|
+
@controller_klass, @action = @trait
|
10
|
+
end
|
11
|
+
|
12
|
+
def key = "#{@verb} #{@path}"
|
13
|
+
end
|
14
|
+
|
15
|
+
class SystemRoute
|
16
|
+
attr_reader :key, :controller_klass, :action
|
17
|
+
|
18
|
+
def initialize(*attrs)
|
19
|
+
@key, @trait = attrs
|
20
|
+
@controller_klass, @action = @trait
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
@@ -0,0 +1,33 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require_relative './route_utils'
|
4
|
+
|
5
|
+
module Chespirito
|
6
|
+
class RouteConstraintChecker
|
7
|
+
def initialize(request)
|
8
|
+
@request = request
|
9
|
+
end
|
10
|
+
|
11
|
+
def match_route?(route)
|
12
|
+
return false unless route.respond_to?(:path)
|
13
|
+
return false if route_constraints(route).empty?
|
14
|
+
|
15
|
+
route_constraints(route).size == request_constraints(route).size
|
16
|
+
end
|
17
|
+
|
18
|
+
def extract_params(route)
|
19
|
+
return {} unless route.respond_to?(:path)
|
20
|
+
return {} unless match_route?(route)
|
21
|
+
|
22
|
+
route_constraints(route)
|
23
|
+
.zip(request_constraints(route))
|
24
|
+
.to_h
|
25
|
+
end
|
26
|
+
|
27
|
+
def route_constraints(route) = RouteUtils.constraints(route.path)
|
28
|
+
def request_constraints(route) = request_parts - route_parts(route)
|
29
|
+
|
30
|
+
def route_parts(route) = RouteUtils.parts(route.path)
|
31
|
+
def request_parts = RouteUtils.words(@request.path)
|
32
|
+
end
|
33
|
+
end
|
@@ -0,0 +1,14 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Chespirito
|
4
|
+
class RouteUtils
|
5
|
+
class << self
|
6
|
+
def words(path) = path.split("/").delete_if(&:empty?)
|
7
|
+
def constraints(path) = words(path).select(&method(:constraint?)).map(&method(:remove_colon))
|
8
|
+
def parts(path) = words(path).select(&method(:part?))
|
9
|
+
def part?(word) = !constraint?(word)
|
10
|
+
def constraint?(word) = word.start_with?(":")
|
11
|
+
def remove_colon(word) = word.gsub(":", '')
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
@@ -0,0 +1,65 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require_relative './route'
|
4
|
+
require_relative './route_constraint_checker'
|
5
|
+
require_relative '../response'
|
6
|
+
|
7
|
+
module Chespirito
|
8
|
+
class Router
|
9
|
+
def initialize
|
10
|
+
@routes = {}
|
11
|
+
end
|
12
|
+
|
13
|
+
def register_route(*attrs)
|
14
|
+
route = Route.new(*attrs)
|
15
|
+
|
16
|
+
@routes[route.key] = route
|
17
|
+
end
|
18
|
+
|
19
|
+
def register_system_route(*attrs)
|
20
|
+
route = SystemRoute.new(*attrs)
|
21
|
+
|
22
|
+
@routes[route.key] = route
|
23
|
+
end
|
24
|
+
|
25
|
+
def dispatch(request)
|
26
|
+
route = route_for(request)
|
27
|
+
return not_found_response unless route
|
28
|
+
|
29
|
+
route
|
30
|
+
.controller_klass
|
31
|
+
.process(route.action, request)
|
32
|
+
end
|
33
|
+
|
34
|
+
def route_for(request)
|
35
|
+
simple_route(request) || constraint_route(request) || not_found_route
|
36
|
+
end
|
37
|
+
|
38
|
+
def simple_route(request)
|
39
|
+
@routes["#{request.verb} #{request.path}"]
|
40
|
+
end
|
41
|
+
|
42
|
+
def constraint_route(request)
|
43
|
+
constraint_checker = RouteConstraintChecker.new(request)
|
44
|
+
|
45
|
+
route = @routes.values.find(&constraint_checker.method(:match_route?))
|
46
|
+
return unless route
|
47
|
+
|
48
|
+
route.tap do
|
49
|
+
constraint_checker
|
50
|
+
.extract_params(route)
|
51
|
+
.each { |(name, value)| request.add_param!(name, value) }
|
52
|
+
end
|
53
|
+
end
|
54
|
+
|
55
|
+
def not_found_route = @routes['404'] || @routes[:not_found]
|
56
|
+
|
57
|
+
def not_found_response
|
58
|
+
::Chespirito::Response.new.tap do |response|
|
59
|
+
response.status = 404
|
60
|
+
response.headers = {}
|
61
|
+
response.body = ''
|
62
|
+
end
|
63
|
+
end
|
64
|
+
end
|
65
|
+
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: chespirito
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0.
|
4
|
+
version: 0.0.4
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Leandro Proença
|
8
|
-
autorequire:
|
8
|
+
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2023-10-05 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: rack
|
@@ -53,12 +53,15 @@ files:
|
|
53
53
|
- lib/chespirito/controller.rb
|
54
54
|
- lib/chespirito/request.rb
|
55
55
|
- lib/chespirito/response.rb
|
56
|
-
- lib/chespirito/
|
56
|
+
- lib/chespirito/routes/route.rb
|
57
|
+
- lib/chespirito/routes/route_constraint_checker.rb
|
58
|
+
- lib/chespirito/routes/route_utils.rb
|
59
|
+
- lib/chespirito/routes/router.rb
|
57
60
|
homepage: https://github.com/leandronsp/chespirito
|
58
61
|
licenses:
|
59
62
|
- MIT
|
60
63
|
metadata: {}
|
61
|
-
post_install_message:
|
64
|
+
post_install_message:
|
62
65
|
rdoc_options: []
|
63
66
|
require_paths:
|
64
67
|
- lib
|
@@ -73,8 +76,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
73
76
|
- !ruby/object:Gem::Version
|
74
77
|
version: '0'
|
75
78
|
requirements: []
|
76
|
-
rubygems_version: 3.
|
77
|
-
signing_key:
|
79
|
+
rubygems_version: 3.4.10
|
80
|
+
signing_key:
|
78
81
|
specification_version: 4
|
79
82
|
summary: Chespirito Ruby web framework
|
80
83
|
test_files: []
|
data/lib/chespirito/router.rb
DELETED
@@ -1,34 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
require_relative './request'
|
4
|
-
require_relative './response'
|
5
|
-
|
6
|
-
module Chespirito
|
7
|
-
class Router
|
8
|
-
def initialize
|
9
|
-
@routes = {}
|
10
|
-
end
|
11
|
-
|
12
|
-
def register_route(verb, path, trait)
|
13
|
-
@routes[route_key(verb, path)] = trait
|
14
|
-
end
|
15
|
-
|
16
|
-
def lookup(request)
|
17
|
-
controller_klass, action = @routes[route_key(request.verb, request.path)]
|
18
|
-
|
19
|
-
return not_found_response unless controller_klass
|
20
|
-
|
21
|
-
controller_klass.dispatch(action, request)
|
22
|
-
end
|
23
|
-
|
24
|
-
def route_key(verb, path) = "#{verb} #{path}"
|
25
|
-
|
26
|
-
def not_found_response
|
27
|
-
::Chespirito::Response.new.tap do |response|
|
28
|
-
response.status = 404
|
29
|
-
response.headers = {}
|
30
|
-
response.body = ''
|
31
|
-
end
|
32
|
-
end
|
33
|
-
end
|
34
|
-
end
|