agoo 2.12.1 → 2.14.1
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/CHANGELOG.md +42 -0
- data/README.md +26 -2
- data/bin/agoo_stubs +166 -0
- data/ext/agoo/bind.c +5 -5
- data/ext/agoo/con.c +18 -1
- data/ext/agoo/con.h +2 -0
- data/ext/agoo/gqleval.c +3 -3
- data/ext/agoo/gqljson.c +1 -0
- data/ext/agoo/http.c +20 -35
- data/ext/agoo/req.c +9 -10
- data/ext/agoo/req.h +2 -0
- data/ext/agoo/request.c +53 -4
- data/ext/agoo/rgraphql.c +89 -7
- data/ext/agoo/rserver.c +48 -4
- data/ext/agoo/rserver.h +8 -0
- data/ext/agoo/server.c +2 -2
- data/ext/agoo/websocket.c +1 -0
- data/lib/agoo.rb +1 -0
- data/lib/agoo/graphql.rb +9 -0
- data/lib/agoo/graphql/arg.rb +13 -0
- data/lib/agoo/graphql/field.rb +14 -0
- data/lib/agoo/graphql/type.rb +12 -0
- data/lib/agoo/version.rb +1 -1
- data/test/base_handler_test.rb +4 -4
- data/test/graphql_test.rb +36 -6
- data/test/rack_handler_test.rb +1 -0
- metadata +17 -11
data/ext/agoo/req.c
CHANGED
@@ -14,7 +14,7 @@ agooReq
|
|
14
14
|
agoo_req_create(size_t mlen) {
|
15
15
|
size_t size = mlen + sizeof(struct _agooReq) - 7;
|
16
16
|
agooReq req = (agooReq)AGOO_MALLOC(size);
|
17
|
-
|
17
|
+
|
18
18
|
if (NULL != req) {
|
19
19
|
memset(req, 0, size);
|
20
20
|
req->env = agoo_server.env_nil_value;
|
@@ -56,7 +56,7 @@ agoo_req_port(agooReq r) {
|
|
56
56
|
int len;
|
57
57
|
const char *host;
|
58
58
|
const char *colon;
|
59
|
-
|
59
|
+
|
60
60
|
if (NULL == (host = agoo_con_header_value(r->header.start, r->header.len, "Host", &len))) {
|
61
61
|
return 0;
|
62
62
|
}
|
@@ -94,7 +94,7 @@ agoo_req_query_value(agooReq r, const char *key, int klen, int *vlenp) {
|
|
94
94
|
static int
|
95
95
|
hexVal(int c) {
|
96
96
|
int h = -1;
|
97
|
-
|
97
|
+
|
98
98
|
if ('0' <= c && c <= '9') {
|
99
99
|
h = c - '0';
|
100
100
|
} else if ('a' <= c && c <= 'f') {
|
@@ -110,12 +110,12 @@ agoo_req_query_decode(char *s, int len) {
|
|
110
110
|
char *sn = s;
|
111
111
|
char *so = s;
|
112
112
|
char *end = s + len;
|
113
|
-
|
113
|
+
|
114
114
|
while (so < end) {
|
115
115
|
if ('%' == *so) {
|
116
116
|
int n;
|
117
117
|
int c = 0;
|
118
|
-
|
118
|
+
|
119
119
|
so++;
|
120
120
|
if (0 > (c = hexVal(*so))) {
|
121
121
|
*sn++ = '%';
|
@@ -133,7 +133,7 @@ agoo_req_query_decode(char *s, int len) {
|
|
133
133
|
}
|
134
134
|
}
|
135
135
|
*sn = '\0';
|
136
|
-
|
136
|
+
|
137
137
|
return (int)(sn - s);
|
138
138
|
}
|
139
139
|
|
@@ -145,9 +145,9 @@ agoo_req_header_value(agooReq req, const char *key, int *vlen) {
|
|
145
145
|
const char *hend = h + req->header.len;
|
146
146
|
const char *value;
|
147
147
|
int klen = (int)strlen(key);
|
148
|
-
|
148
|
+
|
149
149
|
while (h < hend) {
|
150
|
-
if (0 ==
|
150
|
+
if (0 == strncasecmp(key, h, klen) && ':' == h[klen]) {
|
151
151
|
h += klen + 1;
|
152
152
|
for (; ' ' == *h; h++) {
|
153
153
|
}
|
@@ -155,7 +155,7 @@ agoo_req_header_value(agooReq req, const char *key, int *vlen) {
|
|
155
155
|
for (; '\r' != *h && '\0' != *h; h++) {
|
156
156
|
}
|
157
157
|
*vlen = (int)(h - value);
|
158
|
-
|
158
|
+
|
159
159
|
return value;
|
160
160
|
}
|
161
161
|
for (; h < hend; h++) {
|
@@ -167,4 +167,3 @@ agoo_req_header_value(agooReq req, const char *key, int *vlen) {
|
|
167
167
|
}
|
168
168
|
return NULL;
|
169
169
|
}
|
170
|
-
|
data/ext/agoo/req.h
CHANGED
@@ -3,6 +3,7 @@
|
|
3
3
|
#ifndef AGOO_REQ_H
|
4
4
|
#define AGOO_REQ_H
|
5
5
|
|
6
|
+
#include <arpa/inet.h>
|
6
7
|
#include <stdint.h>
|
7
8
|
|
8
9
|
#include "hook.h"
|
@@ -32,6 +33,7 @@ typedef struct _agooReq {
|
|
32
33
|
struct _agooStr query;
|
33
34
|
struct _agooStr header;
|
34
35
|
struct _agooStr body;
|
36
|
+
char remote[INET6_ADDRSTRLEN];
|
35
37
|
void *env;
|
36
38
|
agooHook hook;
|
37
39
|
size_t mlen; // allocated msg length
|
data/ext/agoo/request.c
CHANGED
@@ -43,6 +43,7 @@ static VALUE rack_upgrade_val = Qundef;
|
|
43
43
|
static VALUE rack_url_scheme_val = Qundef;
|
44
44
|
static VALUE rack_version_val = Qundef;
|
45
45
|
static VALUE rack_version_val_val = Qundef;
|
46
|
+
static VALUE remote_addr_val = Qundef;
|
46
47
|
static VALUE request_method_val = Qundef;
|
47
48
|
static VALUE script_name_val = Qundef;
|
48
49
|
static VALUE server_name_val = Qundef;
|
@@ -96,6 +97,27 @@ method(VALUE self) {
|
|
96
97
|
return req_method((agooReq)DATA_PTR(self));
|
97
98
|
}
|
98
99
|
|
100
|
+
static VALUE
|
101
|
+
req_remote_addr(agooReq r) {
|
102
|
+
|
103
|
+
if (NULL == r) {
|
104
|
+
rb_raise(rb_eArgError, "Request is no longer valid.");
|
105
|
+
}
|
106
|
+
return rb_str_new(r->remote, strlen(r->remote));
|
107
|
+
}
|
108
|
+
|
109
|
+
/* Document-method: remote_addr
|
110
|
+
*
|
111
|
+
* call-seq: remote_addr()
|
112
|
+
*
|
113
|
+
* Returns the remote address.
|
114
|
+
*/
|
115
|
+
static VALUE
|
116
|
+
remote_addr(VALUE self) {
|
117
|
+
return req_remote_addr((agooReq)DATA_PTR(self));
|
118
|
+
}
|
119
|
+
|
120
|
+
|
99
121
|
static VALUE
|
100
122
|
req_script_name(agooReq r) {
|
101
123
|
// The logic is a bit tricky here and for path_info. If the HTTP path is /
|
@@ -366,14 +388,29 @@ rack_run_once(VALUE self) {
|
|
366
388
|
|
367
389
|
static void
|
368
390
|
add_header_value(VALUE hh, const char *key, int klen, const char *val, int vlen) {
|
391
|
+
VALUE v;
|
392
|
+
|
369
393
|
if (sizeof(content_type) - 1 == klen && 0 == strncasecmp(key, content_type, sizeof(content_type) - 1)) {
|
370
|
-
|
394
|
+
if (Qnil == (v = rb_hash_lookup2(hh, content_type_val, Qnil))) {
|
395
|
+
rb_hash_aset(hh, content_type_val, rb_str_new(val, vlen));
|
396
|
+
} else {
|
397
|
+
volatile VALUE a = rb_ary_new();
|
398
|
+
|
399
|
+
rb_ary_push(a, v);
|
400
|
+
rb_ary_push(a, rb_str_new(val, vlen));
|
401
|
+
rb_hash_aset(hh, content_type_val, a);
|
402
|
+
}
|
371
403
|
} else if (sizeof(content_length) - 1 == klen && 0 == strncasecmp(key, content_length, sizeof(content_length) - 1)) {
|
372
|
-
|
404
|
+
if (Qnil == (v = rb_hash_lookup2(hh, content_length_val, Qnil))) {
|
405
|
+
rb_hash_aset(hh, content_length_val, rb_str_new(val, vlen));
|
406
|
+
} else {
|
407
|
+
rb_raise(rb_eArgError, "Multiple Content-Length headers.");
|
408
|
+
}
|
373
409
|
} else {
|
374
410
|
char hkey[1024];
|
375
411
|
char *k = hkey;
|
376
412
|
volatile VALUE sval = rb_str_new(val, vlen);
|
413
|
+
volatile VALUE kval;
|
377
414
|
|
378
415
|
strcpy(hkey, "HTTP_");
|
379
416
|
k = hkey + 5;
|
@@ -392,7 +429,16 @@ add_header_value(VALUE hh, const char *key, int klen, const char *val, int vlen)
|
|
392
429
|
*k = toupper(*k);
|
393
430
|
}
|
394
431
|
}
|
395
|
-
|
432
|
+
kval = rb_str_new(hkey, klen + 5);
|
433
|
+
if (Qnil == (v = rb_hash_lookup2(hh, kval, Qnil))) {
|
434
|
+
rb_hash_aset(hh, kval, sval);
|
435
|
+
} else {
|
436
|
+
volatile VALUE a = rb_ary_new();
|
437
|
+
|
438
|
+
rb_ary_push(a, v);
|
439
|
+
rb_ary_push(a, sval);
|
440
|
+
rb_hash_aset(hh, kval, a);
|
441
|
+
}
|
396
442
|
}
|
397
443
|
}
|
398
444
|
|
@@ -545,8 +591,9 @@ request_env(agooReq req, VALUE self) {
|
|
545
591
|
rb_hash_aset(env, script_name_val, req_script_name(req));
|
546
592
|
rb_hash_aset(env, path_info_val, req_path_info(req));
|
547
593
|
rb_hash_aset(env, query_string_val, req_query_string(req));
|
548
|
-
rb_hash_aset(env,
|
594
|
+
rb_hash_aset(env, remote_addr_val, req_remote_addr(req));
|
549
595
|
rb_hash_aset(env, server_port_val, req_server_port(req));
|
596
|
+
rb_hash_aset(env, server_name_val, req_server_name(req));
|
550
597
|
fill_headers(req, env);
|
551
598
|
rb_hash_aset(env, rack_version_val, rack_version_val_val);
|
552
599
|
rb_hash_aset(env, rack_url_scheme_val, req_rack_url_scheme(req));
|
@@ -663,6 +710,7 @@ request_init(VALUE mod) {
|
|
663
710
|
rb_define_method(req_class, "query_string", query_string, 0);
|
664
711
|
rb_define_method(req_class, "server_name", server_name, 0);
|
665
712
|
rb_define_method(req_class, "server_port", server_port, 0);
|
713
|
+
rb_define_method(req_class, "remote_addr", remote_addr, 0);
|
666
714
|
rb_define_method(req_class, "rack_version", rack_version, 0);
|
667
715
|
rb_define_method(req_class, "rack_url_scheme", rack_url_scheme, 0);
|
668
716
|
rb_define_method(req_class, "rack_input", rack_input, 0);
|
@@ -713,6 +761,7 @@ request_init(VALUE mod) {
|
|
713
761
|
rack_upgrade_val = rb_str_new_cstr("rack.upgrade?"); rb_gc_register_address(&rack_upgrade_val);
|
714
762
|
rack_url_scheme_val = rb_str_new_cstr("rack.url_scheme"); rb_gc_register_address(&rack_url_scheme_val);
|
715
763
|
rack_version_val = rb_str_new_cstr("rack.version"); rb_gc_register_address(&rack_version_val);
|
764
|
+
remote_addr_val = rb_str_new_cstr("REMOTE_ADDR"); rb_gc_register_address(&remote_addr_val);
|
716
765
|
request_method_val = rb_str_new_cstr("REQUEST_METHOD"); rb_gc_register_address(&request_method_val);
|
717
766
|
script_name_val = rb_str_new_cstr("SCRIPT_NAME"); rb_gc_register_address(&script_name_val);
|
718
767
|
server_name_val = rb_str_new_cstr("SERVER_NAME"); rb_gc_register_address(&server_name_val);
|
data/ext/agoo/rgraphql.c
CHANGED
@@ -37,6 +37,9 @@ typedef struct _bhArgs {
|
|
37
37
|
static VALUE graphql_class = Qundef;
|
38
38
|
static VALUE vroot = Qnil;
|
39
39
|
static VALUE build_headers_func = Qnil;
|
40
|
+
static VALUE arg_clas = Qnil;
|
41
|
+
static VALUE field_clas = Qnil;
|
42
|
+
static VALUE type_clas = Qnil;
|
40
43
|
|
41
44
|
static ID call_id;
|
42
45
|
|
@@ -101,7 +104,7 @@ call_eval(VALUE x) {
|
|
101
104
|
|
102
105
|
static void*
|
103
106
|
protect_eval(void *x) {
|
104
|
-
rb_rescue2(call_eval, (VALUE)x, rescue_error, (VALUE)x, rb_eException, 0);
|
107
|
+
rb_rescue2(call_eval, (VALUE)x, rescue_error, (VALUE)x, rb_eException, (VALUE)0);
|
105
108
|
|
106
109
|
return NULL;
|
107
110
|
}
|
@@ -679,7 +682,7 @@ graphql_schema(VALUE self, VALUE root) {
|
|
679
682
|
printf("*-*-* %s\n", err.msg);
|
680
683
|
exit(6);
|
681
684
|
}
|
682
|
-
rb_rescue2(rescue_yield, Qnil, rescue_yield_error, (VALUE)&err, rb_eException, 0);
|
685
|
+
rb_rescue2(rescue_yield, Qnil, rescue_yield_error, (VALUE)&err, rb_eException, (VALUE)0);
|
683
686
|
if (AGOO_ERR_OK != err.code) {
|
684
687
|
printf("*-*-* %s\n", err.msg);
|
685
688
|
exit(7);
|
@@ -774,16 +777,16 @@ graphql_load_file(VALUE self, VALUE path) {
|
|
774
777
|
return Qnil;
|
775
778
|
}
|
776
779
|
|
777
|
-
/* Document-method:
|
780
|
+
/* Document-method: sdl_dump
|
778
781
|
*
|
779
|
-
* call-seq:
|
782
|
+
* call-seq: sdl_dump()
|
780
783
|
*
|
781
784
|
* The preferred method of inspecting a GraphQL schema is to use introspection
|
782
785
|
* queries but for debugging and for reviewing the schema a dump of the schema
|
783
|
-
* as SDL can be helpful. The _#
|
786
|
+
* as SDL can be helpful. The _#sdl_dump_ method returns the schema as an SDL
|
784
787
|
* string.
|
785
788
|
*
|
786
|
-
* - *options* [_Hash_]
|
789
|
+
* - *options* [_Hash_] options
|
787
790
|
*
|
788
791
|
* - *:with_description* [_true_|_false_] if true the description strings are included. If false they are not included.
|
789
792
|
*
|
@@ -817,6 +820,79 @@ graphql_sdl_dump(VALUE self, VALUE options) {
|
|
817
820
|
return dump;
|
818
821
|
}
|
819
822
|
|
823
|
+
static void
|
824
|
+
type_cb(gqlType type, void *ctx) {
|
825
|
+
VALUE rtypes = (VALUE)ctx;
|
826
|
+
VALUE t;
|
827
|
+
|
828
|
+
if (GQL_OBJECT != type->kind || type->core) {
|
829
|
+
return;
|
830
|
+
}
|
831
|
+
t = rb_obj_alloc(type_clas);
|
832
|
+
rb_ivar_set(t, rb_intern("@name"), rb_str_new_cstr(type->name));
|
833
|
+
if (NULL != type->desc) {
|
834
|
+
rb_ivar_set(t, rb_intern("@description"), rb_str_new_cstr(type->desc));
|
835
|
+
}
|
836
|
+
if (NULL != type->fields) {
|
837
|
+
VALUE fields = rb_ary_new();
|
838
|
+
VALUE field;
|
839
|
+
gqlField f;
|
840
|
+
|
841
|
+
rb_ivar_set(t, rb_intern("@fields"), fields);
|
842
|
+
for (f = type->fields; NULL != f; f = f->next) {
|
843
|
+
field = rb_obj_alloc(field_clas);
|
844
|
+
rb_ary_push(fields, field);
|
845
|
+
rb_ivar_set(field, rb_intern("@name"), rb_str_new_cstr(f->name));
|
846
|
+
if (NULL != f->desc) {
|
847
|
+
rb_ivar_set(field, rb_intern("@description"), rb_str_new_cstr(f->desc));
|
848
|
+
}
|
849
|
+
if (NULL != f->type) {
|
850
|
+
rb_ivar_set(field, rb_intern("@type_name"), rb_str_new_cstr(f->type->name));
|
851
|
+
}
|
852
|
+
if (NULL != f->default_value) {
|
853
|
+
rb_ivar_set(field, rb_intern("@default_value"), gval_to_ruby(f->default_value));
|
854
|
+
}
|
855
|
+
if (NULL != f->args) {
|
856
|
+
VALUE args = rb_ary_new();
|
857
|
+
VALUE arg;
|
858
|
+
gqlArg a;
|
859
|
+
|
860
|
+
rb_ivar_set(field, rb_intern("@args"), args);
|
861
|
+
for (a = f->args; NULL != a; a = a->next) {
|
862
|
+
arg = rb_obj_alloc(arg_clas);
|
863
|
+
rb_ary_push(args, arg);
|
864
|
+
rb_ivar_set(arg, rb_intern("@name"), rb_str_new_cstr(a->name));
|
865
|
+
if (NULL != a->desc) {
|
866
|
+
rb_ivar_set(arg, rb_intern("@description"), rb_str_new_cstr(a->desc));
|
867
|
+
}
|
868
|
+
if (NULL != a->type) {
|
869
|
+
rb_ivar_set(arg, rb_intern("@type_name"), rb_str_new_cstr(a->type->name));
|
870
|
+
}
|
871
|
+
if (NULL != a->default_value) {
|
872
|
+
rb_ivar_set(arg, rb_intern("@default_value"), gval_to_ruby(a->default_value));
|
873
|
+
}
|
874
|
+
}
|
875
|
+
}
|
876
|
+
}
|
877
|
+
}
|
878
|
+
rb_ary_push(rtypes, t);
|
879
|
+
}
|
880
|
+
|
881
|
+
/* Document-method: sdl_types
|
882
|
+
*
|
883
|
+
* call-seq: sdl_types()
|
884
|
+
*
|
885
|
+
* Returns an array of all SDL types as Ruby objects.
|
886
|
+
*/
|
887
|
+
static VALUE
|
888
|
+
graphql_sdl_types(VALUE self) {
|
889
|
+
VALUE rtypes = rb_ary_new();
|
890
|
+
|
891
|
+
gql_type_iterate(type_cb, (void*)rtypes);
|
892
|
+
|
893
|
+
return rtypes;
|
894
|
+
}
|
895
|
+
|
820
896
|
/* Document-method: publish
|
821
897
|
*
|
822
898
|
* call-seq: publish(subject, event)
|
@@ -876,7 +952,7 @@ inner_build_headers(VALUE x) {
|
|
876
952
|
|
877
953
|
static void*
|
878
954
|
protected_build_headers(void *x) {
|
879
|
-
return (void*)rb_rescue2(inner_build_headers, (VALUE)x, rescue_build_header, (VALUE)x, rb_eException, 0);
|
955
|
+
return (void*)rb_rescue2(inner_build_headers, (VALUE)x, rescue_build_header, (VALUE)x, rb_eException, (VALUE)0);
|
880
956
|
}
|
881
957
|
|
882
958
|
static agooText
|
@@ -963,10 +1039,16 @@ graphql_init(VALUE mod) {
|
|
963
1039
|
|
964
1040
|
rb_define_module_function(graphql_class, "sdl_dump", graphql_sdl_dump, 1);
|
965
1041
|
|
1042
|
+
rb_define_module_function(graphql_class, "sdl_types", graphql_sdl_types, 0);
|
1043
|
+
|
966
1044
|
rb_define_module_function(graphql_class, "publish", graphql_publish, 2);
|
967
1045
|
|
968
1046
|
rb_define_module_function(graphql_class, "build_headers=", graphql_build_headers, 1);
|
969
1047
|
rb_define_module_function(graphql_class, "headers", graphql_headers, 1);
|
970
1048
|
|
1049
|
+
arg_clas = rb_const_get_at(graphql_class, rb_intern("Arg"));
|
1050
|
+
field_clas = rb_const_get_at(graphql_class, rb_intern("Field"));
|
1051
|
+
type_clas = rb_const_get_at(graphql_class, rb_intern("Type"));
|
1052
|
+
|
971
1053
|
call_id = rb_intern("call");
|
972
1054
|
}
|
data/ext/agoo/rserver.c
CHANGED
@@ -103,6 +103,7 @@ configure(agooErr err, int port, const char *root, VALUE options) {
|
|
103
103
|
}
|
104
104
|
agoo_server.thread_cnt = 0;
|
105
105
|
the_rserver.worker_cnt = 1;
|
106
|
+
the_rserver.uses = NULL;
|
106
107
|
atomic_init(&agoo_server.running, 0);
|
107
108
|
agoo_server.listen_thread = 0;
|
108
109
|
agoo_server.con_loops = NULL;
|
@@ -384,7 +385,7 @@ handle_base_inner(VALUE x) {
|
|
384
385
|
|
385
386
|
static void*
|
386
387
|
handle_base(void *x) {
|
387
|
-
rb_rescue2(handle_base_inner, (VALUE)x, rescue_error, (VALUE)x, rb_eException, 0);
|
388
|
+
rb_rescue2(handle_base_inner, (VALUE)x, rescue_error, (VALUE)x, rb_eException, (VALUE)0);
|
388
389
|
|
389
390
|
return NULL;
|
390
391
|
}
|
@@ -613,7 +614,7 @@ handle_rack_inner(VALUE x) {
|
|
613
614
|
static void*
|
614
615
|
handle_rack(void *x) {
|
615
616
|
//rb_gc_disable();
|
616
|
-
rb_rescue2(handle_rack_inner, (VALUE)x, rescue_error, (VALUE)x, rb_eException, 0);
|
617
|
+
rb_rescue2(handle_rack_inner, (VALUE)x, rescue_error, (VALUE)x, rb_eException, (VALUE)0);
|
617
618
|
//rb_gc_enable();
|
618
619
|
//rb_gc();
|
619
620
|
|
@@ -638,7 +639,7 @@ handle_wab_inner(VALUE x) {
|
|
638
639
|
|
639
640
|
static void*
|
640
641
|
handle_wab(void *x) {
|
641
|
-
rb_rescue2(handle_wab_inner, (VALUE)x, rescue_error, (VALUE)x, rb_eException, 0);
|
642
|
+
rb_rescue2(handle_wab_inner, (VALUE)x, rescue_error, (VALUE)x, rb_eException, (VALUE)0);
|
642
643
|
|
643
644
|
return NULL;
|
644
645
|
}
|
@@ -696,7 +697,7 @@ handle_push_inner(VALUE x) {
|
|
696
697
|
|
697
698
|
static void*
|
698
699
|
handle_push(void *x) {
|
699
|
-
rb_rescue2(handle_push_inner, (VALUE)x, rescue_error, (VALUE)x, rb_eException, 0);
|
700
|
+
rb_rescue2(handle_push_inner, (VALUE)x, rescue_error, (VALUE)x, rb_eException, (VALUE)0);
|
700
701
|
return NULL;
|
701
702
|
}
|
702
703
|
|
@@ -1014,6 +1015,14 @@ handle(VALUE self, VALUE method, VALUE pattern, VALUE handler) {
|
|
1014
1015
|
}
|
1015
1016
|
}
|
1016
1017
|
}
|
1018
|
+
if (NULL != the_rserver.uses) {
|
1019
|
+
RUse u;
|
1020
|
+
|
1021
|
+
for (u = the_rserver.uses; NULL != u; u = u->next) {
|
1022
|
+
u->argv[0] = handler;
|
1023
|
+
handler = rb_funcall2(u->clas, rb_intern("new"), u->argc, u->argv);
|
1024
|
+
}
|
1025
|
+
}
|
1017
1026
|
if (NULL == (hook = rhook_create(meth, pat, handler, &agoo_server.eval_queue))) {
|
1018
1027
|
rb_raise(rb_eStandardError, "out of memory.");
|
1019
1028
|
} else {
|
@@ -1195,6 +1204,40 @@ rack_early_hints(VALUE self, VALUE on) {
|
|
1195
1204
|
return on;
|
1196
1205
|
}
|
1197
1206
|
|
1207
|
+
/* Document-method: use
|
1208
|
+
*
|
1209
|
+
* call-seq: use(middleware, *args)
|
1210
|
+
*
|
1211
|
+
* The use function must be called before the _handle_ functions. Any
|
1212
|
+
* invocations of _use_ apply only to handlers called after the call to use.
|
1213
|
+
*/
|
1214
|
+
static VALUE
|
1215
|
+
use(int argc, VALUE *argv, VALUE self) {
|
1216
|
+
VALUE mc;
|
1217
|
+
RUse u;
|
1218
|
+
|
1219
|
+
if (argc < 1) { // at least the middleware class must be provided.
|
1220
|
+
rb_raise(rb_eArgError, "no middleware class provided");
|
1221
|
+
}
|
1222
|
+
mc = argv[0];
|
1223
|
+
if (T_CLASS != rb_type(mc)) {
|
1224
|
+
rb_raise(rb_eArgError, "the first argument to use must be a class");
|
1225
|
+
}
|
1226
|
+
if (NULL == (u = (RUse)AGOO_MALLOC(sizeof(struct _rUse)))) {
|
1227
|
+
rb_raise(rb_eNoMemError, "Failed to allocate memory for a middleware use.");
|
1228
|
+
}
|
1229
|
+
u->clas = mc;
|
1230
|
+
u->argc = argc;
|
1231
|
+
if (NULL == (u->argv = (VALUE*)AGOO_MALLOC(sizeof(VALUE) * u->argc))) {
|
1232
|
+
rb_raise(rb_eNoMemError, "Failed to allocate memory for a middleware use.");
|
1233
|
+
}
|
1234
|
+
memcpy(u->argv, argv, argc * sizeof(VALUE));
|
1235
|
+
u->next = the_rserver.uses;
|
1236
|
+
the_rserver.uses = u;
|
1237
|
+
|
1238
|
+
return Qnil;
|
1239
|
+
}
|
1240
|
+
|
1198
1241
|
/* Document-class: Agoo::Server
|
1199
1242
|
*
|
1200
1243
|
* An HTTP server that support the rack API as well as some other optimized
|
@@ -1214,6 +1257,7 @@ server_init(VALUE mod) {
|
|
1214
1257
|
rb_define_module_function(server_mod, "path_group", path_group, 2);
|
1215
1258
|
rb_define_module_function(server_mod, "header_rule", header_rule, 4);
|
1216
1259
|
rb_define_module_function(server_mod, "domain", domain, 2);
|
1260
|
+
rb_define_module_function(server_mod, "use", use, -1);
|
1217
1261
|
|
1218
1262
|
rb_define_module_function(server_mod, "rack_early_hints", rack_early_hints, 1);
|
1219
1263
|
|