nyara 0.0.1.pre.5 → 0.0.1.pre.6

Sign up to get free protection for your applications and to get access to all the features.
Files changed (59) hide show
  1. checksums.yaml +4 -4
  2. data/example/factorial.rb +19 -0
  3. data/ext/accept.c +2 -2
  4. data/ext/event.c +48 -23
  5. data/ext/extconf.rb +2 -0
  6. data/ext/hashes.c +28 -3
  7. data/ext/http-parser/http_parser.h +1 -0
  8. data/ext/nyara.c +20 -3
  9. data/ext/nyara.h +13 -2
  10. data/ext/request.c +90 -13
  11. data/ext/request.h +8 -2
  12. data/ext/request_parse.c +135 -6
  13. data/ext/route.cc +7 -10
  14. data/ext/test_response.c +155 -0
  15. data/ext/url_encoded.c +0 -5
  16. data/lib/nyara/config.rb +5 -0
  17. data/lib/nyara/controller.rb +91 -28
  18. data/lib/nyara/cookie.rb +7 -0
  19. data/lib/nyara/flash.rb +23 -0
  20. data/lib/nyara/hashes/header_hash.rb +2 -0
  21. data/lib/nyara/nyara.rb +14 -2
  22. data/lib/nyara/part.rb +156 -0
  23. data/lib/nyara/patches/array.rb +5 -0
  24. data/lib/nyara/patches/blank.rb +128 -0
  25. data/lib/nyara/patches/json.rb +15 -0
  26. data/lib/nyara/patches/mini_support.rb +6 -0
  27. data/lib/nyara/patches/string.rb +21 -0
  28. data/lib/nyara/patches/to_query.rb +113 -0
  29. data/lib/nyara/request.rb +13 -15
  30. data/lib/nyara/route.rb +15 -80
  31. data/lib/nyara/route_entry.rb +69 -2
  32. data/lib/nyara/session.rb +66 -21
  33. data/lib/nyara/test.rb +170 -0
  34. data/lib/nyara/view.rb +5 -6
  35. data/lib/nyara.rb +7 -6
  36. data/nyara.gemspec +2 -2
  37. data/rakefile +34 -4
  38. data/readme.md +8 -1
  39. data/spec/config_spec.rb +28 -0
  40. data/spec/cpu_counter_spec.rb +9 -0
  41. data/spec/evented_io_spec.rb +1 -0
  42. data/spec/flash_spec.rb +29 -0
  43. data/spec/hashes_spec.rb +8 -0
  44. data/spec/mini_support_spec.rb +54 -0
  45. data/spec/part_spec.rb +52 -0
  46. data/spec/path_helper_spec.rb +22 -14
  47. data/spec/request_delegate_spec.rb +19 -11
  48. data/spec/route_entry_spec.rb +55 -0
  49. data/spec/session_spec.rb +69 -7
  50. data/spec/spec_helper.rb +3 -0
  51. data/spec/test_spec.rb +58 -0
  52. data/tools/hello.rb +11 -3
  53. data/tools/memcheck.rb +33 -0
  54. data/tools/s.rb +11 -0
  55. metadata +23 -7
  56. data/example/design.rb +0 -62
  57. data/example/fib.rb +0 -15
  58. data/spec/route_spec.rb +0 -84
  59. /data/ext/inc/{status_codes.inc → status_codes.h} +0 -0
data/lib/nyara/route.rb CHANGED
@@ -12,52 +12,46 @@ module Nyara
12
12
  end
13
13
 
14
14
  def compile
15
- global_path_templates = {} # "name#id" => path
16
- @path_templates = {} # klass => {any_id => path}
15
+ @global_path_templates = {} # "name#id" => path
16
+ mapped_controllers = {}
17
17
 
18
- a = @controllers.map do |scope, c|
18
+ route_entries = @controllers.flat_map do |scope, c|
19
19
  if c.is_a?(String)
20
20
  c = name2const c
21
21
  end
22
22
  name = c.controller_name || const2name(c)
23
23
  raise "#{c.inspect} is not a Nyara::Controller" unless Controller > c
24
24
 
25
- if @path_templates[c]
25
+ if mapped_controllers[c]
26
26
  raise "controller #{c.inspect} was already mapped"
27
27
  end
