Skip to content

Commit 4330ba8

Browse files
committed
Move context inside Request object
1 parent fb0b2ad commit 4330ba8

13 files changed

Lines changed: 175 additions & 136 deletions

File tree

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
## 0.1 2025-06-17
22

3+
- Implement routing
34
- Implement RPC API controller
45
- Implement Context with parameter validation
56
- Preliminary version

README.md

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -88,12 +88,12 @@ class APIV1 < Syntropy::RPCAPI
8888
end
8989

9090
# /posts
91-
def all(ctx)
91+
def all(req)
9292
@db[:posts].order_by(:stamp.desc).to_a
9393
end
9494

95-
def by_id(ctx)
96-
id = ctx.validate_param(:id, /^{4,32}$/)
95+
def by_id(req)
96+
id = req.validate_param(:id, /^{4,32}$/)
9797
@db[:posts].where(id: id).first
9898
end
9999
end

lib/syntropy.rb

Lines changed: 52 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,60 @@
11
# frozen_string_literal: true
22

3+
require 'qeweney'
4+
35
require 'syntropy/errors'
4-
require 'syntropy/context'
6+
# require 'syntropy/context'
57
require 'syntropy/rpc_api'
68
require 'syntropy/app'
79

10+
class Qeweney::Request
11+
def ctx
12+
@ctx ||= {}
13+
end
14+
15+
def validate_param(name, *clauses)
16+
value = query[name]
17+
clauses.each do |c|
18+
valid = param_is_valid?(value, c)
19+
raise(Syntropy::ValidationError, 'Validation error') if !valid
20+
value = param_convert(value, c)
21+
end
22+
value
23+
end
24+
25+
private
26+
27+
BOOL_REGEXP = /^(t|f|true|false|on|off|1|0|yes|no)$/
28+
BOOL_TRUE_REGEXP = /^(t|true|on|1|yes)$/
29+
INTEGER_REGEXP = /^[\+\-]?[0-9]+$/
30+
FLOAT_REGEXP = /^[\+\-]?[0-9]+(\.[0-9]+)?$/
31+
32+
def param_is_valid?(value, cond)
33+
if cond == :bool
34+
return (value && value =~ BOOL_REGEXP)
35+
elsif cond == Integer
36+
return (value && value =~ INTEGER_REGEXP)
37+
elsif cond == Float
38+
return (value && value =~ FLOAT_REGEXP)
39+
elsif cond.is_a?(Array)
40+
return cond.any? { |c| param_is_valid?(value, c) }
41+
end
42+
43+
cond === value
44+
end
45+
46+
def param_convert(value, klass)
47+
if klass == :bool
48+
value = value =~ BOOL_TRUE_REGEXP ? true : false
49+
elsif klass == Integer
50+
value = value.to_i
51+
elsif klass == Float
52+
value = value.to_f
53+
else
54+
value
55+
end
56+
end
57+
end
58+
859
module Syntropy
960
end

lib/syntropy/app.rb

Lines changed: 4 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -111,7 +111,6 @@ def parent_path(path)
111111
end
112112

113113
def render_entry(req, entry)
114-
p entry: entry
115114
case entry[:kind]
116115
when :not_found
117116
req.respond('Not found', ':status' => Qeweney::Status::NOT_FOUND)
@@ -122,21 +121,20 @@ def render_entry(req, entry)
122121
body = render_markdown(IO.read(entry[:fn]))
123122
req.respond(body, 'Content-Type' => 'text/html')
124123
when :module
125-
ctx = Syntropy::Context.new(req)
126-
call_module(entry, ctx)
124+
call_module(entry, req)
127125
else
128126
raise "Invalid entry kind"
129127
end
130128
end
131129

132-
def call_module(entry, ctx)
130+
def call_module(entry, req)
133131
entry[:code] ||= load_module(entry)
134132
if entry[:code] == :invalid
135133
req.respond(nil, ':status' => Qeweney::Status::INTERNAL_SERVER_ERROR)
136134
return
137135
end
138136

139-
entry[:code].call(ctx)
137+
entry[:code].call(req)
140138
rescue StandardError => e
141139
p e
142140
p e.backtrace
@@ -156,7 +154,7 @@ def load_module(entry)
156154
end
157155

