nyara 0.0.1.pre

Sign up to get free protection for your applications and to get access to all the features.
Files changed (67) hide show
  1. checksums.yaml +7 -0
  2. data/example/design.rb +62 -0
  3. data/example/fib.rb +15 -0
  4. data/example/hello.rb +5 -0
  5. data/example/stream.rb +10 -0
  6. data/ext/accept.c +133 -0
  7. data/ext/event.c +89 -0
  8. data/ext/extconf.rb +34 -0
  9. data/ext/hashes.c +130 -0
  10. data/ext/http-parser/AUTHORS +41 -0
  11. data/ext/http-parser/CONTRIBUTIONS +4 -0
  12. data/ext/http-parser/LICENSE-MIT +23 -0
  13. data/ext/http-parser/contrib/parsertrace.c +156 -0
  14. data/ext/http-parser/contrib/url_parser.c +44 -0
  15. data/ext/http-parser/http_parser.c +2175 -0
  16. data/ext/http-parser/http_parser.h +304 -0
  17. data/ext/http-parser/test.c +3425 -0
  18. data/ext/http_parser.c +1 -0
  19. data/ext/inc/epoll.h +60 -0
  20. data/ext/inc/kqueue.h +77 -0
  21. data/ext/inc/status_codes.inc +64 -0
  22. data/ext/inc/str_intern.h +66 -0
  23. data/ext/inc/version.inc +1 -0
  24. data/ext/mime.c +107 -0
  25. data/ext/multipart-parser-c/README.md +18 -0
  26. data/ext/multipart-parser-c/multipart_parser.c +309 -0
  27. data/ext/multipart-parser-c/multipart_parser.h +48 -0
  28. data/ext/multipart_parser.c +1 -0
  29. data/ext/nyara.c +56 -0
  30. data/ext/nyara.h +59 -0
  31. data/ext/request.c +474 -0
  32. data/ext/route.cc +325 -0
  33. data/ext/url_encoded.c +304 -0
  34. data/hello.rb +5 -0
  35. data/lib/nyara/config.rb +64 -0
  36. data/lib/nyara/config_hash.rb +51 -0
  37. data/lib/nyara/controller.rb +336 -0
  38. data/lib/nyara/cookie.rb +31 -0
  39. data/lib/nyara/cpu_counter.rb +65 -0
  40. data/lib/nyara/header_hash.rb +18 -0
  41. data/lib/nyara/mime_types.rb +612 -0
  42. data/lib/nyara/nyara.rb +82 -0
  43. data/lib/nyara/param_hash.rb +5 -0
  44. data/lib/nyara/request.rb +144 -0
  45. data/lib/nyara/route.rb +138 -0
  46. data/lib/nyara/route_entry.rb +43 -0
  47. data/lib/nyara/session.rb +104 -0
  48. data/lib/nyara/view.rb +317 -0
  49. data/lib/nyara.rb +25 -0
  50. data/nyara.gemspec +20 -0
  51. data/rakefile +91 -0
  52. data/readme.md +35 -0
  53. data/spec/ext_mime_match_spec.rb +27 -0
  54. data/spec/ext_parse_accept_value_spec.rb +29 -0
  55. data/spec/ext_parse_spec.rb +138 -0
  56. data/spec/ext_route_spec.rb +70 -0
  57. data/spec/hashes_spec.rb +71 -0
  58. data/spec/path_helper_spec.rb +77 -0
  59. data/spec/request_delegate_spec.rb +67 -0
  60. data/spec/request_spec.rb +56 -0
  61. data/spec/route_entry_spec.rb +12 -0
  62. data/spec/route_spec.rb +84 -0
  63. data/spec/session_spec.rb +66 -0
  64. data/spec/spec_helper.rb +52 -0
  65. data/spec/view_spec.rb +87 -0
  66. data/tools/bench-cookie.rb +22 -0
  67. 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
@@ -0,0 +1,15 @@
1
+ require "nyara"
2
+
3
+ configure do
4
+ port 3000
5
+ end
6
+
7
+ def fib i
8
+ a, b = 0, 1
9
+ i.times { a, b = b, a + b }
10
+ a
11
+ end
12
+
13
+ get '/fib/%d' do |i|
14
+ send_string "fib(#{i}) = #{fib i}\n"
15
+ end
data/example/hello.rb ADDED
@@ -0,0 +1,5 @@
1
+ require "nyara"
2
+
3
+ get '/' do
4
+ send_string 'hello world'
5
+ end
data/example/stream.rb ADDED
@@ -0,0 +1,10 @@
1
+ require "nyara"
2
+ require "slim"
3
+
4
+ get '/' do
5
+ view = stream 'index'
6
+ 4.times do
7
+ sleep 1
8
+ view.resume
9
+ end
10
+ end
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,4 @@
1
+ Contributors must agree to the Contributor License Agreement before patches
2
+ can be accepted.
3
+
4
+ http://spreadsheets2.google.com/viewform?hl=en&formkey=dDJXOGUwbzlYaWM4cHN1MERwQS1CSnc6MQ
@@ -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.