28
+ mapped_controllers[c] = true
28
29
 
29
- route_entries = c.preprocess_actions
30
- @path_templates[c] = {}
31
- route_entries.each do |e|
32
- id = e.id.to_s
33
- path = File.join scope, e.path
34
- global_path_templates[name + id] = path
35
- @path_templates[c][id] = path
30
+ c.compile_route_entries(scope).each do |e|
31
+ @global_path_templates[name + e.id] = e.path_template
36
32
  end
37
-
38
- [scope, c, route_entries]
39
33
  end
34
+ route_entries.sort_by! &:prefix
35
+ route_entries.reverse!
40
36
 
41
- @path_templates.keys.each do |c|
42
- @path_templates[c] = global_path_templates.merge @path_templates[c]
37
+ mapped_controllers.each do |c, _|
38
+ c.path_templates = @global_path_templates.merge c.path_templates
43
39
  end
44
40
 
45
41
  Ext.clear_route
46
- process(a).each do |entry|
47
- entry.validate
48
- Ext.register_route entry
42
+ route_entries.each do |e|
43
+ Ext.register_route e
49
44
  end
50
45
  end
51
46
 
52
- def path_template klass, id
53
- @path_templates[klass][id]
47
+ def global_path_template id
48
+ @global_path_templates[id]
54
49
  end
55
50
 
56
51
  def clear
57
52
  # gc mark fail if wrong order?
58
53
  Ext.clear_route
59
54
  @controllers = {}
60
- @path_templates = {}
61
55
  end
62
56
 
63
57
  # private
@@ -75,64 +69,5 @@ module Nyara
75
69
  name << 'Controller'
76
70
  Module.const_get name
77
71
  end
78
-
79
- def process preprocessed
80
- entries = []
81
- preprocessed.each do |(scope, controller, route_entries)|
82
- route_entries.each do |e|
83
- e = e.dup # in case there is controller used in more than 1 maps
84
- path = scope.sub /\/?$/, e.path
85
- if path.empty?
86
- path = '/'
87
- end
88
- e.prefix, suffix = analyse_path path
89
- e.suffix, e.conv = compile_re suffix
90
- e.scope = scope
91
- e.controller = controller
92
- entries << e
93
- end
94
- end
95
- entries.sort_by! &:prefix
96
- entries.reverse!
97
- entries
98
- end
99
-
100
- # returns [str_re, conv]
101
- def compile_re suffix
102
- return ['', []] unless suffix
103
- conv = []
104
- re_segs = suffix.split(/(?<=%[dfsux])|(?=%[dfsux])/).map do |s|
105
- case s
106
- when '%d'
107
- conv << :to_i
108
- '(-?[0-9]+)'
109
- when '%f'
110
- conv << :to_f
111
- # just copied from scanf
112
- '([-+]?(?:0[xX](?:\.\h+|\h+(?:\.\h*)?)[pP][-+]\d+|\d+(?![\d.])|\d*\.\d*(?:[eE][-+]?\d+)?))'
113
- when '%u'
114
- conv << :to_i
115
- '([0-9]+)'
116
- when '%x'
117
- conv << :hex
118
- '(\h+)'
119
- when '%s'
120
- conv << :to_s
121
- '([^/]+)'
122
- else
123
- Regexp.quote s
124
- end
125
- end
126
- ["^#{re_segs.join}$", conv]
127
- end
128
-
129
- # split the path into parts
130
- def analyse_path path
131
- raise 'path must contain no new line' if path.index "\n"
132
- raise 'path must start with /' unless path.start_with? '/'
133
- path = path.sub(/\/$/, '') if path != '/'
134
-
135
- path.split(/(?=%[dfsux])/, 2)
136
- end
137
72
  end
138
73
  end
@@ -1,7 +1,12 @@
1
1
  module Nyara
2
2
  class RouteEntry
3
3
  REQUIRED_ATTRS = [:http_method, :scope, :prefix, :suffix, :controller, :id, :conv]
4
- attr_accessor *REQUIRED_ATTRS
4
+ attr_reader *REQUIRED_ATTRS
5
+ attr_writer :http_method, :id
6
+ # stores symbol for C conenience, and returns string for Ruby side goodness
7
+ def id
8
+ @id.to_s
9
+ end
5
10
 
6
11
  # optional