158156
def wrap_template(templ)
159-
->(ctx) {
157+
->(req) {
160158
body = templ.render
161159
req.respond(body, 'Content-Type' => 'text/html')
162160
}

lib/syntropy/context.rb

Lines changed: 58 additions & 58 deletions
Original file line numberDiff line numberDiff line change
@@ -1,58 +1,58 @@
1-
# frozen_string_literal: true
2-
3-
require 'syntropy/errors'
4-
5-
module Syntropy
6-
class Context
7-
attr_reader :request
8-
9-
def initialize(request)
10-
@request = request
11-
end
12-
13-
def params
14-
@request.query
15-
end
16-
17-
def validate_param(name, *clauses)
18-
value = @request.query[name]
19-
clauses.each do |c|
20-
valid = param_is_valid?(value, c)
21-
raise(Syntropy::ValidationError, 'Validation error') if !valid
22-
value = param_convert(value, c)
23-
end
24-
value
25-
end
26-
27-
BOOL_REGEXP = /^(t|f|true|false|on|off|1|0|yes|no)$/
28-
BOOL_TRUE_REGEXP = /^(t|true|on|1|yes)$/
29-
INTEGER_REGEXP = /^[\+\-]?[0-9]+$/
30-
FLOAT_REGEXP = /^[\+\-]?[0-9]+(\.[0-9]+)?$/
31-
32-
def param_is_valid?(value, cond)
33-
if cond == :bool
34-
return (value && value =~ BOOL_REGEXP)
35-
elsif cond == Integer
36-
return (value && value =~ INTEGER_REGEXP)
37-
elsif cond == Float
38-
return (value && value =~ FLOAT_REGEXP)
39-
elsif cond.is_a?(Array)
40-
return cond.any? { |c| param_is_valid?(value, c) }
41-
end
42-
43-
cond === value
44-
end
45-
46-
def param_convert(value, klass)
47-
if klass == :bool
48-
value = value =~ BOOL_TRUE_REGEXP ? true : false
49-
elsif klass == Integer
50-
value = value.to_i
51-
elsif klass == Float
52-
value = value.to_f
53-
else
54-
value
55-
end
56-
end
57-
end
58-
end
1+
# # frozen_string_literal: true
2+
3+
# require 'syntropy/errors'
4+
5+
# module Syntropy
6+
# class Context
7+
# attr_reader :request
8+
9+
# def initialize(request)
10+
# @request = request
11+
# end
12+
13+
# def params
14+
# @request.query
15+
# end
16+
17+
# def validate_param(name, *clauses)
18+
# value = @request.query[name]
19+
# clauses.each do |c|
20+
# valid = param_is_valid?(value, c)
21+
# raise(Syntropy::ValidationError, 'Validation error') if !valid
22+
# value = param_convert(value, c)
23+
# end
24+
# value
25+
# end
26+
27+
# BOOL_REGEXP = /^(t|f|true|false|on|off|1|0|yes|no)$/
28+
# BOOL_TRUE_REGEXP = /^(t|true|on|1|yes)$/
29+
# INTEGER_REGEXP = /^[\+\-]?[0-9]+$/
30+
# FLOAT_REGEXP = /^[\+\-]?[0-9]+(\.[0-9]+)?$/
31+
32+
# def param_is_valid?(value, cond)
33+
# if cond == :bool
34+
# return (value && value =~ BOOL_REGEXP)
35+
# elsif cond == Integer
36+
# return (value && value =~ INTEGER_REGEXP)
37+
# elsif cond == Float
38+
# return (value && value =~ FLOAT_REGEXP)
39+
# elsif cond.is_a?(Array)
40+
# return cond.any? { |c| param_is_valid?(value, c) }
41+
# end
42+
43+
# cond === value
44+
# end
45+
46+
# def param_convert(value, klass)
47+
# if klass == :bool
48+
# value = value =~ BOOL_TRUE_REGEXP ? true : false
49+
# elsif klass == Integer
50+
# value = value.to_i
51+
# elsif klass == Float
52+
# value = value.to_f
53+
# else
54+
# value
55+
# end
56+
# end
57+
# end
58+
# end

lib/syntropy/rpc_api.rb

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -6,22 +6,22 @@
66

77
module Syntropy
88
class RPCAPI
9-
def call(ctx)
10-
response, status = invoke(ctx)
11-
ctx.request.respond(
9+
def call(req)
10+
response, status = invoke(req)
11+
req.respond(
1212
response.to_json,
1313
':status' => status,
1414
'Content-Type' => 'application/json'
1515
)
1616
end
1717

18-
def invoke(ctx)
19-
q = ctx.validate_param(:q, String)
20-
response = case ctx.request.method
18+
def invoke(req)
19+
q = req.validate_param(:q, String)
20+
response = case req.method
2121
when 'get'
22-
send(q.to_sym, ctx)
22+
send(q.to_sym, req)
2323
when 'post'
24-
send(:"#{q}!", ctx)
24+
send(:"#{q}!", req)
2525
else
2626
raise Syntropy::Error.new(Qeweney::Status::METHOD_NOT_ALLOWED)
2727
end

test/app/about/index.rb

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,3 @@
1-
->(ctx) {
2-
ctx.request.respond('About')
1+
->(req) {
2+
req.respond('About')
33
}

test/app/api+.rb

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,12 +3,12 @@ def initialize
33
@count = 0
44
end
55

6-
def get(ctx)
6+
def get(req)
77
@count
88
end
99

10-
def incr!(ctx)
11-
if ctx.request.path != '/test/api'
10+
def incr!(req)
11+
if req.path != '/test/api'
1212
raise Syntropy::Error.new(Qeweney::Status::TEAPOT, 'Teapot')
1313
end
1414

test/app/bar.rb

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,3 @@
1-
->(ctx) {
2-
ctx.request.respond('foobar')
1+
->(req) {
2+
req.respond('foobar')
33
}

test/test_app.rb

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -48,8 +48,6 @@ def test_find_route
4848
entry = @app.find_route('/test/about/foo')
4949
assert_equal :markdown, entry[:kind]
5050
assert_equal full_path('about/foo.md'), entry[:fn]
51-
52-
pp @app.route_cache
5351
end
5452

5553
def make_request(*, **)

0 commit comments

Comments
 (0)