nyara 0.0.1.pre.2 → 0.0.1.pre.3
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/ext/accept.c +29 -33
- data/ext/event.c +218 -22
- data/ext/extconf.rb +3 -3
- data/ext/hashes.c +2 -1
- data/ext/http_parser.c +6 -0
- data/ext/inc/epoll.h +11 -9
- data/ext/inc/kqueue.h +14 -17
- data/ext/inc/str_intern.h +2 -2
- data/ext/mime.c +2 -0
- data/ext/multipart_parser.c +2 -0
- data/ext/nyara.c +2 -0
- data/ext/nyara.h +15 -9
- data/ext/request.c +88 -266
- data/ext/request.h +43 -0
- data/ext/request_parse.c +123 -0
- data/ext/route.cc +2 -0
- data/ext/url_encoded.c +66 -6
- data/hello.rb +8 -2
- data/lib/nyara/controller.rb +29 -10
- data/lib/nyara/cookie.rb +3 -2
- data/lib/nyara/nyara.rb +41 -27
- data/lib/nyara/patch_tcp_socket.rb +22 -0
- data/lib/nyara/request.rb +1 -3
- data/lib/nyara/view.rb +1 -0
- data/nyara.gemspec +1 -1
- data/rakefile +63 -42
- data/readme.md +34 -5
- data/spec/apps/connect.rb +14 -0
- data/spec/evented_io_spec.rb +23 -0
- data/spec/ext_parse_spec.rb +26 -7
- data/spec/performance/layout_render.rb +52 -0
- data/spec/performance/parse_accept_value.rb +13 -0
- data/spec/performance/parse_param.rb +18 -0
- data/spec/performance/performance_helper.rb +25 -0
- data/spec/performance_spec.rb +33 -0
- data/spec/request_delegate_spec.rb +41 -16
- data/spec/request_spec.rb +4 -7
- data/spec/spec_helper.rb +20 -10
- metadata +15 -6
- /data/lib/nyara/{config_hash.rb → hashes/config_hash.rb} +0 -0
- /data/lib/nyara/{header_hash.rb → hashes/header_hash.rb} +0 -0
- /data/lib/nyara/{param_hash.rb → hashes/param_hash.rb} +0 -0
data/ext/url_encoded.c
CHANGED
@@ -1,4 +1,5 @@
|
|
1
|
-
|
1
|
+
/* url-encoded parsing */
|
2
|
+
|
2
3
|
#include "nyara.h"
|
3
4
|
#include <ruby/encoding.h>
|
4
5
|
|
@@ -18,13 +19,13 @@ static char _half_octet(char c) {
|
|
18
19
|
}
|
19
20
|
}
|
20
21
|
|
21
|
-
static long _decode_url_seg(VALUE
|
22
|
+
static long _decode_url_seg(VALUE output, const char*s, long len, char stop_char) {
|
22
23
|
const char* last_s = s;
|
23
24
|
long last_len = 0;
|
24
25
|
|
25
26
|
# define FLUSH_UNESCAPED\
|
26
27
|
if (last_len) {\
|
27
|
-
rb_str_cat(
|
28
|
+
rb_str_cat(output, last_s, last_len);\
|
28
29
|
last_s += last_len;\
|
29
30
|
last_len = 0;\
|
30
31
|
}
|
@@ -50,7 +51,7 @@ static long _decode_url_seg(VALUE path, const char*s, long len, char stop_char)
|
|
50
51
|
unsigned char r = ((unsigned char)r1 << 4) | (unsigned char)r2;
|
51
52
|
FLUSH_UNESCAPED;
|
52
53
|
last_s += 3;
|
53
|
-
rb_str_cat(
|
54
|
+
rb_str_cat(output, (char*)&r, 1);
|
54
55
|
|
55
56
|
} else if (s[i] == stop_char) {
|
56
57
|
i++;
|
@@ -58,7 +59,7 @@ static long _decode_url_seg(VALUE path, const char*s, long len, char stop_char)
|
|
58
59
|
|
59
60
|
} else if (s[i] == '+') {
|
60
61
|
FLUSH_UNESCAPED;
|
61
|
-
rb_str_cat(
|
62
|
+
rb_str_cat(output, " ", 1);
|
62
63
|
|
63
64
|
} else {
|
64
65
|
last_len++;
|
@@ -70,9 +71,68 @@ static long _decode_url_seg(VALUE path, const char*s, long len, char stop_char)
|
|
70
71
|
return i;
|
71
72
|
}
|
72
73
|
|
74
|
+
// s should contain no space
|
73
75
|
// return parsed len, s + return == start of query
|
76
|
+
// NOTE it's similar to _decode_url_seg, but:
|
77
|
+
// - "+" is not escaped
|
78
|
+
// - matrix uri params (segments starting with ";") are ignored
|
74
79
|
long nyara_parse_path(VALUE output, const char* s, long len) {
|
75
|
-
|
80
|
+
const char* last_s = s;
|
81
|
+
long last_len = 0;
|
82
|
+
|
83
|
+
# define FLUSH_UNESCAPED\
|
84
|
+
if (last_len) {\
|
85
|
+
rb_str_cat(output, last_s, last_len);\
|
86
|
+
last_s += last_len;\
|
87
|
+
last_len = 0;\
|
88
|
+
}
|
89
|
+
|
90
|
+
long i;
|
91
|
+
for (i = 0; i < len; i++) {
|
92
|
+
if (s[i] == '%') {
|
93
|
+
if (i + 2 >= len) {
|
94
|
+
last_len++;
|
95
|
+
continue;
|
96
|
+
}
|
97
|
+
char r1 = _half_octet(s[i + 1]);
|
98
|
+
if (r1 < 0) {
|
99
|
+
last_len++;
|
100
|
+
continue;
|
101
|
+
}
|
102
|
+
char r2 = _half_octet(s[i + 2]);
|
103
|
+
if (r2 < 0) {
|
104
|
+
last_len++;
|
105
|
+
continue;
|
106
|
+
}
|
107
|
+
i += 2;
|
108
|
+
unsigned char r = ((unsigned char)r1 << 4) | (unsigned char)r2;
|
109
|
+
FLUSH_UNESCAPED;
|
110
|
+
last_s += 3;
|
111
|
+
rb_str_cat(output, (char*)&r, 1);
|
112
|
+
|
113
|
+
} else if (s[i] == ';') {
|
114
|
+
// skip matrix uri params
|
115
|
+
i++;
|
116
|
+
for (; i < len; i++) {
|
117
|
+
if (s[i] == '?') {
|
118
|
+
i++;
|
119
|
+
break;
|
120
|
+
}
|
121
|
+
}
|
122
|
+
break;
|
123
|
+
|
124
|
+
} else if (s[i] == '?') {
|
125
|
+
i++;
|
126
|
+
break;
|
127
|
+
|
128
|
+
} else {
|
129
|
+
last_len++;
|
130
|
+
}
|
131
|
+
}
|
132
|
+
FLUSH_UNESCAPED;
|
133
|
+
# undef FLUSH_UNESCAPED
|
134
|
+
|
135
|
+
return i;
|
76
136
|
}
|
77
137
|
|
78
138
|
static VALUE ext_parse_path(VALUE self, VALUE output, VALUE input) {
|
data/hello.rb
CHANGED
@@ -1,8 +1,14 @@
|
|
1
|
-
|
1
|
+
require_relative "lib/nyara"
|
2
|
+
require "open-uri"
|
3
|
+
require "pry"
|
2
4
|
|
3
|
-
|
5
|
+
configure do
|
6
|
+
# set :env, 'production'
|
7
|
+
# set :workers, 2
|
8
|
+
end
|
4
9
|
|
5
10
|
get '/' do
|
11
|
+
open 'http://baidu.com', &:read
|
6
12
|
send_string 'hello world'
|
7
13
|
end
|
8
14
|
|
data/lib/nyara/controller.rb
CHANGED
@@ -183,7 +183,7 @@ module Nyara
|
|
183
183
|
def add_header_line h
|
184
184
|
raise 'can not modify sent header' if request.response_header.frozen?
|
185
185
|
h = h.sub /(?<![\r\n])\z/, "\r\n"
|
186
|
-
request.response_header_extra_lines <<
|
186
|
+
request.response_header_extra_lines << h
|
187
187
|
end
|
188
188
|
|
189
189
|
# todo args helper
|
@@ -198,15 +198,34 @@ module Nyara
|
|
198
198
|
end
|
199
199
|
alias cookies cookie
|
200
200
|
|
201
|
-
|
201
|
+
# Set cookie, if expires is +Time.now+, will remove the cookie entry
|
202
|
+
#
|
203
|
+
# :call-seq:
|
204
|
+
#
|
205
|
+
# set_cookie 'JSESSIONID', 'not-exist'
|
206
|
+
# set_cookie 'key-without-value'
|
207
|
+
#
|
208
|
+
# +opt: default_value+ are:
|
209
|
+
#
|
210
|
+
# expires: nil
|
211
|
+
# max_age: nil
|
212
|
+
# domain: nil
|
213
|
+
# path: nil
|
214
|
+
# secure: nil
|
215
|
+
# httponly: true
|
216
|
+
#
|
217
|
+
def set_cookie name, value=nil, opts={}
|
218
|
+
if value.is_a?(Hash)
|
219
|
+
raise ArgumentError, 'hash not allowed in cookie value, did you mean to use it as options?'
|
220
|
+
end
|
202
221
|
# todo default domain ?
|
203
222
|
opts = Hash[opts.map{|k,v| [k.to_sym,v]}]
|
204
|
-
Cookie.
|
223
|
+
Cookie.add_set_cookie request.response_header_extra_lines, name, value, opts
|
205
224
|
end
|
206
225
|
|
207
|
-
def delete_cookie
|
226
|
+
def delete_cookie name
|
208
227
|
# todo domain ? path ?
|
209
|
-
set_cookie
|
228
|
+
set_cookie name, nil, expires: Time.now, max_age: 0
|
210
229
|
end
|
211
230
|
|
212
231
|
def clear_cookie
|
@@ -238,7 +257,7 @@ module Nyara
|
|
238
257
|
r = request
|
239
258
|
header = r.response_header
|
240
259
|
|
241
|
-
Ext.
|
260
|
+
Ext.request_send_data r, HTTP_STATUS_FIRST_LINES[r.status]
|
242
261
|
|
243
262
|
header.aset_content_type \
|
244
263
|
r.response_content_type ||
|
@@ -254,7 +273,7 @@ module Nyara
|
|
254
273
|
end
|
255
274
|
data.concat r.response_header_extra_lines
|
256
275
|
data << "\r\n"
|
257
|
-
Ext.
|
276
|
+
Ext.request_send_data r, data.join
|
258
277
|
|
259
278
|
# forbid further modification
|
260
279
|
header.freeze
|
@@ -263,17 +282,17 @@ module Nyara
|
|
263
282
|
# Send raw data, that is, not wrapped in chunked encoding<br>
|
264
283
|
# NOTE: often you should call send_header before doing this.
|
265
284
|
def send_data data
|
266
|
-
Ext.
|
285
|
+
Ext.request_send_data request, data.to_s
|
267
286
|
end
|
268
287
|
|
269
288
|
# Send a data chunk, it can send_header first if header is not sent.
|
270
|
-
#
|
289
|
+
#
|
271
290
|
# :call-seq:
|
272
291
|
#
|
273
292
|
# send_chunk 'hello world!'
|
274
293
|
def send_chunk data
|
275
294
|
send_header unless request.response_header.frozen?
|
276
|
-
Ext.
|
295
|
+
Ext.request_send_chunk request, data.to_s
|
277
296
|
end
|
278
297
|
alias send_string send_chunk
|
279
298
|
|
data/lib/nyara/cookie.rb
CHANGED
@@ -11,8 +11,8 @@ module Nyara
|
|
11
11
|
res
|
12
12
|
end
|
13
13
|
|
14
|
-
def add_set_cookie
|
15
|
-
r
|
14
|
+
def add_set_cookie header_lines, k, v, expires: nil, max_age: nil, domain: nil, path: nil, secure: nil, httponly: true
|
15
|
+
r = "Set-Cookie: "
|
16
16
|
if v.nil? or v == true
|
17
17
|
r << "#{CGI.escape k.to_s}; "
|
18
18
|
else
|
@@ -26,6 +26,7 @@ module Nyara
|
|
26
26
|
r << "Secure; " if secure
|
27
27
|
r << "HttpOnly; " if httponly
|
28
28
|
r << "\r\n"
|
29
|
+
header_lines << r
|
29
30
|
end
|
30
31
|
end
|
31
32
|
end
|
data/lib/nyara/nyara.rb
CHANGED
@@ -8,9 +8,9 @@ require "socket"
|
|
8
8
|
require "tilt"
|
9
9
|
|
10
10
|
require_relative "../../ext/nyara"
|
11
|
-
require_relative "param_hash"
|
12
|
-
require_relative "header_hash"
|
13
|
-
require_relative "config_hash"
|
11
|
+
require_relative "hashes/param_hash"
|
12
|
+
require_relative "hashes/header_hash"
|
13
|
+
require_relative "hashes/config_hash"
|
14
14
|
require_relative "mime_types"
|
15
15
|
require_relative "controller"
|
16
16
|
require_relative "request"
|
@@ -43,40 +43,54 @@ module Nyara
|
|
43
43
|
|
44
44
|
def start_server
|
45
45
|
port = Config[:port] || 3000
|
46
|
-
workers = Config[:workers] || (CpuCounter.count - 1)
|
47
46
|
|
48
47
|
puts "starting #{Config[:env]} server at 0.0.0.0:#{port}"
|
49
48
|
case Config[:env].to_s
|
50
|
-
|
51
49
|
when 'production'
|
52
|
-
|
53
|
-
|
54
|
-
trap :INT do
|
55
|
-
@workers.each do |w|
|
56
|
-
Process.kill :KILL, w
|
57
|
-
end
|
58
|
-
end
|
59
|
-
GC.start
|
60
|
-
@workers = workers.times.map do
|
61
|
-
fork {
|
62
|
-
Ext.init_queue
|
63
|
-
Ext.run_queue server.fileno
|
64
|
-
}
|
65
|
-
end
|
66
|
-
Process.waitall
|
67
|
-
|
50
|
+
patch_tcp_socket
|
51
|
+
start_production_server port
|
68
52
|
when 'test'
|
69
53
|
# don't
|
70
|
-
|
71
54
|
else
|
72
|
-
|
73
|
-
|
74
|
-
|
55
|
+
patch_tcp_socket
|
56
|
+
start_development_server port
|
57
|
+
end
|
58
|
+
end
|
59
|
+
|
60
|
+
def patch_tcp_socket
|
61
|
+
puts "patching TCPSocket"
|
62
|
+
require_relative "patch_tcp_socket"
|
63
|
+
end
|
64
|
+
|
65
|
+
def start_production_server port
|
66
|
+
workers = Config[:workers] || ((CpuCounter.count + 1)/ 2)
|
67
|
+
|
68
|
+
puts "workers: #{workers}"
|
69
|
+
server = TCPServer.new '0.0.0.0', port
|
70
|
+
server.listen 1000
|
71
|
+
trap :INT do
|
72
|
+
@workers.each do |w|
|
73
|
+
Process.kill :KILL, w
|
74
|
+
end
|
75
|
+
end
|
76
|
+
GC.start
|
77
|
+
@workers = workers.times.map do
|
78
|
+
fork {
|
75
79
|
Ext.init_queue
|
76
80
|
Ext.run_queue server.fileno
|
77
|
-
|
78
|
-
|
81
|
+
}
|
82
|
+
end
|
83
|
+
Process.waitall
|
84
|
+
end
|
85
|
+
|
86
|
+
def start_development_server port
|
87
|
+
t = Thread.new do
|
88
|
+
server = TCPServer.new '0.0.0.0', port
|
89
|
+
server.listen 1000
|
90
|
+
Ext.init_queue
|
91
|
+
Ext.run_queue server.fileno
|
79
92
|
end
|
93
|
+
t.join
|
80
94
|
end
|
81
95
|
end
|
82
96
|
end
|
@@ -0,0 +1,22 @@
|
|
1
|
+
# patch TCPSocket to make operations synchrony
|
2
|
+
class TCPSocket
|
3
|
+
alias _orig_initialize initialize
|
4
|
+
|
5
|
+
def initialize *xs
|
6
|
+
_orig_initialize *xs
|
7
|
+
Nyara::Ext.set_nonblock fileno
|
8
|
+
Nyara::Ext.fd_watch fileno
|
9
|
+
end
|
10
|
+
|
11
|
+
def send data, flags, dest_addr=nil, &blk
|
12
|
+
if dest_addr
|
13
|
+
super
|
14
|
+
else
|
15
|
+
Nyara::Ext.fd_send fileno, data, flags, &blk
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
def recv max_len, flags=0
|
20
|
+
Nyara::Ext.fd_recv fileno, max_len, flags
|
21
|
+
end
|
22
|
+
end
|
data/lib/nyara/request.rb
CHANGED
@@ -133,9 +133,7 @@ module Nyara
|
|
133
133
|
|
134
134
|
# todo rename and move it into Ext
|
135
135
|
def not_found
|
136
|
-
|
137
|
-
Ext.send_data self, "HTTP/1.1 404 Not Found\r\nConnection: close\r\nContent-Length: 0\r\n\r\n"
|
138
|
-
Ext.close self
|
136
|
+
Ext.request_send_data self, "HTTP/1.1 404 Not Found\r\nConnection: close\r\nContent-Length: 0\r\n\r\n"
|
139
137
|
end
|
140
138
|
end
|
141
139
|
end
|
data/lib/nyara/view.rb
CHANGED
@@ -128,6 +128,7 @@ module Nyara
|
|
128
128
|
ENGINE_DEFAULT_CONTENT_TYPES[ext] = default_content_type
|
129
129
|
end
|
130
130
|
|
131
|
+
# local keys are for first-time code generation, values not used
|
131
132
|
# returns +[meth, ext_without_dot]+
|
132
133
|
def template path, locals={}
|
133
134
|
if File.extname(path).empty?
|
data/nyara.gemspec
CHANGED
data/rakefile
CHANGED
@@ -58,43 +58,6 @@ task :build => makefile do
|
|
58
58
|
end
|
59
59
|
end
|
60
60
|
|
61
|
-
def term_color n
|
62
|
-
print "\e[38;5;#{n}m"
|
63
|
-
end
|
64
|
-
|
65
|
-
def reset_color
|
66
|
-
print "\e[00m"
|
67
|
-
end
|
68
|
-
|
69
|
-
desc "check arity of rb_define_method/rb_define_singleton_method"
|
70
|
-
task :check_arity do
|
71
|
-
Dir.glob 'ext/*.{c,cc}' do |f|
|
72
|
-
puts "validatign #{f}"
|
73
|
-
arities = {}
|
74
|
-
data = File.read f
|
75
|
-
data.scan /^(?:static )?VALUE (\w+)\((.+)\)/ do |func, params|
|
76
|
-
arities[func] = params.count(',')
|
77
|
-
puts " scan: #{func}/#{arities[func]}"
|
78
|
-
end
|
79
|
-
data.scan /rb_define(?:_singleton)?_method\(.*?(\w+)\s*\,\s*(\d+)\)/ do |func, arity|
|
80
|
-
print " check: #{func}/#{arity} "
|
81
|
-
if arities[func].nil?
|
82
|
-
term_color 5
|
83
|
-
print "UNSCANNED"
|
84
|
-
reset_color
|
85
|
-
puts
|
86
|
-
elsif arities[func] != arity.to_i
|
87
|
-
term_color 9
|
88
|
-
print "MISMATCH #{arities[func]}"
|
89
|
-
reset_color
|
90
|
-
puts
|
91
|
-
else
|
92
|
-
puts "OK"
|
93
|
-
end
|
94
|
-
end
|
95
|
-
end
|
96
|
-
end
|
97
|
-
|
98
61
|
desc "test"
|
99
62
|
task :test => :build do
|
100
63
|
sh 'rspec', '-c'
|
@@ -118,6 +81,7 @@ task :clean do
|
|
118
81
|
sh 'rm', '-f', '*.gem'
|
119
82
|
Dir.chdir 'ext' do
|
120
83
|
sh 'make', 'clean'
|
84
|
+
sh 'rm', '-f', 'Makefile'
|
121
85
|
end
|
122
86
|
end
|
123
87
|
|
@@ -125,15 +89,72 @@ end
|
|
125
89
|
|
126
90
|
desc "collect line stat"
|
127
91
|
task :lines do
|
128
|
-
|
129
|
-
Dir.glob('
|
130
|
-
|
92
|
+
rb_c = 0
|
93
|
+
Dir.glob('**/*.rb') do |f|
|
94
|
+
rb_c += (File.read(f).count "\n")
|
95
|
+
end
|
96
|
+
|
97
|
+
c_c = 0
|
98
|
+
Dir.glob('ext/*.{c,cc,h}') do |f|
|
99
|
+
c_c += (File.read(f).count "\n")
|
100
|
+
end
|
101
|
+
|
102
|
+
spec_c = 0
|
103
|
+
Dir.glob('spec/**/*.rb') do |f|
|
104
|
+
spec_c += (File.read(f).count "\n")
|
131
105
|
end
|
132
|
-
|
106
|
+
|
107
|
+
puts "c: #{c_c} lines"
|
108
|
+
puts "rb: #{rb_c - spec_c} lines"
|
109
|
+
puts "spec: #{spec_c} lines"
|
133
110
|
end
|
134
111
|
|
135
112
|
desc "list Nyara::Ext methods"
|
136
113
|
task :list_ext do
|
137
114
|
require_relative "lib/nyara/nyara"
|
138
|
-
|
115
|
+
methods = (Nyara::Ext.methods - Module.methods).sort
|
116
|
+
[/queue/, /route/, /parse/, /request/].each do |r|
|
117
|
+
group = methods.grep r
|
118
|
+
puts group
|
119
|
+
puts
|
120
|
+
methods -= group
|
121
|
+
end
|
122
|
+
puts methods
|
123
|
+
end
|
124
|
+
|
125
|
+
def term_color n
|
126
|
+
print "\e[38;5;#{n}m"
|
127
|
+
end
|
128
|
+
|
129
|
+
def reset_color
|
130
|
+
print "\e[00m"
|
131
|
+
end
|
132
|
+
|
133
|
+
desc "audit arity of rb_define_method/rb_define_singleton_method"
|
134
|
+
task :audit_arity do
|
135
|
+
Dir.glob 'ext/*.{c,cc}' do |f|
|
136
|
+
puts "validatign #{f}"
|
137
|
+
arities = {}
|
138
|
+
data = File.read f
|
139
|
+
data.scan /^(?:static )?VALUE (\w+)\((.+)\)/ do |func, params|
|
140
|
+
arities[func] = params.count(',')
|
141
|
+
puts " scan: #{func}/#{arities[func]}"
|
142
|
+
end
|
143
|
+
data.scan /rb_define(?:_singleton)?_method\(.*?(\w+)\s*\,\s*(\d+)\)/ do |func, arity|
|
144
|
+
print " check: #{func}/#{arity} "
|
145
|
+
if arities[func].nil?
|
146
|
+
term_color 5
|
147
|
+
print "UNSCANNED"
|
148
|
+
reset_color
|
149
|
+
puts
|
150
|
+
elsif arities[func] != arity.to_i
|
151
|
+
term_color 9
|
152
|
+
print "MISMATCH #{arities[func]}"
|
153
|
+
reset_color
|
154
|
+
puts
|
155
|
+
else
|
156
|
+
puts "OK"
|
157
|
+
end
|
158
|
+
end
|
159
|
+
end
|
139
160
|
end
|
data/readme.md
CHANGED
@@ -8,7 +8,7 @@ Not Yet Another Ruby Async web framework and server. Not on rack nor rack-compat
|
|
8
8
|
|
9
9
|
# Getting started
|
10
10
|
|
11
|
-
Requires Ruby 2.0+, BSD/Linux/Mac OS X.
|
11
|
+
Requires Ruby 2.0+, BSD/Linux/Mac OS X, GCC4.7+ or Clang.
|
12
12
|
|
13
13
|
Install
|
14
14
|
|
@@ -42,6 +42,33 @@ rake gen
|
|
42
42
|
rake gem
|
43
43
|
```
|
44
44
|
|
45
|
+
If you have cloned the repo once, and want to update code
|
46
|
+
|
47
|
+
```bash
|
48
|
+
git pull --recurse-submodules
|
49
|
+
git submodule foreach git fetch
|
50
|
+
```
|
51
|
+
|
52
|
+
# Testing
|
53
|
+
|
54
|
+
Simply run the test
|
55
|
+
|
56
|
+
```bash
|
57
|
+
rspec -c
|
58
|
+
```
|
59
|
+
|
60
|
+
Test in GC.stress mode
|
61
|
+
|
62
|
+
```bash
|
63
|
+
rspec -c -f d
|
64
|
+
```
|
65
|
+
|
66
|
+
With coverage (generates *coverage/index.html*)
|
67
|
+
|
68
|
+
```bash
|
69
|
+
COVERAGE=1 rspec -c
|
70
|
+
```
|
71
|
+
|
45
72
|
# Why fast
|
46
73
|
|
47
74
|
### Solid http parsers written in C
|
@@ -87,10 +114,12 @@ In Nyara, nested templates of Slim, ERB or Haml share the same output buffer, so
|
|
87
114
|
|
88
115
|
# How fast
|
89
116
|
|
90
|
-
Performance is feature, there are specs on
|
117
|
+
Performance is feature, there are specs on:
|
91
118
|
|
92
|
-
- Accept-* parse vs
|
93
|
-
- MIME matching vs rack
|
119
|
+
- Accept-* parse vs sinatra
|
94
120
|
- param parse vs ruby
|
95
121
|
- layout rendering vs tilt
|
96
|
-
|
122
|
+
|
123
|
+
# License
|
124
|
+
|
125
|
+
BSD, see copying
|
@@ -0,0 +1,23 @@
|
|
1
|
+
require_relative "spec_helper"
|
2
|
+
|
3
|
+
module Nyara
|
4
|
+
describe 'evented IO' do
|
5
|
+
before :all do
|
6
|
+
pid = Process.pid
|
7
|
+
@server = fork do
|
8
|
+
exec 'ruby', __dir__ + '/apps/connect.rb'
|
9
|
+
end
|
10
|
+
sleep 1 # wait for server startup
|
11
|
+
end
|
12
|
+
|
13
|
+
after :all do
|
14
|
+
Process.kill :KILL, @server
|
15
|
+
end
|
16
|
+
|
17
|
+
it "works" do
|
18
|
+
result1 = open "http://localhost:3003", &:read
|
19
|
+
result2 = open "http://baidu.com", &:read
|
20
|
+
assert_equal result2, result1
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
data/spec/ext_parse_spec.rb
CHANGED
@@ -63,47 +63,66 @@ module Nyara
|
|
63
63
|
@output = ''
|
64
64
|
end
|
65
65
|
|
66
|
-
it "
|
66
|
+
it "converts '%' bytes but not '+'" do
|
67
67
|
i = '/%23+%24'
|
68
68
|
assert_equal i.bytesize, parse(i)
|
69
|
-
assert_equal "/\x23
|
69
|
+
assert_equal "/\x23+\x24", @output
|
70
70
|
end
|
71
71
|
|
72
|
-
it "truncates ? after %" do
|
72
|
+
it "truncates '?' after %" do
|
73
73
|
i = '/hello%f3%?world'
|
74
74
|
len = parse i
|
75
75
|
assert_equal '/hello%f3%?'.bytesize, len
|
76
76
|
assert_equal "/hello\xf3%", @output
|
77
77
|
end
|
78
78
|
|
79
|
-
it "truncates ? after begin" do
|
79
|
+
it "truncates '?' after begin" do
|
80
80
|
i = '?a'
|
81
81
|
len = parse i
|
82
82
|
assert_equal 1, len
|
83
83
|
assert_equal '', @output
|
84
84
|
end
|
85
85
|
|
86
|
-
it "truncates ? before end" do
|
86
|
+
it "truncates '?' before end" do
|
87
87
|
i = 'a?'
|
88
88
|
len = parse i
|
89
89
|
assert_equal 2, len
|
90
90
|
assert_equal 'a', @output
|
91
91
|
end
|
92
92
|
|
93
|
-
it "truncates ? after unescaped char" do
|
93
|
+
it "truncates '?' after unescaped char" do
|
94
94
|
i = 'a?a'
|
95
95
|
len = parse i
|
96
96
|
assert_equal 2, len
|
97
97
|
assert_equal 'a', @output
|
98
98
|
end
|
99
99
|
|
100
|
-
it "truncates ? after escaped char" do
|
100
|
+
it "truncates '?' after escaped char" do
|
101
101
|
i = '%40?'
|
102
102
|
len = parse i
|
103
103
|
assert_equal 4, len
|
104
104
|
assert_equal "\x40", @output
|
105
105
|
end
|
106
106
|
|
107
|
+
it "removes matrix uri params" do
|
108
|
+
i = '/a;matrix;matrix=3'
|
109
|
+
len = parse i
|
110
|
+
assert_equal i.size, len
|
111
|
+
assert_equal "/a", @output
|
112
|
+
|
113
|
+
@output = ''
|
114
|
+
i += '?'
|
115
|
+
len = parse i
|
116
|
+
assert_equal i.size, len
|
117
|
+
assert_equal "/a", @output
|
118
|
+
|
119
|
+
@output = ''
|
120
|
+
i += 'query'
|
121
|
+
len = parse i
|
122
|
+
assert_equal i.size - 'query'.size, len
|
123
|
+
assert_equal '/a', @output
|
124
|
+
end
|
125
|
+
|
107
126
|
def parse input
|
108
127
|
Ext.parse_path @output, input
|
109
128
|
end
|