7
12
  attr_accessor :accept_exts, :accept_mimes
@@ -13,6 +18,25 @@ module Nyara
13
18
  instance_eval &p if p
14
19
  end
15
20
 
21
+ def path_template
22
+ File.join @scope, (@path.gsub '%z', '%s')
23
+ end
24
+
25
+ # compute prefix, suffix, conv
26
+ # NOTE route_entries may be inherited, so late-setting controller is necessary
27
+ def compile controller, scope
28
+ @controller = controller
29
+ @scope = scope
30
+
31
+ path = scope.sub /\/?$/, @path
32
+ if path.empty?
33
+ path = '/'
34
+ end
35
+ @prefix, suffix = analyse_path path
36
+ @suffix, @conv = compile_re suffix
37
+ end
38
+
39
+ # compute accept_exts, accept_mimes
16
40
  def set_accept_exts a
17
41
  @accept_exts = {}
18
42
  @accept_mimes = []
@@ -37,7 +61,50 @@ module Nyara
37
61
  raise ArgumentError, "missing #{attr}"
38
62
  end
39
63
  end
40
- raise ArgumentError, "id must be symbol" unless id.is_a?(Symbol)
64
+ raise ArgumentError, "id must be symbol" unless @id.is_a?(Symbol)
65
+ end
66
+
67
+ # private
68
+
69
+ # returns [str_re, conv]
70
+ def compile_re suffix
71
+ return ['', []] unless suffix
72
+ conv = []
73
+ re_segs = suffix.split(/(?<=%[dfsux])|(?=%[dfsux])/).map do |s|
74
+ case s
75
+ when '%d'
76
+ conv << :to_i
77
+ '(-?[0-9]+)'
78
+ when '%f'
79
+ conv << :to_f
80
+ # just copied from scanf
81
+ '([-+]?(?:0[xX](?:\.\h+|\h+(?:\.\h*)?)[pP][-+]\d+|\d+(?![\d.])|\d*\.\d*(?:[eE][-+]?\d+)?))'
82
+ when '%u'
83
+ conv << :to_i
84
+ '([0-9]+)'
85
+ when '%x'
86
+ conv << :hex
87
+ '(\h+)'
88
+ when '%s'
89
+ conv << :to_s
90
+ '([^/]+)'
91
+ when '%z'
92
+ conv << :to_s
93
+ '(.+)'
94
+ else
95
+ Regexp.quote s
96
+ end
97
+ end
98
+ ["^#{re_segs.join}$", conv]
99
+ end
100
+
101
+ # split the path into parts
102
+ def analyse_path path
103
+ raise 'path must contain no new line' if path.index "\n"
104
+ raise 'path must start with /' unless path.start_with? '/'
105
+ path = path.sub(/\/$/, '') if path != '/'
106
+
107
+ path.split(/(?=%[dfsux])/, 2)
41
108
  end
42
109
  end
43
110
  end
data/lib/nyara/session.rb CHANGED
@@ -1,42 +1,74 @@
1
1
  module Nyara
2
- # cookie based
3
- # usually it's no need to call cache or database data a "session"
2
+ # helper module for session management, cookie based<br>
3
+ # (usually it's no need to call cache or database data a "session")<br><br>
4
+ # session is by default DSA + SHA2/SHA1 signed, sub config options are:
5
+ #
6
+ # [name] session entry name in cookie, default is +'spare_me_plz'+
7
+ # [expire] expire session after seconds. default is +nil+, which means session expires when browser is closed<br>
8
+ # [expires] same as +expire+
9
+ # [secure] - +nil+(default): if request is https, add +Secure+ option to it
10
+ # - +true+: always add +Secure+
11
+ # - +false+: always no +Secure+
12
+ # [key] DSA private key string, in der or pem format, use random if not given
13
+ # [cipher_key] if exist, use aes-256-cbc to cipher the "sig/json"<br>
14
+ # NOTE: it's no need to set +cipher_key+ if using https
15
+ #
16
+ # = example
17
+ #
18
+ # configure do
19
+ # set 'session', 'key', File.read(project_path 'config/session.key')
20
+ # set 'session', 'expire', 30 * 60
21
+ # end
22
+ #
4
23
  module Session
5
24
  extend self
6
25
 
