nyara 0.0.1.pre
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/example/design.rb +62 -0
- data/example/fib.rb +15 -0
- data/example/hello.rb +5 -0
- data/example/stream.rb +10 -0
- data/ext/accept.c +133 -0
- data/ext/event.c +89 -0
- data/ext/extconf.rb +34 -0
- data/ext/hashes.c +130 -0
- data/ext/http-parser/AUTHORS +41 -0
- data/ext/http-parser/CONTRIBUTIONS +4 -0
- data/ext/http-parser/LICENSE-MIT +23 -0
- data/ext/http-parser/contrib/parsertrace.c +156 -0
- data/ext/http-parser/contrib/url_parser.c +44 -0
- data/ext/http-parser/http_parser.c +2175 -0
- data/ext/http-parser/http_parser.h +304 -0
- data/ext/http-parser/test.c +3425 -0
- data/ext/http_parser.c +1 -0
- data/ext/inc/epoll.h +60 -0
- data/ext/inc/kqueue.h +77 -0
- data/ext/inc/status_codes.inc +64 -0
- data/ext/inc/str_intern.h +66 -0
- data/ext/inc/version.inc +1 -0
- data/ext/mime.c +107 -0
- data/ext/multipart-parser-c/README.md +18 -0
- data/ext/multipart-parser-c/multipart_parser.c +309 -0
- data/ext/multipart-parser-c/multipart_parser.h +48 -0
- data/ext/multipart_parser.c +1 -0
- data/ext/nyara.c +56 -0
- data/ext/nyara.h +59 -0
- data/ext/request.c +474 -0
- data/ext/route.cc +325 -0
- data/ext/url_encoded.c +304 -0
- data/hello.rb +5 -0
- data/lib/nyara/config.rb +64 -0
- data/lib/nyara/config_hash.rb +51 -0
- data/lib/nyara/controller.rb +336 -0
- data/lib/nyara/cookie.rb +31 -0
- data/lib/nyara/cpu_counter.rb +65 -0
- data/lib/nyara/header_hash.rb +18 -0
- data/lib/nyara/mime_types.rb +612 -0
- data/lib/nyara/nyara.rb +82 -0
- data/lib/nyara/param_hash.rb +5 -0
- data/lib/nyara/request.rb +144 -0
- data/lib/nyara/route.rb +138 -0
- data/lib/nyara/route_entry.rb +43 -0
- data/lib/nyara/session.rb +104 -0
- data/lib/nyara/view.rb +317 -0
- data/lib/nyara.rb +25 -0
- data/nyara.gemspec +20 -0
- data/rakefile +91 -0
- data/readme.md +35 -0
- data/spec/ext_mime_match_spec.rb +27 -0
- data/spec/ext_parse_accept_value_spec.rb +29 -0
- data/spec/ext_parse_spec.rb +138 -0
- data/spec/ext_route_spec.rb +70 -0
- data/spec/hashes_spec.rb +71 -0
- data/spec/path_helper_spec.rb +77 -0
- data/spec/request_delegate_spec.rb +67 -0
- data/spec/request_spec.rb +56 -0
- data/spec/route_entry_spec.rb +12 -0
- data/spec/route_spec.rb +84 -0
- data/spec/session_spec.rb +66 -0
- data/spec/spec_helper.rb +52 -0
- data/spec/view_spec.rb +87 -0
- data/tools/bench-cookie.rb +22 -0
- metadata +111 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: cb0049e820e49ff09f09423ecce778a56834fd82
|
4
|
+
data.tar.gz: 30a2651c518f2f7c3db0581396b52ef1655c4ce8
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: b43a204aa71c4a3b1f2a94b21ee87be98d0e78348e93d9ba7439df27cb383cced9d1135e3ac1ce47e6bd7479d8542456360ce1c297399eaa77cfcce41871ea79
|
7
|
+
data.tar.gz: 955570020bccc660c5d7ae82ecad85c821988f92ebc80b4beffaa84575a1b487ccecf07be51d6041c7a88af62565e6a61260bec11009dacaf0c88814decedca7
|
data/example/design.rb
ADDED
@@ -0,0 +1,62 @@
|
|
1
|
+
meta '#hello', accept: %w[js html] | default is text/html, default / * not implemented yet
|
2
|
+
get '/' do
|
3
|
+
send_data ... --> will make encoding chunked
|
4
|
+
|
5
|
+
# set resp status
|
6
|
+
status 302 | :not_found
|
7
|
+
|
8
|
+
# content type is separated out from render
|
9
|
+
content_type :js
|
10
|
+
|
11
|
+
# terminal action : render view, or file for download
|
12
|
+
render ..., layout: [a, b, c]
|
13
|
+
|
14
|
+
render file # choose renderer by ext
|
15
|
+
render :slim => template_content
|
16
|
+
|
17
|
+
... Fiber.yield
|
18
|
+
|
19
|
+
s = stream ... # same arg as render
|
20
|
+
...
|
21
|
+
r.resume
|
22
|
+
...
|
23
|
+
r.resume
|
24
|
+
|
25
|
+
render :slim, 'content'
|
26
|
+
|
27
|
+
# terminal action
|
28
|
+
redirect_to path_for '...'
|
29
|
+
redirect_to '/'
|
30
|
+
redirect_to :back # referrer
|
31
|
+
|
32
|
+
# terminate process
|
33
|
+
halt status
|
34
|
+
|
35
|
+
# loop response
|
36
|
+
loop do
|
37
|
+
sleep 4
|
38
|
+
send_data ...
|
39
|
+
end
|
40
|
+
|
41
|
+
# can use accept when meta is configured, raise error if not configured
|
42
|
+
case accept
|
43
|
+
when 'html'
|
44
|
+
...
|
45
|
+
when 'js'
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
# default is no scheme, the links start with // to fit all schemes
|
50
|
+
configure url_for, default_scheme nil / 'https'
|
51
|
+
|
52
|
+
url_for '#b', scheme: 'http', format: 'js', host: 'a.b.c:3000' # string keys are put in query
|
53
|
+
|
54
|
+
path_for 'cont#action', 12, 3, :format => 'js', # string keys are put in query, (what about hash tags?)
|
55
|
+
|
56
|
+
partial '...'
|
57
|
+
|
58
|
+
# for middleware, we use life cycle callbacks
|
59
|
+
# on :header_complete
|
60
|
+
# on :init
|
61
|
+
|
62
|
+
# before
|
data/example/fib.rb
ADDED
data/example/hello.rb
ADDED
data/example/stream.rb
ADDED
data/ext/accept.c
ADDED
@@ -0,0 +1,133 @@
|
|
1
|
+
/* efficient Accpet-* value parser in C */
|
2
|
+
|
3
|
+
#include "nyara.h"
|
4
|
+
#include <ctype.h>
|
5
|
+
#include "inc/str_intern.h"
|
6
|
+
|
7
|
+
// standard:
|
8
|
+
// http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html
|
9
|
+
// about +q+:
|
10
|
+
// http://www.gethifi.com/blog/browser-rest-http-accept-headers
|
11
|
+
// +level+ is a waste of time:
|
12
|
+
// http://stackoverflow.com/questions/13890996/http-accept-level
|
13
|
+
|
14
|
+
// sorted data structure
|
15
|
+
typedef struct {
|
16
|
+
double* qs;
|
17
|
+
long len;
|
18
|
+
long cap;
|
19
|
+
} QArray;
|
20
|
+
|
21
|
+
static QArray qarray_new() {
|
22
|
+
QArray qa = {ALLOC_N(double, 10), 0, 10};
|
23
|
+
return qa;
|
24
|
+
}
|
25
|
+
|
26
|
+
// return inserted pos
|
27
|
+
static long qarray_insert(QArray* qa, double v) {
|
28
|
+
if (qa->len == qa->cap) {
|
29
|
+
qa->cap *= 2;
|
30
|
+
REALLOC_N(qa->qs, double, qa->cap);
|
31
|
+
}
|
32
|
+
long i = 0;
|
33
|
+
for (; i < qa->len; i++) {
|
34
|
+
if (qa->qs[i] < v) {
|
35
|
+
memmove(qa->qs + i + 1, qa->qs + i, sizeof(double) * (qa->len - i));
|
36
|
+
break;
|
37
|
+
}
|
38
|
+
}
|
39
|
+
qa->qs[i] = v;
|
40
|
+
qa->len++;
|
41
|
+
return i;
|
42
|
+
}
|
43
|
+
|
44
|
+
static void qarray_delete(QArray* qa) {
|
45
|
+
xfree(qa->qs);
|
46
|
+
}
|
47
|
+
|
48
|
+
static VALUE trim_space(VALUE str) {
|
49
|
+
long olen = RSTRING_LEN(str);
|
50
|
+
str = rb_str_new(RSTRING_PTR(str), olen);
|
51
|
+
char* s = RSTRING_PTR(str);
|
52
|
+
long len = 0;
|
53
|
+
for (long i = 0; i < olen; i++) {
|
54
|
+
if (!isspace(s[i])) {
|
55
|
+
s[len++] = s[i];
|
56
|
+
}
|
57
|
+
}
|
58
|
+
STR_SET_LEN(str, len);
|
59
|
+
return str;
|
60
|
+
}
|
61
|
+
|
62
|
+
// stopped by ',' or EOS, return seg_len
|
63
|
+
static long find_seg(const char* s, long len) {
|
64
|
+
long i = 0;
|
65
|
+
for (; i < len; i++) {
|
66
|
+
if (s[i] == ',') {
|
67
|
+
break;
|
68
|
+
}
|
69
|
+
}
|
70
|
+
return i;
|
71
|
+
}
|
72
|
+
|
73
|
+
// return first pointer to ';q='
|
74
|
+
static const char* find_q(const char* s, long len) {
|
75
|
+
for (long i = 0; i < (len - 2); i++) {
|
76
|
+
if (s[i] == ';' && s[i+1] == 'q' && s[i+2] == '=') {
|
77
|
+
return s + i;
|
78
|
+
}
|
79
|
+
}
|
80
|
+
return NULL;
|
81
|
+
}
|
82
|
+
|
83
|
+
// parse a segment, and +out[value] = q+
|
84
|
+
static void parse_seg(const char* s, long len, VALUE out, QArray* qa) {
|
85
|
+
double qval = 1;
|
86
|
+
const char* q = find_q(s, len);
|
87
|
+
if (q) {
|
88
|
+
if (q == s) {
|
89
|
+
return;
|
90
|
+
}
|
91
|
+
char* str_end = (char*)q + 3;
|
92
|
+
qval = strtod(q + 3, &str_end);
|
93
|
+
if (str_end == q + 3 || isnan(qval) || qval > 3) {
|
94
|
+
qval = 1;
|
95
|
+
} else if (qval <= 0) {
|
96
|
+
return;
|
97
|
+
}
|
98
|
+
len = q - s;
|
99
|
+
}
|
100
|
+
long pos = qarray_insert(qa, qval);
|
101
|
+
rb_ary_push(out, Qnil); // just to increase cap
|
102
|
+
VALUE* out_ptr = RARRAY_PTR(out);
|
103
|
+
long out_len = RARRAY_LEN(out); // note this len is +1
|
104
|
+
memmove(out_ptr + pos + 1, out_ptr + pos, sizeof(VALUE) * (out_len - pos - 1));
|
105
|
+
rb_ary_store(out, pos, rb_str_new(s, len));
|
106
|
+
}
|
107
|
+
|
108
|
+
VALUE ext_parse_accept_value(VALUE _, VALUE str) {
|
109
|
+
if (str == Qnil) {
|
110
|
+
return rb_ary_new();
|
111
|
+
}
|
112
|
+
|
113
|
+
str = trim_space(str);
|
114
|
+
const char* s = RSTRING_PTR(str);
|
115
|
+
long len = RSTRING_LEN(str);
|
116
|
+
volatile VALUE out = rb_ary_new();
|
117
|
+
QArray qa = qarray_new();
|
118
|
+
while (len > 0) {
|
119
|
+
long seg_len = find_seg(s, len);
|
120
|
+
if (seg_len == 0) {
|
121
|
+
break;
|
122
|
+
}
|
123
|
+
parse_seg(s, seg_len, out, &qa);
|
124
|
+
s += seg_len + 1;
|
125
|
+
len -= seg_len + 1;
|
126
|
+
}
|
127
|
+
qarray_delete(&qa);
|
128
|
+
return out;
|
129
|
+
}
|
130
|
+
|
131
|
+
void Init_accept(VALUE ext) {
|
132
|
+
rb_define_singleton_method(ext, "parse_accept_value", ext_parse_accept_value, 1);
|
133
|
+
}
|
data/ext/event.c
ADDED
@@ -0,0 +1,89 @@
|
|
1
|
+
#include "nyara.h"
|
2
|
+
#include <sys/fcntl.h>
|
3
|
+
#include <sys/socket.h>
|
4
|
+
#include <errno.h>
|
5
|
+
#include <stdint.h>
|
6
|
+
#include <unistd.h>
|
7
|
+
|
8
|
+
#define ETYPE_ACCEPT 0
|
9
|
+
#define ETYPE_REQUEST 1
|
10
|
+
#define ETYPE_CONNECT 2
|
11
|
+
#define MAX_E 1024
|
12
|
+
static void loop_body(int fd, int etype);
|
13
|
+
static int qfd;
|
14
|
+
|
15
|
+
#ifdef HAVE_KQUEUE
|
16
|
+
#include "inc/kqueue.h"
|
17
|
+
#elif HAVE_EPOLL
|
18
|
+
#include "inc/epoll.h"
|
19
|
+
#endif
|
20
|
+
|
21
|
+
static void set_nonblock(int fd) {
|
22
|
+
int flags;
|
23
|
+
|
24
|
+
if ((flags = fcntl(fd, F_GETFL)) == -1) {
|
25
|
+
rb_raise(rb_eRuntimeError, "fcntl(F_GETFL): %s", strerror(errno));
|
26
|
+
}
|
27
|
+
if (fcntl(fd, F_SETFL, flags | O_NONBLOCK) == -1) {
|
28
|
+
rb_raise(rb_eRuntimeError, "fcntl(F_SETFL,O_NONBLOCK): %s", strerror(errno));
|
29
|
+
}
|
30
|
+
}
|
31
|
+
|
32
|
+
static VALUE ext_add(VALUE _, VALUE vfd) {
|
33
|
+
int fd = FIX2INT(vfd);
|
34
|
+
ADD_E(fd, ETYPE_CONNECT);
|
35
|
+
return Qnil;
|
36
|
+
}
|
37
|
+
|
38
|
+
// platform independent, invoked by LOOP_E()
|
39
|
+
static void loop_body(int fd, int etype) {
|
40
|
+
switch (etype) {
|
41
|
+
case ETYPE_ACCEPT: {
|
42
|
+
int cfd = accept(fd, NULL, NULL);
|
43
|
+
if (cfd > 0) {
|
44
|
+
set_nonblock(cfd);
|
45
|
+
ADD_E(cfd, ETYPE_REQUEST);
|
46
|
+
}
|
47
|
+
break;
|
48
|
+
}
|
49
|
+
case ETYPE_REQUEST: {
|
50
|
+
nyara_handle_request(fd);
|
51
|
+
break;
|
52
|
+
}
|
53
|
+
case ETYPE_CONNECT: {
|
54
|
+
// todo
|
55
|
+
// NOTE
|
56
|
+
// fd and connection are 1:1, there can more more than 1 fds on a same file / address
|
57
|
+
// so it's streight forward to using fd as query index
|
58
|
+
}
|
59
|
+
}
|
60
|
+
}
|
61
|
+
|
62
|
+
static VALUE ext_init_queue(VALUE _) {
|
63
|
+
INIT_E();
|
64
|
+
return Qnil;
|
65
|
+
}
|
66
|
+
|
67
|
+
static VALUE ext_run_queue(VALUE _, VALUE v_fd) {
|
68
|
+
int fd = FIX2INT(v_fd);
|
69
|
+
set_nonblock(fd);
|
70
|
+
ADD_E(fd, ETYPE_ACCEPT);
|
71
|
+
|
72
|
+
LOOP_E();
|
73
|
+
return Qnil;
|
74
|
+
}
|
75
|
+
|
76
|
+
static VALUE ext_set_nonblock(VALUE _, VALUE v_fd) {
|
77
|
+
int fd = FIX2INT(v_fd);
|
78
|
+
set_nonblock(fd);
|
79
|
+
return Qnil;
|
80
|
+
}
|
81
|
+
|
82
|
+
void Init_event(VALUE ext) {
|
83
|
+
// rb_define_singleton_method(c, "add", add_q, 2);
|
84
|
+
rb_define_singleton_method(ext, "init_queue", ext_init_queue, 0);
|
85
|
+
rb_define_singleton_method(ext, "run_queue", ext_run_queue, 1);
|
86
|
+
|
87
|
+
// for test
|
88
|
+
rb_define_singleton_method(ext, "set_nonblock", ext_set_nonblock, 1);
|
89
|
+
}
|
data/ext/extconf.rb
ADDED
@@ -0,0 +1,34 @@
|
|
1
|
+
require "mkmf"
|
2
|
+
|
3
|
+
def tweak_include
|
4
|
+
dir = File.dirname __FILE__
|
5
|
+
multipart_dir = File.join dir, "multipart-parser-c"
|
6
|
+
http_parser_dir = File.join dir, "http-parser"
|
7
|
+
flags = " -I#{multipart_dir.shellescape} -I#{http_parser_dir.shellescape}"
|
8
|
+
$CFLAGS << flags
|
9
|
+
$CPPFLAGS << flags
|
10
|
+
end
|
11
|
+
|
12
|
+
def tweak_cflags
|
13
|
+
mf_conf = RbConfig::MAKEFILE_CONFIG
|
14
|
+
if mf_conf['CC'] =~ /clang/
|
15
|
+
# enable c++11. this can not be installed on $CPPFLAGS, wtf??
|
16
|
+
mf_conf['CXXFLAGS'] << ' -stdlib=libc++ -std=c++11'
|
17
|
+
$CFLAGS << ' $(xflags)'
|
18
|
+
else
|
19
|
+
mf_conf['CXXFLAGS'] << ' -std=c++11'
|
20
|
+
$CFLAGS << ' -std=c99 -Wno-declaration-after-statement $(xflags)'
|
21
|
+
end
|
22
|
+
|
23
|
+
$CPPFLAGS << ' $(xflags)'
|
24
|
+
puts "To enable debug: make xflags='-DDEBUG -O0'"
|
25
|
+
end
|
26
|
+
|
27
|
+
have_kqueue = (have_header("sys/event.h") and have_header("sys/queue.h"))
|
28
|
+
have_epoll = have_func('epoll_create', 'sys/epoll.h')
|
29
|
+
abort('no kqueue nor epoll') if !have_kqueue and !have_epoll
|
30
|
+
$defs << "-DNDEBUG -D#{have_epoll ? 'HAVE_EPOLL' : 'HAVE_KQUEUE'}"
|
31
|
+
|
32
|
+
tweak_include
|
33
|
+
tweak_cflags
|
34
|
+
create_makefile 'nyara'
|
data/ext/hashes.c
ADDED
@@ -0,0 +1,130 @@
|
|
1
|
+
// provide handy hash variants
|
2
|
+
#include "nyara.h"
|
3
|
+
#include <ruby/st.h>
|
4
|
+
|
5
|
+
VALUE nyara_param_hash_class;
|
6
|
+
VALUE nyara_header_hash_class;
|
7
|
+
VALUE nyara_config_hash_class;
|
8
|
+
|
9
|
+
// stolen from hash.c
|
10
|
+
int nyara_rb_hash_has_key(VALUE hash, VALUE key) {
|
11
|
+
if (!RHASH(hash)->ntbl)
|
12
|
+
return 0;
|
13
|
+
if (st_lookup(RHASH(hash)->ntbl, key, 0))
|
14
|
+
return 1;
|
15
|
+
return 0;
|
16
|
+
}
|
17
|
+
|
18
|
+
// NOTE no need to add lots of methods like HashWithIndifferentAccess
|
19
|
+
// just return simple hash like rack
|
20
|
+
|
21
|
+
static VALUE param_hash_aref(VALUE self, VALUE key) {
|
22
|
+
if (TYPE(key) == T_SYMBOL) {
|
23
|
+
key = rb_sym_to_s(key);
|
24
|
+
}
|
25
|
+
return rb_hash_aref(self, key);
|
26
|
+
}
|
27
|
+
|
28
|
+
static VALUE param_hash_key_p(VALUE self, VALUE key) {
|
29
|
+
if (TYPE(key) == T_SYMBOL) {
|
30
|
+
key = rb_sym_to_s(key);
|
31
|
+
}
|
32
|
+
return nyara_rb_hash_has_key(self, key) ? Qtrue : Qfalse;
|
33
|
+
}
|
34
|
+
|
35
|
+
static VALUE param_hash_aset(VALUE self, VALUE key, VALUE value) {
|
36
|
+
if (TYPE(key) == T_SYMBOL) {
|
37
|
+
key = rb_sym_to_s(key);
|
38
|
+
}
|
39
|
+
return rb_hash_aset(self, key, value);
|
40
|
+
}
|
41
|
+
|
42
|
+
void nyara_headerlize(VALUE str) {
|
43
|
+
char* s = (char*)RSTRING_PTR(str);
|
44
|
+
long len = RSTRING_LEN(str);
|
45
|
+
int border = 1;
|
46
|
+
for (long i = 0; i < len; i++) {
|
47
|
+
if (s[i] == '-') {
|
48
|
+
border = 1;
|
49
|
+
continue;
|
50
|
+
}
|
51
|
+
if (border) {
|
52
|
+
// note this is most reliable way,
|
53
|
+
// with <ctype.h> we have to deal with locale...
|
54
|
+
if (s[i] >= 'a' && s[i] <= 'z') {
|
55
|
+
s[i] = 'A' + (s[i] - 'a');
|
56
|
+
}
|
57
|
+
border = 0;
|
58
|
+
} else {
|
59
|
+
if (s[i] >= 'A' && s[i] <= 'Z') {
|
60
|
+
s[i] = 'a' + (s[i] - 'A');
|
61
|
+
}
|
62
|
+
}
|
63
|
+
}
|
64
|
+
}
|
65
|
+
|
66
|
+
static VALUE header_hash_tidy_key(VALUE key) {
|
67
|
+
if (TYPE(key) == T_SYMBOL) {
|
68
|
+
key = rb_sym_to_s(key);
|
69
|
+
}
|
70
|
+
Check_Type(key, T_STRING);
|
71
|
+
key = rb_str_new(RSTRING_PTR(key), RSTRING_LEN(key));
|
72
|
+
nyara_headerlize(key);
|
73
|
+
return key;
|
74
|
+
}
|
75
|
+
|
76
|
+
static VALUE header_hash_aref(VALUE self, VALUE key) {
|
77
|
+
return rb_hash_aref(self, header_hash_tidy_key(key));
|
78
|
+
}
|
79
|
+
|
80
|
+
static VALUE header_hash_key_p(VALUE self, VALUE key) {
|
81
|
+
return nyara_rb_hash_has_key(self, header_hash_tidy_key(key)) ? Qtrue : Qfalse;
|
82
|
+
}
|
83
|
+
|
84
|
+
ID id_to_s;
|
85
|
+
static VALUE header_hash_aset(VALUE self, VALUE key, VALUE value) {
|
86
|
+
key = header_hash_tidy_key(key);
|
87
|
+
if (TYPE(value) != T_STRING) {
|
88
|
+
value = rb_funcall(value, id_to_s, 0);
|
89
|
+
}
|
90
|
+
|
91
|
+
return rb_hash_aset(self, key, value);
|
92
|
+
}
|
93
|
+
|
94
|
+
int header_hash_merge_func(VALUE k, VALUE v, VALUE self_st) {
|
95
|
+
st_table* t = (st_table*)self_st;
|
96
|
+
if (!st_is_member(t, k)) {
|
97
|
+
st_insert(t, (st_data_t)k, (st_data_t)v);
|
98
|
+
}
|
99
|
+
return ST_CONTINUE;
|
100
|
+
}
|
101
|
+
|
102
|
+
static VALUE header_hash_reverse_merge_bang(VALUE self, VALUE other) {
|
103
|
+
if (!rb_obj_is_kind_of(other, nyara_header_hash_class)) {
|
104
|
+
rb_raise(rb_eArgError, "need a Nyara::HeaderHash");
|
105
|
+
}
|
106
|
+
st_table* t = rb_hash_tbl(self);
|
107
|
+
rb_hash_foreach(other, header_hash_merge_func, (VALUE)t);
|
108
|
+
return self;
|
109
|
+
}
|
110
|
+
|
111
|
+
void Init_hashes(VALUE nyara) {
|
112
|
+
id_to_s = rb_intern("to_s");
|
113
|
+
|
114
|
+
nyara_param_hash_class = rb_define_class_under(nyara, "ParamHash", rb_cHash);
|
115
|
+
nyara_header_hash_class = rb_define_class_under(nyara, "HeaderHash", nyara_param_hash_class);
|
116
|
+
nyara_config_hash_class = rb_define_class_under(nyara, "ConfigHash", nyara_param_hash_class);
|
117
|
+
|
118
|
+
rb_define_method(nyara_param_hash_class, "[]", param_hash_aref, 1);
|
119
|
+
rb_define_method(nyara_param_hash_class, "key?", param_hash_key_p, 1);
|
120
|
+
rb_define_method(nyara_param_hash_class, "[]=", param_hash_aset, 2);
|
121
|
+
|
122
|
+
rb_define_method(nyara_header_hash_class, "[]", header_hash_aref, 1);
|
123
|
+
rb_define_method(nyara_header_hash_class, "key?", header_hash_key_p, 1);
|
124
|
+
rb_define_method(nyara_header_hash_class, "[]=", header_hash_aset, 2);
|
125
|
+
rb_define_method(nyara_header_hash_class, "reverse_merge!", header_hash_reverse_merge_bang, 1);
|
126
|
+
|
127
|
+
// for internal use
|
128
|
+
rb_define_method(nyara_header_hash_class, "_aset", rb_hash_aset, 2);
|
129
|
+
rb_define_method(nyara_header_hash_class, "_aref", rb_hash_aref, 1);
|
130
|
+
}
|
@@ -0,0 +1,41 @@
|
|
1
|
+
# Authors ordered by first contribution.
|
2
|
+
Ryan Dahl <ry@tinyclouds.org>
|
3
|
+
Jeremy Hinegardner <jeremy@hinegardner.org>
|
4
|
+
Sergey Shepelev <temotor@gmail.com>
|
5
|
+
Joe Damato <ice799@gmail.com>
|
6
|
+
tomika <tomika_nospam@freemail.hu>
|
7
|
+
Phoenix Sol <phoenix@burninglabs.com>
|
8
|
+
Cliff Frey <cliff@meraki.com>
|
9
|
+
Ewen Cheslack-Postava <ewencp@cs.stanford.edu>
|
10
|
+
Santiago Gala <sgala@apache.org>
|
11
|
+
Tim Becker <tim.becker@syngenio.de>
|
12
|
+
Jeff Terrace <jterrace@gmail.com>
|
13
|
+
Ben Noordhuis <info@bnoordhuis.nl>
|
14
|
+
Nathan Rajlich <nathan@tootallnate.net>
|
15
|
+
Mark Nottingham <mnot@mnot.net>
|
16
|
+
Aman Gupta <aman@tmm1.net>
|
17
|
+
Tim Becker <tim.becker@kuriositaet.de>
|
18
|
+
Sean Cunningham <sean.cunningham@mandiant.com>
|
19
|
+
Peter Griess <pg@std.in>
|
20
|
+
Salman Haq <salman.haq@asti-usa.com>
|
21
|
+
Cliff Frey <clifffrey@gmail.com>
|
22
|
+
Jon Kolb <jon@b0g.us>
|
23
|
+
Fouad Mardini <f.mardini@gmail.com>
|
24
|
+
Paul Querna <pquerna@apache.org>
|
25
|
+
Felix Geisendörfer <felix@debuggable.com>
|
26
|
+
koichik <koichik@improvement.jp>
|
27
|
+
Andre Caron <andre.l.caron@gmail.com>
|
28
|
+
Ivo Raisr <ivosh@ivosh.net>
|
29
|
+
James McLaughlin <jamie@lacewing-project.org>
|
30
|
+
David Gwynne <loki@animata.net>
|
31
|
+
Thomas LE ROUX <thomas@november-eleven.fr>
|
32
|
+
Randy Rizun <rrizun@ortivawireless.com>
|
33
|
+
Andre Louis Caron <andre.louis.caron@usherbrooke.ca>
|
34
|
+
Simon Zimmermann <simonz05@gmail.com>
|
35
|
+
Erik Dubbelboer <erik@dubbelboer.com>
|
36
|
+
Martell Malone <martellmalone@gmail.com>
|
37
|
+
Bertrand Paquet <bpaquet@octo.com>
|
38
|
+
BogDan Vatra <bogdan@kde.org>
|
39
|
+
Peter Faiman <peter@thepicard.org>
|
40
|
+
Corey Richardson <corey@octayn.net>
|
41
|
+
Tóth Tamás <tomika_nospam@freemail.hu>
|
@@ -0,0 +1,23 @@
|
|
1
|
+
http_parser.c is based on src/http/ngx_http_parse.c from NGINX copyright
|
2
|
+
Igor Sysoev.
|
3
|
+
|
4
|
+
Additional changes are licensed under the same terms as NGINX and
|
5
|
+
copyright Joyent, Inc. and other Node contributors. All rights reserved.
|
6
|
+
|
7
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
8
|
+
of this software and associated documentation files (the "Software"), to
|
9
|
+
deal in the Software without restriction, including without limitation the
|
10
|
+
rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
|
11
|
+
sell copies of the Software, and to permit persons to whom the Software is
|
12
|
+
furnished to do so, subject to the following conditions:
|
13
|
+
|
14
|
+
The above copyright notice and this permission notice shall be included in
|
15
|
+
all copies or substantial portions of the Software.
|
16
|
+
|
17
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
18
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
19
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
20
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
21
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
22
|
+
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
|
23
|
+
IN THE SOFTWARE.
|