nyara 0.0.1.pre
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 +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.
|