7
26
  CIPHER_BLOCK_SIZE = 256/8
8
27
 
9
- # session is by default DSA + SHA2/SHA1 signed, sub config options are:
10
- #
11
- # - name (session entry name in cookie, default is 'spare_me_plz')
12
- # - key (DSA private key string, in der or pem format, use random if not given)
13
- # - cipher_key (if exist, use aes-256-cbc to cipher the "sig&json", the first 256bit is sliced for iv)
14
- # (it's no need to set cipher_key if using https)
15
-
16
28
  # init from config
17
29
  def init
18
- c = Config['session'] || {}
19
- @name = (c['name'] || 'spare_me_plz').to_s
30
+ c = Config['session'] ? Config['session'].dup : {}
31
+ @name = (c.delete('name') || 'spare_me_plz').to_s
20
32
 
21
33
  if c['key']
22
- @dsa = OpenSSL::PKey::DSA.new c['key']
34
+ @dsa = OpenSSL::PKey::DSA.new c.delete 'key'
23
35
  else
24
- @dsa = OpenSSL::PKey::DSA.generate 256
36
+ @dsa = generate_key
25
37
  end
26
38
 
27
39
  # DSA can sign on any digest since 1.0.0
28
40
  @dss = OpenSSL::VERSION >= '1.0.0' ? OpenSSL::Digest::SHA256 : OpenSSL::Digest::DSS1
29
41
 
30
- @cipher_key = pad_256_bit c['cipher_key']
42
+ @cipher_key = pad_256_bit c.delete 'cipher_key'
43
+
44
+ @expire = c.delete('expire') || c.delete('expires')
45
+ @secure = c.delete('secure')
46
+
47
+ unless c.empty?
48
+ raise "unknown options in Nyara::Config[:session]: #{c.inspect}"
49
+ end
31
50
  end
32
51
 
33
52
  attr_reader :name
34
53
 
35
- def encode h, cookie
54
+ # encode into a cookie hash, for test environment
55
+ def encode_to_cookie h, cookie
56
+ cookie[@name] = encode h
57
+ end
58
+
59
+ # encode to value
60
+ def encode h
36
61
  str = h.to_json
37
62
  sig = @dsa.syssign @dss.digest str
38
- str = "#{Base64.urlsafe_encode64 sig}&#{str}"
39
- cookie[@name] = @cipher_key ? cipher(str) : str
63
+ str = "#{encode64 sig}/#{encode64 str}"
64
+ @cipher_key ? cipher(str) : str
65
+ end
66
+
67
+ # encode as header line
68
+ def encode_set_cookie h, secure
69
+ secure = @secure unless @secure.nil?
70
+ expire = (Time.now + @expire).gmtime.rfc2822 if @expire
71
+ "Set-Cookie: #{@name}=#{encode h}; HttpOnly#{'; Secure' if secure}#{"; Expires=#{expire}" if expire}\r\n"
40
72
  end
41
73
 
42
74
  def decode cookie
@@ -44,11 +76,12 @@ module Nyara
44
76
  return empty_hash if str.empty?
45
77
 
46
78
  str = decipher(str) if @cipher_key
47
- sig, str = str.split '&', 2
79
+ sig, str = str.split '/', 2
48
80
  return empty_hash unless str
49
81
 
50
82
  begin
51
- sig = Base64.urlsafe_decode64 sig
83
+ sig = decode64 sig
84
+ str = decode64 str
52
85
  verified = @dsa.sysverify @dss.digest(str), sig
53
86
  if verified
54
87
  h = JSON.parse str, create_additions: false, object_class: ParamHash
@@ -64,16 +97,28 @@ module Nyara
64
97
  end
65
98
  end
66
99
 
100
+ def generate_key
101
+ OpenSSL::PKey::DSA.generate 256
102
+ end
103
+
67
104
  # private
68
105
 
106
+ def encode64 s
107
+ [s].pack('m0').tr("+/", "-_")
108
+ end
109
+
110
+ def decode64 s
111
+ s.tr("-_", "+/").unpack('m0').first
112
+ end
113
+
69
114
  def cipher str
70
115
  iv = rand(36**CIPHER_BLOCK_SIZE).to_s(36).ljust CIPHER_BLOCK_SIZE
71
116
  c = new_cipher true, iv
