nyara 0.0.1.pre.9 → 0.1.pre.0
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/bin/nyara +3 -3
- data/changes +1 -0
- data/ext/event.c +16 -22
- data/ext/hashes.c +222 -4
- data/ext/inc/rdtsc.h +56 -0
- data/ext/inc/status_codes.inc +64 -0
- data/ext/inc/version.inc +1 -1
- data/ext/nyara.c +12 -10
- data/ext/nyara.h +5 -5
- data/ext/request.c +18 -24
- data/ext/request_parse.c +1 -1
- data/ext/route.cc +2 -4
- data/ext/url_encoded.c +51 -193
- data/lib/nyara/command.rb +39 -12
- data/lib/nyara/config.rb +10 -10
- data/lib/nyara/controller.rb +60 -14
- data/lib/nyara/cookie.rb +1 -1
- data/lib/nyara/hashes/config_hash.rb +2 -24
- data/lib/nyara/nyara.rb +33 -19
- data/lib/nyara/part.rb +7 -3
- data/lib/nyara/reload.rb +85 -0
- data/lib/nyara/request.rb +1 -1
- data/lib/nyara/route.rb +55 -19
- data/lib/nyara/templates/Gemfile +10 -1
- data/lib/nyara/templates/Rakefile +6 -1
- data/lib/nyara/templates/app/controllers/application_controller.rb +3 -0
- data/lib/nyara/templates/app/controllers/welcome_controller.rb +5 -0
- data/lib/nyara/templates/app/views/layouts/application.erb +12 -0
- data/lib/nyara/templates/app/views/welcome/index.erb +1 -0
- data/lib/nyara/templates/config/application.rb +34 -0
- data/lib/nyara/templates/config/boot.rb +4 -0
- data/lib/nyara/templates/config/development.rb +5 -0
- data/lib/nyara/templates/config/production.rb +8 -0
- data/lib/nyara/templates/config/test.rb +2 -0
- data/lib/nyara/templates/public/css/app.css +1 -0
- data/lib/nyara/templates/public/js/app.js +1 -0
- data/lib/nyara/templates/spec/spec_helper.rb +9 -0
- data/lib/nyara/test.rb +10 -2
- data/lib/nyara/view.rb +116 -67
- data/nyara.gemspec +3 -1
- data/rakefile +1 -1
- data/readme.md +1 -1
- data/spec/command_spec.rb +28 -24
- data/spec/config_spec.rb +24 -1
- data/spec/dummy/app/controllers/dummy_controller.rb +2 -0
- data/spec/dummy/app/models/dmmy_model.rb +2 -0
- data/spec/evented_io_spec.rb +2 -1
- data/spec/ext_route_spec.rb +2 -2
- data/spec/flash_spec.rb +8 -0
- data/spec/hashes_spec.rb +127 -0
- data/spec/integration_spec.rb +15 -0
- data/spec/path_helper_spec.rb +17 -5
- data/spec/performance/escape.rb +15 -4
- data/spec/performance/layout_render.rb +15 -10
- data/spec/performance/parse_accept_value.rb +24 -8
- data/spec/performance/parse_param.rb +14 -8
- data/spec/performance/performance_helper.rb +8 -21
- data/spec/performance_spec.rb +5 -4
- data/spec/route_spec.rb +7 -2
- data/spec/url_encoded_spec.rb +18 -74
- data/spec/view_spec.rb +1 -3
- data/spec/views/_partial.slim +1 -0
- data/spec/views/_partial_with_yield.erb +1 -0
- metadata +73 -43
- data/example/factorial.rb +0 -19
- data/example/hello.rb +0 -5
- data/example/project.rb +0 -11
- data/example/stream.rb +0 -14
- data/lib/nyara/controllers/public_controller.rb +0 -14
- data/lib/nyara/templates/config/session.key +0 -1
- data/tools/bench-cookie.rb +0 -22
- data/tools/foo.rb +0 -9
- data/tools/hello.rb +0 -46
- data/tools/memcheck.rb +0 -33
- data/tools/s.rb +0 -11
data/lib/nyara/command.rb
CHANGED
@@ -1,3 +1,4 @@
|
|
1
|
+
require 'optparse'
|
1
2
|
module Nyara
|
2
3
|
module Command
|
3
4
|
extend self
|
@@ -9,9 +10,6 @@ module Nyara
|
|
9
10
|
commands:
|
10
11
|
nyara help\t\t\tShow this message
|
11
12
|
nyara new APP_NAME\t\tTo initialize a new project with default template in current directory.
|
12
|
-
options:
|
13
|
-
-f\t\t\tForce override if same name path existed
|
14
|
-
|
15
13
|
nyara version\t\t\tDisplay current version
|
16
14
|
)
|
17
15
|
end
|
@@ -20,23 +18,33 @@ commands:
|
|
20
18
|
puts "Nyara #{Nyara::VERSION}"
|
21
19
|
end
|
22
20
|
|
23
|
-
def new_project(
|
21
|
+
def new_project(*args)
|
24
22
|
args ||= []
|
25
|
-
|
23
|
+
opts = {
|
24
|
+
force: false
|
25
|
+
}
|
26
|
+
OptionParser.new do |opt|
|
27
|
+
opt.banner = 'Usage: nyara new APP_NAME [options]'
|
28
|
+
opt.on('-f', 'Force override old') do
|
29
|
+
opts[:force] = true
|
30
|
+
end
|
31
|
+
end.parse(args)
|
32
|
+
|
26
33
|
require 'fileutils'
|
27
34
|
require "erb"
|
28
35
|
require 'ostruct'
|
29
36
|
require_relative "view_handlers/erb"
|
30
37
|
|
38
|
+
name = args.shift
|
31
39
|
if name.blank?
|
32
40
|
puts "Need project name: \n\tnyara new xxx"
|
33
41
|
return
|
34
42
|
end
|
35
43
|
|
36
|
-
app_dir = File.join(Dir.pwd,name)
|
37
|
-
templte_dir = File.join(File.dirname(__FILE__),"templates")
|
44
|
+
app_dir = File.join(Dir.pwd, name)
|
45
|
+
templte_dir = File.join(File.dirname(__FILE__), "templates")
|
38
46
|
|
39
|
-
FileUtils.rm_rf(app_dir) if
|
47
|
+
FileUtils.rm_rf(app_dir) if opts[:force]
|
40
48
|
|
41
49
|
if Dir.exist?(app_dir)
|
42
50
|
puts "This has same dir name's '#{name}' existed, Nyara can not override it."
|
@@ -46,8 +54,9 @@ commands:
|
|
46
54
|
Dir.mkdir(app_dir)
|
47
55
|
|
48
56
|
puts "Generate Nyara project..."
|
49
|
-
|
50
|
-
|
57
|
+
source_templates = Dir.glob("#{templte_dir}/*")
|
58
|
+
puts source_templates.map{|f| File.basename f }
|
59
|
+
FileUtils.cp_r(source_templates, app_dir)
|
51
60
|
|
52
61
|
# render template
|
53
62
|
files = Dir.glob("#{app_dir}/**/*")
|
@@ -56,13 +65,31 @@ commands:
|
|
56
65
|
}
|
57
66
|
files.each do |fname|
|
58
67
|
if not File.directory?(fname)
|
59
|
-
render_template(fname,render_opts)
|
68
|
+
render_template(fname, render_opts)
|
69
|
+
end
|
70
|
+
end
|
71
|
+
|
72
|
+
Dir.chdir app_dir do
|
73
|
+
puts "config/session.key"
|
74
|
+
File.open 'config/session.key', 'wb' do |f|
|
75
|
+
f << Session.generate_key
|
76
|
+
end
|
77
|
+
|
78
|
+
puts ".gitignore"
|
79
|
+
File.open '.gitignore', 'w' do |f|
|
80
|
+
f.puts ".DS_Store"
|
81
|
+
f.puts "config/session.key"
|
60
82
|
end
|
61
83
|
end
|
62
84
|
|
63
85
|
puts "Enjoy!"
|
64
86
|
end
|
65
87
|
|
88
|
+
def run_server(*args)
|
89
|
+
args ||= []
|
90
|
+
system("bundle exec ruby config/boot.rb")
|
91
|
+
end
|
92
|
+
|
66
93
|
private
|
67
94
|
def render_template(fname, opts = {})
|
68
95
|
renderer = ERB.new(File.read(fname))
|
@@ -70,7 +97,7 @@ commands:
|
|
70
97
|
app_name: opts[:app_name],
|
71
98
|
nyara_version: Nyara::VERSION
|
72
99
|
}
|
73
|
-
File.open(fname,'w+') do |f|
|
100
|
+
File.open(fname, 'w+') do |f|
|
74
101
|
f.write renderer.result(OpenStruct.new(locals).instance_eval { binding })
|
75
102
|
end
|
76
103
|
end
|
data/lib/nyara/config.rb
CHANGED
@@ -54,16 +54,14 @@ module Nyara
|
|
54
54
|
self['root'] = File.expand_path self['root']
|
55
55
|
|
56
56
|
self['views'] = project_path(self['views'] || 'views')
|
57
|
-
|
57
|
+
if self['public']
|
58
|
+
self['public'] = project_path(self['public'])
|
59
|
+
end
|
58
60
|
|
59
61
|
self.logger = create_logger
|
60
62
|
|
61
|
-
assert !self['before_fork']
|
62
|
-
assert !self['after_fork']
|
63
|
-
|
64
|
-
if self['public']
|
65
|
-
map '/', PublicController
|
66
|
-
end
|
63
|
+
assert !self['before_fork'] || self['before_fork'].respond_to?('call')
|
64
|
+
assert !self['after_fork'] || self['after_fork'].respond_to?('call')
|
67
65
|
end
|
68
66
|
|
69
67
|
attr_accessor :logger
|
@@ -73,11 +71,8 @@ module Nyara
|
|
73
71
|
l = self['logger']
|
74
72
|
|
75
73
|
if l == true or l.nil?
|
76
|
-
# see Nyara.summary_request
|
77
|
-
Ext.summary_request true if development?
|
78
74
|
::Logger.new(production? ? project_path('production.log') : STDOUT)
|
79
75
|
elsif l.is_a?(Class)
|
80
|
-
Ext.summary_request true if development?
|
81
76
|
l.new(production? ? project_path('production.log') : STDOUT)
|
82
77
|
elsif l.is_a?(Proc)
|
83
78
|
l.call
|
@@ -140,6 +135,10 @@ module Nyara
|
|
140
135
|
self['env'].to_s
|
141
136
|
end
|
142
137
|
|
138
|
+
def root
|
139
|
+
self['root'].to_s
|
140
|
+
end
|
141
|
+
|
143
142
|
def development?
|
144
143
|
e = env
|
145
144
|
e.empty? or e == 'development'
|
@@ -179,4 +178,5 @@ configure do
|
|
179
178
|
set 'env', 'development'
|
180
179
|
set 'views', 'views'
|
181
180
|
set 'public', 'public'
|
181
|
+
set 'root', Dir.pwd
|
182
182
|
end
|
data/lib/nyara/controller.rb
CHANGED
@@ -1,8 +1,4 @@
|
|
1
1
|
module Nyara
|
2
|
-
# Contain render methods
|
3
|
-
module Renderable
|
4
|
-
end
|
5
|
-
|
6
2
|
Controller = Struct.new :request
|
7
3
|
class Controller
|
8
4
|
module ClassMethods
|
@@ -15,9 +11,12 @@ module Nyara
|
|
15
11
|
def http method, path, &blk
|
16
12
|
@routes ||= []
|
17
13
|
@used_ids = {}
|
14
|
+
method = method.to_s.upcase
|
18
15
|
|
19
16
|
action = Route.new
|
20
|
-
action.http_method = HTTP_METHODS[method]
|
17
|
+
unless action.http_method = HTTP_METHODS[method]
|
18
|
+
raise ArgumentError, "missing http method: #{method.inspect}"
|
19
|
+
end
|
21
20
|
action.path = path
|
22
21
|
action.set_accept_exts @formats
|
23
22
|
action.id = @curr_id if @curr_id
|
@@ -132,8 +131,6 @@ module Nyara
|
|
132
131
|
class_eval <<-RUBY
|
133
132
|
def __nyara_tmp_action *xs
|
134
133
|
#{senders.join}
|
135
|
-
rescue Exception => e
|
136
|
-
handle_error e
|
137
134
|
end
|
138
135
|
alias :#{e.id.inspect} __nyara_tmp_action
|
139
136
|
undef __nyara_tmp_action
|
@@ -141,7 +138,7 @@ module Nyara
|
|
141
138
|
|
142
139
|
e.compile self, scope
|
143
140
|
e.validate
|
144
|
-
@path_templates[e.id] = e.path_template
|
141
|
+
@path_templates[e.id] = [e.path_template, e.http_method_override]
|
145
142
|
end
|
146
143
|
@routes
|
147
144
|
end
|
@@ -149,8 +146,6 @@ module Nyara
|
|
149
146
|
attr_accessor :path_templates
|
150
147
|
end
|
151
148
|
|
152
|
-
include Renderable
|
153
|
-
|
154
149
|
def self.inherited klass
|
155
150
|
# note: klass will also have this inherited method
|
156
151
|
|
@@ -169,17 +164,62 @@ module Nyara
|
|
169
164
|
end
|
170
165
|
end
|
171
166
|
|
167
|
+
def self.dispatch request, instance, args
|
168
|
+
if cookie_str = request.header._aref('Cookie')
|
169
|
+
ParamHash.parse_cookie request.cookie, cookie_str
|
170
|
+
end
|
171
|
+
request.flash = Flash.new(
|
172
|
+
request.session = Session.decode(request.cookie)
|
173
|
+
)
|
174
|
+
|
175
|
+
if instance
|
176
|
+
if l = Nyara.logger
|
177
|
+
l.info "#{request.http_method} #{request.path} => #{instance.class}"
|
178
|
+
end
|
179
|
+
instance.send *args
|
180
|
+
return
|
181
|
+
elsif request.http_method == 'GET' and Config['public']
|
182
|
+
path = Config.public_path request.path
|
183
|
+
if File.file?(path)
|
184
|
+
if l = Nyara.logger
|
185
|
+
l.info "GET #{path} => public 200"
|
186
|
+
end
|
187
|
+
instance = Controller.new request
|
188
|
+
instance.send_file path
|
189
|
+
return
|
190
|
+
end
|
191
|
+
end
|
192
|
+
|
193
|
+
if l = Nyara.logger
|
194
|
+
l.info "#{request.http_method} #{request.path} => 404"
|
195
|
+
end
|
196
|
+
Ext.request_send_data request, "HTTP/1.1 404 Not Found\r\nConnection: close\r\nContent-Length: 0\r\n\r\n"
|
197
|
+
Fiber.yield :term_close
|
198
|
+
|
199
|
+
rescue Exception
|
200
|
+
instance.handle_error($!) if instance
|
201
|
+
end
|
202
|
+
|
172
203
|
# Path helper
|
173
204
|
def path_to id, *args
|
174
205
|
if args.last.is_a?(Hash)
|
175
206
|
opts = args.pop
|
176
207
|
end
|
177
208
|
|
178
|
-
|
209
|
+
template, meth = self.class.path_templates[id.to_s]
|
210
|
+
r = template % args
|
179
211
|
|
180
212
|
if opts
|
181
213
|
format = opts.delete :format
|
182
214
|
r << ".#{format}" if format
|
215
|
+
if meth and !opts.key?(:_method) and !opts.key?('_method')
|
216
|
+
opts['_method'] = meth
|
217
|
+
end
|
218
|
+
elsif meth
|
219
|
+
opts = {'_method' => meth}
|
220
|
+
end
|
221
|
+
|
222
|
+
if opts
|
183
223
|
r << '?' << opts.to_query unless opts.empty?
|
184
224
|
end
|
185
225
|
r
|
@@ -210,7 +250,7 @@ module Nyara
|
|
210
250
|
raise "unsupported redirect status: #{status}" unless HTTP_REDIRECT_STATUS.include?(status)
|
211
251
|
|
212
252
|
r = request
|
213
|
-
header = r.
|
253
|
+
header = r.response_header
|
214
254
|
self.status status
|
215
255
|
|
216
256
|
uri = URI.parse url_or_path
|
@@ -219,7 +259,7 @@ module Nyara
|
|
219
259
|
uri.port = request.port
|
220
260
|
end
|
221
261
|
uri.scheme = r.ssl? ? 'https' : 'http'
|
222
|
-
|
262
|
+
header['Location'] = uri.to_s
|
223
263
|
|
224
264
|
# similar to send_header, but without content-type
|
225
265
|
Ext.request_send_data r, HTTP_STATUS_FIRST_LINES[r.status]
|
@@ -484,6 +524,12 @@ module Nyara
|
|
484
524
|
Fiber.yield :sleep # see event.c for the handler
|
485
525
|
end
|
486
526
|
|
527
|
+
# Render a template as string
|
528
|
+
def partial view_path, locals: nil
|
529
|
+
view = View.new self, view_path, nil, nil, {}
|
530
|
+
view.partial
|
531
|
+
end
|
532
|
+
|
487
533
|
# One shot render, and terminate the action.
|
488
534
|
#
|
489
535
|
# #### Call-seq
|
@@ -545,7 +591,7 @@ module Nyara
|
|
545
591
|
def handle_error e
|
546
592
|
if l = Nyara.logger
|
547
593
|
l.error "#{e.class}: #{e.message}"
|
548
|
-
l.error e.backtrace
|
594
|
+
l.error e.backtrace.join "\n"
|
549
595
|
end
|
550
596
|
status 500
|
551
597
|
send_header rescue nil
|
data/lib/nyara/cookie.rb
CHANGED
@@ -35,30 +35,8 @@ module Nyara
|
|
35
35
|
# config['a', 'very', 'deep', 'key'] = value
|
36
36
|
#
|
37
37
|
# All intermediate level ConfigHashes are created automatically
|
38
|
-
def []= *keys,
|
39
|
-
|
40
|
-
keys.each do |key|
|
41
|
-
if h.has_key?(key)
|
42
|
-
if h.is_a?(ConfigHash)
|
43
|
-
h = h._aref key
|
44
|
-
else
|
45
|
-
h = h[key]
|
46
|
-
end
|
47
|
-
else
|
48
|
-
new_h = ConfigHash.new
|
49
|
-
if h.is_a?(ConfigHash)
|
50
|
-
h._aset key, new_h
|
51
|
-
else
|
52
|
-
h[key] = new_h
|
53
|
-
end
|
54
|
-
h = new_h
|
55
|
-
end
|
56
|
-
end
|
57
|
-
if h.is_a?(ConfigHash)
|
58
|
-
h._aset last_key, value
|
59
|
-
else
|
60
|
-
h[last_key] = value
|
61
|
-
end
|
38
|
+
def []= *keys, value
|
39
|
+
nested_aset keys.map(&:to_s), value
|
62
40
|
end
|
63
41
|
end
|
64
42
|
end
|
data/lib/nyara/nyara.rb
CHANGED
@@ -28,9 +28,6 @@ require_relative "cpu_counter"
|
|
28
28
|
require_relative "part"
|
29
29
|
require_relative "command"
|
30
30
|
|
31
|
-
# default controllers
|
32
|
-
require_relative "controllers/public_controller"
|
33
|
-
|
34
31
|
module Nyara
|
35
32
|
HTTP_STATUS_FIRST_LINES = Hash[HTTP_STATUS_CODES.map{|k,v|[k, "HTTP/1.1 #{k} #{v}\r\n".freeze]}].freeze
|
36
33
|
|
@@ -80,6 +77,24 @@ module Nyara
|
|
80
77
|
View.init
|
81
78
|
end
|
82
79
|
|
80
|
+
def load_app
|
81
|
+
Dir.chdir Config.root do
|
82
|
+
if Config.development?
|
83
|
+
require_relative "reload"
|
84
|
+
Reload.init do
|
85
|
+
# NOTE app_files can be an array
|
86
|
+
Dir.glob(Config['app_files']).uniq.each do |file|
|
87
|
+
Reload.load_file Config.project_path file
|
88
|
+
end
|
89
|
+
end
|
90
|
+
else
|
91
|
+
Dir.glob Config['app_files'] do |file|
|
92
|
+
require Config.project_path file
|
93
|
+
end
|
94
|
+
end
|
95
|
+
end
|
96
|
+
end
|
97
|
+
|
83
98
|
def start_server
|
84
99
|
port = Config[:port]
|
85
100
|
|
@@ -105,13 +120,6 @@ module Nyara
|
|
105
120
|
require_relative "patches/tcp_socket"
|
106
121
|
end
|
107
122
|
|
108
|
-
def summary_request method_num, path, controller
|
109
|
-
if l = logger
|
110
|
-
method = HTTP_METHODS.find{|k, v| method_num == v}.first
|
111
|
-
l.info "#{method} #{path} => #{controller}"
|
112
|
-
end
|
113
|
-
end
|
114
|
-
|
115
123
|
def start_development_server port
|
116
124
|
trap :INT do
|
117
125
|
exit!
|
@@ -210,15 +218,21 @@ module Nyara
|
|
210
218
|
def spawn_new_master sig
|
211
219
|
fork do
|
212
220
|
@server.close_on_exec = false
|
213
|
-
|
214
|
-
|
215
|
-
|
216
|
-
|
217
|
-
|
218
|
-
|
219
|
-
|
220
|
-
|
221
|
-
|
221
|
+
reload_all
|
222
|
+
end
|
223
|
+
end
|
224
|
+
|
225
|
+
# Reload everything
|
226
|
+
def reload_all
|
227
|
+
# todo set 1-1024 close_on_exec
|
228
|
+
Dir.chdir START_CTX[:cwd]
|
229
|
+
if File.executable?(START_CTX[0])
|
230
|
+
exec START_CTX[0], *START_CTX[:argv], close_others: false
|
231
|
+
else
|
232
|
+
# gemset env should be correct because env is inherited
|
233
|
+
require "rbconfig"
|
234
|
+
ruby = File.join(RbConfig::CONFIG['bindir'], RbConfig::CONFIG['ruby_install_name'])
|
235
|
+
exec ruby, START_CTX[0], *START_CTX[:argv], close_others: false
|
222
236
|
end
|
223
237
|
end
|
224
238
|
|
data/lib/nyara/part.rb
CHANGED
@@ -100,19 +100,22 @@ module Nyara
|
|
100
100
|
end
|
101
101
|
|
102
102
|
# NOTE `[` are `]` are escaped in url-encoded, so should not split before decode
|
103
|
-
keys =
|
103
|
+
keys = ParamHash.split_name(name)
|
104
|
+
|
104
105
|
if self['filename']
|
105
|
-
|
106
|
+
params.nested_aset keys, self
|
106
107
|
elsif self['type']
|
107
108
|
warn "looks like bad part: #{self['header'].inspect}"
|
108
109
|
else
|
109
|
-
|
110
|
+
params.nested_aset keys, CGI.unescape(self['data'])
|
110
111
|
end
|
111
112
|
end
|
112
113
|
|
113
114
|
# #### Params
|
114
115
|
#
|
115
116
|
# - `raw` in binary encoding
|
117
|
+
#
|
118
|
+
# NOTE close connection on error
|
116
119
|
def update raw
|
117
120
|
case self['mechanism']
|
118
121
|
when 'base64'
|
@@ -148,6 +151,7 @@ module Nyara
|
|
148
151
|
end
|
149
152
|
end
|
150
153
|
|
154
|
+
# NOTE close connection on error
|
151
155
|
def final
|
152
156
|
case self['mechanism']
|
153
157
|
when 'base64'
|