72
- Base64.urlsafe_encode64(iv.dup << c.update(str) << c.final)
117
+ encode64(iv.dup << c.update(str) << c.final)
73
118
  end
74
119
 
75
120
  def decipher str
76
- str = Base64.urlsafe_decode64 str
121
+ str = decode64 str
77
122
  iv = str.byteslice 0...CIPHER_BLOCK_SIZE
78
123
  str = str.byteslice CIPHER_BLOCK_SIZE..-1
79
124
  return '' if !str or str.empty?
data/lib/nyara/test.rb ADDED
@@ -0,0 +1,170 @@
1
+ module Nyara
2
+ # test helper
3
+ module Test
4
+ class Response
5
+ # whether request is success
6
+ def success?
7
+ status < 400
8
+ end
9
+
10
+ def redirect_location
11
+ if HTTP_REDIRECT_STATUS.include?(status)
12
+ header['Location']
13
+ end
14
+ end
15
+
16
+ # C-ext methods: header, body, status, initialize(data), set_cookies
17
+ end
18
+
19
+ Env = Struct.new :cookie, :session, :request, :controller, :response, :response_size_limit
20
+ class Env
21
+ # :call-seq:
22
+ #
23
+ # # change size limit of response data to 100M:
24
+ # @_env = Env.new 10**8
25
+ #
26
+ def initialize response_size_limit=5_000_000
27
+ self.response_size_limit = response_size_limit
28
+ self.cookie = ParamHash.new
29
+ self.session = ParamHash.new
30
+ end
31
+
32
+ def process_request_data data
33
+ client, server = Socket.pair :UNIX, :STREAM
34
+ self.request = Ext.request_new
35
+ Ext.request_set_fd request, server.fileno
36
+
37
+ client << data
38
+ self.controller = Ext.handle_request request
39
+ response_data = client.read_nonblock response_size_limit
40
+ self.response = Response.new response_data
41
+
42
+ # merge session
43
+ session.clear
44
+ session.merge! request.session
45
+
46
+ # merge Set-Cookie
47
+ response.set_cookies.each do |cookie_seg|
48
+ # todo distinguish delete, value and set
49
+ Ext.parse_url_encoded_seg cookie, cookie_seg, false
50
+ end
51
+
52
+ server.close
53
+ client.close
54
+ end
55
+
56
+ def http meth, path, headers={}, body_string_or_hash=''
57
+ headers = (headers || {}).dup
58
+
59
+ # serialize body
60
+ # todo build multipart for file
61
+ if body_string_or_hash.is_a?(Hash)
62
+ body = body_string_or_hash.to_param
63
+ headers['Content-Type'] = 'application/x-www-form-urlencoded'
64
+ else
65
+ body = body_string_or_hash.to_s
66
+ headers['Content-Type'] ||= 'text/plain'
67
+ end
68
+ if body.bytesize > 0
69
+ headers['Content-Length'] = body.bytesize
70
+ end
71
+
72
+ # serialize cookie / session
73
+ if headers['Cookie']
74
+ cookie.clear
75
+ cookie.merge! Cookie.decode headers
76
+ end
77
+ Session.encode_to_cookie session, cookie
78
+ headers['Cookie'] = Cookie.encode cookie
79
+
80
+ request_data = ["#{meth.upcase} #{path} HTTP/1.1\r\n"]
81
+ headers.each do |k, v|
82
+ request_data << "#{k}: #{v}\r\n"
83
+ end
84
+ request_data << "\r\n"
85
+ request_data << body
86
+ process_request_data request_data.join
87
+ end
88
+ end
89
+
90
+ def env
91
+ @_env ||= Env.new
92
+ end
93
+
94
+ # :call-seq:
95
+ #
96
+ # get '/', headers
97
+ #
98
+ def get path, header={}, body_string_or_hash=""
99
+ env.http 'GET', path, header, body_string_or_hash
100
+ end
101
+
102
+ # :call-seq:
103
+ #
104
+ # post '/', {}, page: 3
105
+ # post '/', { 'content-type' => 'application/json' }, '{"page":3}'
106
+ #
107
+ def post path, header={}, body_string_or_hash=""
108
+ env.http 'POST', path, header, body_string_or_hash
109
+ end
110
+
111
+ def put path, header={}, body_string_or_hash=""
112
+ env.http 'PUT', path, header, body_string_or_hash
113
+ end
114
+
115
+ def delete path, header={}, body_string_or_hash=""
116
+ env.http 'DELETE', path, header, body_string_or_hash
117
+ end
118
+
119
+ def patch path, header={}, body_string_or_hash=""
120
+ env.http 'PATCH', path, header, body_string_or_hash
121
+ end
122
+
123
+ def options path, header={}, body_string_or_hash=""
124
+ env.http 'OPTIONS', path, header, body_string_or_hash
125
+ end
126
+
127
+ def path_to id, *args
128
+ # similar to Controller#path_to, but without local query
129
+ if args.last.is_a?(Hash)
130
+ opts = args.pop
131
+ end
132
+
133
+ r = Route.global_path_template(id) % args
134
+
135
+ if opts
136
+ format = opts.delete :format
137
+ r << ".#{format}" if format
138
+ r << '?' << opts.to_param unless query.empty?
139
+ end
140
+ r
141
+ end
142
+
143
+ def cookie
144
+ env.cookie
145
+ end
146
+
147
+ def session
148
+ env.session
149
+ end
150
+
151
+ def request
152
+ env.request
153
+ end
154
+
155
+ def response
156
+ env.response
157
+ end
158
+
159
+ def redirect_location
160
+ env.response.redirect_location
161
+ end
162
+
163
+ def follow_redirect
164
+ # todo validate scheme and host
165
+ u = URI.parse(redirect_location)
166
+ path = [u.path, u.query].compact.join '?'
167
+ get path
168
+ end
169
+ end
170
+ end
data/lib/nyara/view.rb CHANGED
@@ -42,7 +42,7 @@ module Nyara
42
42
  end
43
43
  attr_reader :root
44
44
 
45
- # +path+ needs extension
45
+ # NOTE: +path+ needs extension
46
46
  def on_delete path
47
47
  meth = path2meth path
48
48
  Renderable.class_eval do
@@ -64,7 +64,7 @@ module Nyara
64
64
  @meth2ext.clear
65
65
  end
66
66
 
67
- # +path+ needs extension
67
+ # NOTE: +path+ needs extension<br>
68
68
  # returns dot_ext for further use
69
69
  def on_update path
70
70
  meth = path2meth path
@@ -108,7 +108,7 @@ module Nyara
108
108
  line = 1
109
109
 
110
110
  if stream_friendly
111
- Renderable.class_eval <<-RUBY, __FILE__, __LINE__ + 1
111
+ Renderable.class_eval <<-RUBY, __FILE__, __LINE__
112
112
  def render locals={}
113
113
  @_nyara_locals = locals
114
114
  src = locals.map{|k, _| "\#{k} = @_nyara_locals[:\#{k}];" }.join
@@ -119,7 +119,7 @@ module Nyara
119
119
  RUBY
120
120
  ENGINE_STREAM_FRIENDLY[ext] = true
121
121
  else
122
- Renderable.class_eval <<-RUBY, __FILE__, __LINE__ + 1
122
+ Renderable.class_eval <<-RUBY, __FILE__, __LINE__
123
123
  def render locals=nil
124
124
  Tilt[#{ext.inspect}].new(#{file}, #{line}){ @_nyara_view.in }.render self, locals
125
125
  end
@@ -278,8 +278,7 @@ RUBY
278
278
  Fiber.yield :term_close
279
279
  end
280
280
 
281
- # :nodoc:
282
- def _render
281
+ def _render # :nodoc:
283
282
  t, _ = @rest_layouts.pop
284
283
  if @rest_layouts.empty?
285
284
  @instance.send t, @locals
data/lib/nyara.rb CHANGED
@@ -1,18 +1,19 @@
1
1
  # auto run
2
2
  require_relative "nyara/nyara"
3
3
 
4
- at_exit do
5
- Nyara::Route.compile
6
- Nyara::View.init
7
- Nyara.start_server
8
- end
4
+ END {
5
+ if $!.nil? and !Nyara.config.test?
6
+ Nyara.setup
7
+ Nyara.start_server
8
+ end
9
+ }
9
10
 
10
11
  module Nyara
11
12
  class SimpleController < Controller
12
13
  end
13
14
  end
14
15
 
15
- %w[on tag get post put delete patch options].each do |m|
16
+ %w[on tag get post put delete patch options meta].each do |m|
16
17
  eval <<-RUBY
17
18
  def #{m} *xs, &blk
18
19
  Nyara::SimpleController.#{m} *xs, &blk
data/nyara.gemspec CHANGED
@@ -1,6 +1,6 @@
1
1
  Gem::Specification.new do |s|
2
2
  s.name = "nyara"
3
- s.version = "0.0.1.pre.5"
3
+ s.version = "0.0.1.pre.6"
4
4
  s.author = "Zete Lui"
5
5
  s.email = "nobody@example.com"
6
6
  s.homepage = "https://github.com/luikore/nyara"
@@ -8,7 +8,7 @@ Gem::Specification.new do |s|
8
8
  s.summary = "Fast, slim and fuzzy ruby web framework + server"
9
9
  s.description = "Fast, slim and fuzzy ruby web framework + server, based on preforked event queue and Fiber. NO rack NOR eventmachine are used."
10
10
  s.required_ruby_version = ">=2.0.0"
11
- s.licenses = ['BSD']
11
+ s.licenses = ['BSD 3-Clause']
12
12
 
13
13
  s.files = Dir.glob('{rakefile,nyara.gemspec,readme.md,**/*.{rb,h,c,cc,inc}}')
14
14
  s.files += Dir.glob('ext/http-parser/{AUTHORS,CONTRIBUTIONS,LICENSE-MIT}')
data/rakefile CHANGED
@@ -2,13 +2,13 @@ require "rake"
2
2
 
3
3
  Dir.chdir __dir__
4
4
 
5
- status_file = "ext/inc/status_codes.inc"
5
+ status_file = "ext/inc/status_codes.h"
6
6
  version_file = "ext/inc/version.inc"
7
7
  makefile = "ext/Makefile"
8
8
  extconf = "ext/extconf.rb"
9
9
 
10
10
  desc "code generate"
11
- task :gen => [status_file, version_file]
11
+ task :gen => [version_file]
12
12
 
13
13
  desc "generate #{status_file}"
14
14
  file status_file => __FILE__ do
@@ -47,6 +47,7 @@ end
47
47
  desc "generate makefile"
48
48
  file makefile => extconf do
49
49
  Dir.chdir 'ext' do
50
+ sh 'make clean' if File.exist?('Makefile')
50
51
  sh 'ruby extconf.rb'
51
52
  end
52
53
  end
@@ -112,14 +113,20 @@ end
112
113
  desc "list Nyara::Ext methods"
113
114
  task :list_ext do
114
115
  require_relative "lib/nyara/nyara"
116
+ puts_methods = lambda{|methods|
117
+ methods.each do |m|
118
+ puts "#{m} /#{Nyara::Ext.method(m).arity}"
119
+ end
120
+ }
121
+
115
122
  methods = (Nyara::Ext.methods - Module.methods).sort
116
123
  [/queue/, /route/, /parse/, /request/].each do |r|
117
124
  group = methods.grep r
118
- puts group
125
+ puts_methods[group]
119
126
  puts
120
127
  methods -= group
121
128
  end
122
- puts methods
129
+ puts_methods[methods]
123
130
  end
124
131
 
125
132
  def term_color n
@@ -158,3 +165,26 @@ task :audit_arity do
158
165
  end
159
166
  end
160
167
  end
168
+
169
+ desc "audit http_parser / multipart_parser struct size, they should be dividable by 8 so that Request fields are aligned"
170
+ task :audit_sizeof_parsers do
171
+ require "mkmf"
172
+ $CFLAGS << " -Iext/http-parser -Iext/multipart-parser-c"
173
+ {
174
+ 'http_parser' => 'http_parser.h',
175
+ 'multipart_parser*' => 'multipart_parser.h' # multipart_parser is opaque -_-
176
+ }.each do |struct, header|
177
+ have_header header
178
+ res = check_sizeof(struct, header)
179
+ if res and res % 8 == 0
180
+ puts "OK"
181
+ else
182
+ term_color 9
183
+ print "Need padding"
184
+ reset_color
185
+ puts
186
+ end
187
+ puts
188
+ end
189
+ sh 'rm', 'mkmf.log'
190
+ end