agoo 2.11.7 → 2.12.0
Sign up to get free protection for your applications and to get access to all the features.
Potentially problematic release.
This version of agoo might be problematic. Click here for more details.
- checksums.yaml +4 -4
- data/CHANGELOG.md +14 -0
- data/ext/agoo/gqleval.c +85 -21
- data/ext/agoo/gqleval.h +6 -0
- data/ext/agoo/gqlintro.c +175 -103
- data/ext/agoo/gqljson.c +3 -0
- data/ext/agoo/gqlvalue.c +5 -5
- data/ext/agoo/graphql.c +35 -24
- data/ext/agoo/graphql.h +11 -15
- data/ext/agoo/rgraphql.c +160 -6
- data/ext/agoo/rserver.c +4 -1
- data/ext/agoo/sdl.c +23 -26
- data/ext/agoo/sdl.h +1 -1
- data/lib/agoo/version.rb +1 -1
- data/test/graphql_test.rb +22 -18
- metadata +2 -2
data/ext/agoo/gqljson.c
CHANGED
@@ -424,6 +424,7 @@ parse_value(agooErr err, agooDoc doc) {
|
|
424
424
|
if (4 <= doc->end - doc->cur &&
|
425
425
|
'r' == doc->cur[1] && 'u' == doc->cur[2] && 'e' == doc->cur[3]) {
|
426
426
|
value = gql_bool_create(err, true);
|
427
|
+
doc->cur += 4;
|
427
428
|
} else {
|
428
429
|
agoo_doc_err(doc, err, "invalid token");
|
429
430
|
}
|
@@ -432,6 +433,7 @@ parse_value(agooErr err, agooDoc doc) {
|
|
432
433
|
if (5 <= doc->end - doc->cur &&
|
433
434
|
'a' == doc->cur[1] && 'l' == doc->cur[2] && 's' == doc->cur[3] && 'e' == doc->cur[4]) {
|
434
435
|
value = gql_bool_create(err, false);
|
436
|
+
doc->cur += 5;
|
435
437
|
} else {
|
436
438
|
agoo_doc_err(doc, err, "invalid token");
|
437
439
|
}
|
@@ -440,6 +442,7 @@ parse_value(agooErr err, agooDoc doc) {
|
|
440
442
|
if (4 <= doc->end - doc->cur &&
|
441
443
|
'u' == doc->cur[1] && 'l' == doc->cur[2] && 'l' == doc->cur[3]) {
|
442
444
|
value = gql_null_create(err);
|
445
|
+
doc->cur += 4;
|
443
446
|
} else {
|
444
447
|
agoo_doc_err(doc, err, "invalid token");
|
445
448
|
}
|
data/ext/agoo/gqlvalue.c
CHANGED
@@ -590,8 +590,7 @@ list_destroy(gqlValue value) {
|
|
590
590
|
|
591
591
|
while (NULL != (link = value->members)) {
|
592
592
|
value->members = link->next;
|
593
|
-
|
594
|
-
AGOO_FREE(link);
|
593
|
+
gql_link_destroy(link);
|
595
594
|
}
|
596
595
|
}
|
597
596
|
|
@@ -679,9 +678,7 @@ object_destroy(gqlValue value) {
|
|
679
678
|
|
680
679
|
while (NULL != (link = value->members)) {
|
681
680
|
value->members = link->next;
|
682
|
-
|
683
|
-
AGOO_FREE(link->key);
|
684
|
-
AGOO_FREE(link);
|
681
|
+
gql_link_destroy(link);
|
685
682
|
}
|
686
683
|
}
|
687
684
|
|
@@ -1572,6 +1569,9 @@ int
|
|
1572
1569
|
gql_value_convert(agooErr err, gqlValue value, gqlType type) {
|
1573
1570
|
int code = AGOO_ERR_OK;
|
1574
1571
|
|
1572
|
+
if (GQL_NON_NULL == type->kind) {
|
1573
|
+
type = type->base;
|
1574
|
+
}
|
1575
1575
|
if (type != value->type) {
|
1576
1576
|
switch (type->scalar_kind) {
|
1577
1577
|
case GQL_SCALAR_BOOL:
|
data/ext/agoo/graphql.c
CHANGED
@@ -517,8 +517,7 @@ gql_type_field(agooErr err,
|
|
517
517
|
gqlType return_type,
|
518
518
|
gqlValue default_value,
|
519
519
|
const char *desc,
|
520
|
-
size_t dlen
|
521
|
-
bool required) {
|
520
|
+
size_t dlen) {
|
522
521
|
gqlField f = (gqlField)AGOO_MALLOC(sizeof(struct _gqlField));
|
523
522
|
|
524
523
|
if (NULL == f) {
|
@@ -538,7 +537,6 @@ gql_type_field(agooErr err,
|
|
538
537
|
f->args = NULL;
|
539
538
|
f->dir = NULL;
|
540
539
|
f->default_value = default_value;
|
541
|
-
f->required = required;
|
542
540
|
if (NULL == type->fields) {
|
543
541
|
type->fields = f;
|
544
542
|
} else {
|
@@ -559,8 +557,7 @@ gql_field_arg(agooErr err,
|
|
559
557
|
gqlType type,
|
560
558
|
const char *desc,
|
561
559
|
size_t dlen,
|
562
|
-
struct _gqlValue *def_value
|
563
|
-
bool required) {
|
560
|
+
struct _gqlValue *def_value) {
|
564
561
|
gqlArg a = (gqlArg)AGOO_MALLOC(sizeof(struct _gqlArg));
|
565
562
|
|
566
563
|
if (NULL == a) {
|
@@ -579,7 +576,6 @@ gql_field_arg(agooErr err,
|
|
579
576
|
}
|
580
577
|
a->default_value = def_value;
|
581
578
|
a->dir = NULL;
|
582
|
-
a->required = required;
|
583
579
|
if (NULL == field->args) {
|
584
580
|
field->args = a;
|
585
581
|
} else {
|
@@ -600,8 +596,7 @@ gql_input_arg(agooErr err,
|
|
600
596
|
gqlType type,
|
601
597
|
const char *desc,
|
602
598
|
size_t dlen,
|
603
|
-
struct _gqlValue *def_value
|
604
|
-
bool required) {
|
599
|
+
struct _gqlValue *def_value) {
|
605
600
|
gqlArg a = (gqlArg)AGOO_MALLOC(sizeof(struct _gqlArg));
|
606
601
|
|
607
602
|
if (NULL == a) {
|
@@ -620,7 +615,6 @@ gql_input_arg(agooErr err,
|
|
620
615
|
}
|
621
616
|
a->default_value = def_value;
|
622
617
|
a->dir = NULL;
|
623
|
-
a->required = required;
|
624
618
|
if (NULL == input->args) {
|
625
619
|
input->args = a;
|
626
620
|
} else {
|
@@ -801,8 +795,7 @@ gql_dir_arg(agooErr err,
|
|
801
795
|
gqlType type,
|
802
796
|
const char *desc,
|
803
797
|
size_t dlen,
|
804
|
-
struct _gqlValue *def_value
|
805
|
-
bool required) {
|
798
|
+
struct _gqlValue *def_value) {
|
806
799
|
|
807
800
|
gqlArg a = (gqlArg)AGOO_MALLOC(sizeof(struct _gqlArg));
|
808
801
|
|
@@ -822,7 +815,6 @@ gql_dir_arg(agooErr err,
|
|
822
815
|
}
|
823
816
|
a->default_value = def_value;
|
824
817
|
a->dir = NULL;
|
825
|
-
a->required = required;
|
826
818
|
if (NULL == dir->args) {
|
827
819
|
dir->args = a;
|
828
820
|
} else {
|
@@ -863,11 +855,11 @@ gql_directive_on(agooErr err, gqlDir d, const char *on, int len) {
|
|
863
855
|
}
|
864
856
|
|
865
857
|
gqlType
|
866
|
-
gql_assure_list(agooErr err, gqlType base
|
858
|
+
gql_assure_list(agooErr err, gqlType base) {
|
867
859
|
char name[256];
|
868
860
|
gqlType type;
|
869
861
|
|
870
|
-
if ((int)sizeof(name) <= snprintf(name, sizeof(name), "[%s
|
862
|
+
if ((int)sizeof(name) <= snprintf(name, sizeof(name), "[%s]", base->name)) {
|
871
863
|
agoo_err_set(err, AGOO_ERR_ARG, "Name too long");
|
872
864
|
return NULL;
|
873
865
|
}
|
@@ -876,7 +868,24 @@ gql_assure_list(agooErr err, gqlType base, bool not_empty) {
|
|
876
868
|
return NULL;
|
877
869
|
}
|
878
870
|
type->base = base;
|
879
|
-
|
871
|
+
}
|
872
|
+
return type;
|
873
|
+
}
|
874
|
+
|
875
|
+
gqlType
|
876
|
+
gql_assure_nonnull(agooErr err, gqlType base) {
|
877
|
+
char name[256];
|
878
|
+
gqlType type;
|
879
|
+
|
880
|
+
if ((int)sizeof(name) <= snprintf(name, sizeof(name), "%s!", base->name)) {
|
881
|
+
agoo_err_set(err, AGOO_ERR_ARG, "Name too long");
|
882
|
+
return NULL;
|
883
|
+
}
|
884
|
+
if (NULL == (type = gql_type_get(name))) {
|
885
|
+
if (NULL == (type = type_create(err, GQL_NON_NULL, name, NULL, 0))) {
|
886
|
+
return NULL;
|
887
|
+
}
|
888
|
+
type->base = base;
|
880
889
|
}
|
881
890
|
return type;
|
882
891
|
}
|
@@ -988,9 +997,6 @@ arg_sdl(agooText text, gqlArg a, bool with_desc, bool same_line, bool last) {
|
|
988
997
|
if (NULL != a->type) { // should always be true
|
989
998
|
text = agoo_text_append(text, a->type->name, -1);
|
990
999
|
}
|
991
|
-
if (a->required) {
|
992
|
-
text = agoo_text_append(text, "!", 1);
|
993
|
-
}
|
994
1000
|
if (NULL != a->default_value) {
|
995
1001
|
text = agoo_text_append(text, " = ", 3);
|
996
1002
|
text = gql_value_sdl(text, a->default_value, 0, 0);
|
@@ -1024,9 +1030,6 @@ field_sdl(agooText text, gqlField f, bool with_desc) {
|
|
1024
1030
|
}
|
1025
1031
|
text = agoo_text_append(text, ": ", 2);
|
1026
1032
|
text = agoo_text_append(text, f->type->name, -1);
|
1027
|
-
if (f->required) {
|
1028
|
-
text = agoo_text_append(text, "!", 1);
|
1029
|
-
}
|
1030
1033
|
if (NULL != f->default_value) {
|
1031
1034
|
text = agoo_text_append(text, " = ", 3);
|
1032
1035
|
text = gql_value_sdl(text, f->default_value, 0, 0);
|
@@ -1204,7 +1207,7 @@ gql_schema_sdl(agooText text, bool with_desc, bool all) {
|
|
1204
1207
|
for (bucket = buckets, i = 0; i < BUCKET_SIZE; bucket++, i++) {
|
1205
1208
|
for (s = *bucket; NULL != s; s = s->next) {
|
1206
1209
|
type = s->type;
|
1207
|
-
if (GQL_LIST == type->kind) {
|
1210
|
+
if (GQL_LIST == type->kind || GQL_NON_NULL == type->kind) {
|
1208
1211
|
continue;
|
1209
1212
|
}
|
1210
1213
|
if (!all && type->core) {
|
@@ -1216,11 +1219,12 @@ gql_schema_sdl(agooText text, bool with_desc, bool all) {
|
|
1216
1219
|
if (0 < cnt) {
|
1217
1220
|
gqlType types[cnt];
|
1218
1221
|
gqlType *tp = types;
|
1222
|
+
long len;
|
1219
1223
|
|
1220
1224
|
for (bucket = buckets, i = 0; i < BUCKET_SIZE; bucket++, i++) {
|
1221
1225
|
for (s = *bucket; NULL != s; s = s->next) {
|
1222
1226
|
type = s->type;
|
1223
|
-
if (GQL_LIST == type->kind) {
|
1227
|
+
if (GQL_LIST == type->kind || GQL_NON_NULL == type->kind) {
|
1224
1228
|
continue;
|
1225
1229
|
}
|
1226
1230
|
if (!all && type->core) {
|
@@ -1231,8 +1235,9 @@ gql_schema_sdl(agooText text, bool with_desc, bool all) {
|
|
1231
1235
|
}
|
1232
1236
|
qsort(types, cnt, sizeof(gqlType), type_cmp);
|
1233
1237
|
for (i = 0, tp = types; i < cnt; i++, tp++) {
|
1238
|
+
len = text->len;
|
1234
1239
|
text = gql_type_sdl(text, *tp, with_desc);
|
1235
|
-
if (i < cnt - 1) {
|
1240
|
+
if (i < cnt - 1 && len < text->len) {
|
1236
1241
|
text = agoo_text_append(text, "\n", 1);
|
1237
1242
|
}
|
1238
1243
|
}
|
@@ -1355,6 +1360,9 @@ gql_doc_create(agooErr err) {
|
|
1355
1360
|
doc->ops = NULL;
|
1356
1361
|
doc->vars = NULL;
|
1357
1362
|
doc->frags = NULL;
|
1363
|
+
doc->req = NULL;
|
1364
|
+
doc->ctx = NULL;
|
1365
|
+
doc->ctx_free = NULL;
|
1358
1366
|
}
|
1359
1367
|
return doc;
|
1360
1368
|
}
|
@@ -1474,6 +1482,9 @@ gql_doc_destroy(gqlDoc doc) {
|
|
1474
1482
|
doc->frags = frag->next;
|
1475
1483
|
gql_frag_destroy(frag);
|
1476
1484
|
}
|
1485
|
+
if (NULL != doc->ctx_free) {
|
1486
|
+
doc->ctx_free(doc->ctx);
|
1487
|
+
}
|
1477
1488
|
AGOO_FREE(doc);
|
1478
1489
|
}
|
1479
1490
|
|
data/ext/agoo/graphql.h
CHANGED
@@ -88,7 +88,6 @@ typedef struct _gqlArg {
|
|
88
88
|
struct _gqlType *type;
|
89
89
|
struct _gqlValue *default_value;
|
90
90
|
struct _gqlDirUse *dir;
|
91
|
-
bool required;
|
92
91
|
} *gqlArg;
|
93
92
|
|
94
93
|
typedef struct _gqlField {
|
@@ -99,7 +98,6 @@ typedef struct _gqlField {
|
|
99
98
|
gqlArg args;
|
100
99
|
struct _gqlDirUse *dir;
|
101
100
|
struct _gqlValue *default_value;
|
102
|
-
bool required;
|
103
101
|
} *gqlField;
|
104
102
|
|
105
103
|
typedef struct _gqlDir {
|
@@ -133,15 +131,12 @@ typedef struct _gqlType {
|
|
133
131
|
gqlTypeLink types; // Union
|
134
132
|
gqlEnumVal choices; // Enums
|
135
133
|
gqlArg args; // InputObject
|
134
|
+
struct _gqlType *base; // List and NonNull types
|
136
135
|
struct { // scalar
|
137
136
|
agooText (*to_sdl)(agooText text, struct _gqlValue *value, int indent, int depth);
|
138
137
|
agooText (*to_json)(agooText text, struct _gqlValue *value, int indent, int depth);
|
139
138
|
void (*destroy)(struct _gqlValue *value);
|
140
139
|
};
|
141
|
-
struct { // List types
|
142
|
-
struct _gqlType *base;
|
143
|
-
bool not_empty;
|
144
|
-
};
|
145
140
|
};
|
146
141
|
} *gqlType;
|
147
142
|
|
@@ -202,6 +197,9 @@ typedef struct _gqlDoc {
|
|
202
197
|
gqlFrag frags;
|
203
198
|
gqlOp op; // the op to execute
|
204
199
|
struct _gqlFuncs funcs;
|
200
|
+
struct _agooReq *req;
|
201
|
+
void *ctx;
|
202
|
+
void (*ctx_free)(void*);
|
205
203
|
} *gqlDoc;
|
206
204
|
|
207
205
|
extern int gql_init(agooErr err);
|
@@ -222,8 +220,7 @@ extern gqlField gql_type_field(agooErr err,
|
|
222
220
|
gqlType return_type,
|
223
221
|
struct _gqlValue *default_value,
|
224
222
|
const char *desc,
|
225
|
-
size_t dlen
|
226
|
-
bool required);
|
223
|
+
size_t dlen);
|
227
224
|
|
228
225
|
extern gqlArg gql_field_arg(agooErr err,
|
229
226
|
gqlField field,
|
@@ -231,8 +228,7 @@ extern gqlArg gql_field_arg(agooErr err,
|
|
231
228
|
gqlType type,
|
232
229
|
const char *desc,
|
233
230
|
size_t dlen,
|
234
|
-
struct _gqlValue *def_value
|
235
|
-
bool required);
|
231
|
+
struct _gqlValue *def_value);
|
236
232
|
|
237
233
|
extern gqlArg gql_input_arg(agooErr err,
|
238
234
|
gqlType input,
|
@@ -240,8 +236,7 @@ extern gqlArg gql_input_arg(agooErr err,
|
|
240
236
|
gqlType type,
|
241
237
|
const char *desc,
|
242
238
|
size_t dlen,
|
243
|
-
struct _gqlValue *def_value
|
244
|
-
bool required);
|
239
|
+
struct _gqlValue *def_value);
|
245
240
|
|
246
241
|
extern gqlType gql_scalar_create(agooErr err, const char *name, const char *desc, size_t dlen);
|
247
242
|
|
@@ -252,8 +247,7 @@ extern gqlArg gql_dir_arg(agooErr err,
|
|
252
247
|
gqlType type,
|
253
248
|
const char *desc,
|
254
249
|
size_t dlen,
|
255
|
-
struct _gqlValue *def_value
|
256
|
-
bool required);
|
250
|
+
struct _gqlValue *def_value);
|
257
251
|
extern int gql_directive_on(agooErr err, gqlDir d, const char *on, int len);
|
258
252
|
extern gqlDir gql_directive_get(const char *name);
|
259
253
|
|
@@ -266,7 +260,8 @@ extern int gql_union_add(agooErr err, gqlType type, gqlType member);
|
|
266
260
|
extern gqlType gql_enum_create(agooErr err, const char *name, const char *desc, size_t dlen);
|
267
261
|
extern gqlEnumVal gql_enum_append(agooErr err, gqlType type, const char *value, size_t len, const char *desc, size_t dlen);
|
268
262
|
|
269
|
-
extern gqlType gql_assure_list(agooErr err, gqlType base
|
263
|
+
extern gqlType gql_assure_list(agooErr err, gqlType base);
|
264
|
+
extern gqlType gql_assure_nonnull(agooErr err, gqlType base);
|
270
265
|
|
271
266
|
extern int gql_type_set(agooErr err, gqlType type);
|
272
267
|
extern gqlType gql_type_get(const char *name);
|
@@ -291,6 +286,7 @@ extern agooText gql_doc_sdl(gqlDoc doc, agooText text);
|
|
291
286
|
extern void gql_dump_hook(struct _agooReq *req);
|
292
287
|
extern void gql_eval_get_hook(struct _agooReq *req);
|
293
288
|
extern void gql_eval_post_hook(struct _agooReq *req);
|
289
|
+
extern void gql_eval_options_hook(struct _agooReq *req);
|
294
290
|
|
295
291
|
extern int gql_validate(agooErr err);
|
296
292
|
|
data/ext/agoo/rgraphql.c
CHANGED
@@ -13,6 +13,7 @@
|
|
13
13
|
#include "gqlvalue.h"
|
14
14
|
#include "graphql.h"
|
15
15
|
#include "pub.h"
|
16
|
+
#include "request.h"
|
16
17
|
#include "sdl.h"
|
17
18
|
#include "server.h"
|
18
19
|
|
@@ -27,13 +28,28 @@ typedef struct _typeClass {
|
|
27
28
|
const char *classname;
|
28
29
|
} *TypeClass;
|
29
30
|
|
31
|
+
typedef struct _bhArgs {
|
32
|
+
agooErr err;
|
33
|
+
agooReq req;
|
34
|
+
agooText headers;
|
35
|
+
} *bhArgs;
|
36
|
+
|
30
37
|
static VALUE graphql_class = Qundef;
|
31
38
|
static VALUE vroot = Qnil;
|
39
|
+
static VALUE build_headers_func = Qnil;
|
40
|
+
|
41
|
+
static ID call_id;
|
32
42
|
|
33
43
|
static TypeClass type_class_map = NULL;
|
34
44
|
|
35
45
|
static int
|
36
|
-
make_ruby_use(agooErr
|
46
|
+
make_ruby_use(agooErr err,
|
47
|
+
VALUE root,
|
48
|
+
const char *method,
|
49
|
+
const char *type_name,
|
50
|
+
bool fresh,
|
51
|
+
gqlType schema_type,
|
52
|
+
const char *desc) {
|
37
53
|
gqlType type;
|
38
54
|
gqlDirUse use;
|
39
55
|
volatile VALUE v;
|
@@ -47,7 +63,7 @@ make_ruby_use(agooErr err, VALUE root, const char *method, const char *type_name
|
|
47
63
|
return agoo_err_set(err, AGOO_ERR_ARG, "Failed to find the '%s' type.", type_name);
|
48
64
|
}
|
49
65
|
if (fresh) {
|
50
|
-
if (NULL == gql_type_field(err, schema_type, method, type, NULL, desc, 0
|
66
|
+
if (NULL == gql_type_field(err, schema_type, method, type, NULL, desc, 0)) {
|
51
67
|
return err->code;
|
52
68
|
}
|
53
69
|
}
|
@@ -225,6 +241,9 @@ coerce(agooErr err, gqlRef ref, gqlType type) {
|
|
225
241
|
if (Qnil == (VALUE)ref) {
|
226
242
|
return gql_null_create(err);
|
227
243
|
}
|
244
|
+
if (NULL != type && GQL_NON_NULL == type->kind) {
|
245
|
+
type = type->base;
|
246
|
+
}
|
228
247
|
if (NULL == type) {
|
229
248
|
// This is really an error but make a best effort anyway.
|
230
249
|
switch (rb_type((VALUE)ref)) {
|
@@ -372,12 +391,25 @@ ref_type(gqlRef ref) {
|
|
372
391
|
return type;
|
373
392
|
}
|
374
393
|
|
394
|
+
static VALUE
|
395
|
+
make_plan(gqlSel sel) {
|
396
|
+
|
397
|
+
// TBD create a plan object that wraps the sel, create children as needed
|
398
|
+
// plan is not valid outside of method
|
399
|
+
// should be able to create SDL from it
|
400
|
+
|
401
|
+
return Qnil;
|
402
|
+
}
|
403
|
+
|
375
404
|
static int
|
376
405
|
resolve(agooErr err, gqlDoc doc, gqlRef target, gqlField field, gqlSel sel, gqlValue result, int depth) {
|
377
406
|
volatile VALUE child;
|
407
|
+
volatile VALUE rreq = Qnil;
|
378
408
|
VALUE obj = (VALUE)target;
|
379
409
|
int d2 = depth + 1;
|
380
410
|
const char *key = sel->name;
|
411
|
+
ID method;
|
412
|
+
int arity;
|
381
413
|
|
382
414
|
if ('_' == *sel->name && '_' == sel->name[1]) {
|
383
415
|
if (0 == strcmp("__typename", sel->name)) {
|
@@ -397,8 +429,10 @@ resolve(agooErr err, gqlDoc doc, gqlRef target, gqlField field, gqlSel sel, gqlV
|
|
397
429
|
return agoo_err_set(err, AGOO_ERR_EVAL, "Not a valid operation on the root object.");
|
398
430
|
}
|
399
431
|
}
|
400
|
-
|
401
|
-
|
432
|
+
method = rb_intern(sel->name);
|
433
|
+
arity = rb_obj_method_arity(obj, method);
|
434
|
+
if (0 == arity) {
|
435
|
+
child = rb_funcall(obj, method, 0);
|
402
436
|
} else {
|
403
437
|
volatile VALUE rargs = rb_hash_new();
|
404
438
|
gqlSelArg sa;
|
@@ -429,7 +463,21 @@ resolve(agooErr err, gqlDoc doc, gqlRef target, gqlField field, gqlSel sel, gqlV
|
|
429
463
|
}
|
430
464
|
rb_hash_aset(rargs, rb_str_new_cstr(sa->name), gval_to_ruby(v));
|
431
465
|
}
|
432
|
-
|
466
|
+
if (-1 == arity || 1 == arity) {
|
467
|
+
child = rb_funcall(obj, method, 1, rargs);
|
468
|
+
} else {
|
469
|
+
if (NULL == doc->ctx) {
|
470
|
+
rreq = request_wrap(doc->req);
|
471
|
+
doc->ctx = (void*)rreq;
|
472
|
+
} else {
|
473
|
+
rreq = (VALUE)doc->ctx;
|
474
|
+
}
|
475
|
+
if (-2 == arity || 2 == arity) {
|
476
|
+
child = rb_funcall(obj, method, 2, rargs, rreq);
|
477
|
+
} else {
|
478
|
+
child = rb_funcall(obj, method, 3, rargs, rreq, make_plan(sel));
|
479
|
+
}
|
480
|
+
}
|
433
481
|
}
|
434
482
|
if (GQL_SUBSCRIPTION == doc->op->kind && RUBY_T_STRING == rb_type(child)) {
|
435
483
|
gqlValue c;
|
@@ -591,6 +639,7 @@ graphql_schema(VALUE self, VALUE root) {
|
|
591
639
|
gqlDirUse use;
|
592
640
|
gqlType schema_type;
|
593
641
|
bool fresh = false;
|
642
|
+
gqlType string_nn;
|
594
643
|
|
595
644
|
if (!rb_block_given_p()) {
|
596
645
|
rb_raise(rb_eStandardError, "A block is required.");
|
@@ -603,7 +652,8 @@ graphql_schema(VALUE self, VALUE root) {
|
|
603
652
|
printf("*-*-* %s\n", err.msg);
|
604
653
|
exit(2);
|
605
654
|
}
|
606
|
-
if (NULL ==
|
655
|
+
if (NULL == (string_nn = gql_assure_nonnull(&err, &gql_string_type)) ||
|
656
|
+
NULL == gql_dir_arg(&err, dir, "class", string_nn, NULL, 0, NULL)) {
|
607
657
|
printf("*-*-* %s\n", err.msg);
|
608
658
|
exit(3);
|
609
659
|
}
|
@@ -791,6 +841,105 @@ graphql_publish(VALUE self, VALUE subject, VALUE event) {
|
|
791
841
|
return Qnil;
|
792
842
|
}
|
793
843
|
|
844
|
+
static VALUE
|
845
|
+
rescue_build_header(VALUE x, VALUE ignore) {
|
846
|
+
bhArgs args = (bhArgs)x;
|
847
|
+
volatile VALUE info = rb_errinfo();
|
848
|
+
volatile VALUE msg = rb_funcall(info, rb_intern("message"), 0);
|
849
|
+
|
850
|
+
agoo_err_set(args->err, AGOO_ERR_EVAL, "%s", rb_string_value_ptr(&msg));
|
851
|
+
|
852
|
+
return Qnil;
|
853
|
+
}
|
854
|
+
|
855
|
+
static int
|
856
|
+
build_headers_cb(VALUE key, VALUE value, VALUE x) {
|
857
|
+
bhArgs args = (bhArgs)x;
|
858
|
+
const char *ks = rb_string_value_ptr((VALUE*)&key);
|
859
|
+
volatile VALUE vs = rb_obj_as_string(value);
|
860
|
+
const char *s = rb_string_value_ptr((VALUE*)&vs);
|
861
|
+
|
862
|
+
if (NULL == (args->headers = gql_add_header(args->err, args->headers, ks, s))) {
|
863
|
+
rb_raise(rb_eStandardError, "%s", args->err->msg);
|
864
|
+
}
|
865
|
+
return ST_CONTINUE;
|
866
|
+
}
|
867
|
+
|
868
|
+
static VALUE
|
869
|
+
inner_build_headers(VALUE x) {
|
870
|
+
volatile VALUE hh = rb_funcall(build_headers_func, call_id, 1, request_wrap(((bhArgs)x)->req));
|
871
|
+
|
872
|
+
rb_hash_foreach(hh, build_headers_cb, x);
|
873
|
+
|
874
|
+
return Qnil;
|
875
|
+
}
|
876
|
+
|
877
|
+
static void*
|
878
|
+
protected_build_headers(void *x) {
|
879
|
+
return (void*)rb_rescue2(inner_build_headers, (VALUE)x, rescue_build_header, (VALUE)x, rb_eException, 0);
|
880
|
+
}
|
881
|
+
|
882
|
+
static agooText
|
883
|
+
build_headers(agooErr err, agooReq req, agooText headers) {
|
884
|
+
struct _bhArgs args = {
|
885
|
+
.err = err,
|
886
|
+
.req = req,
|
887
|
+
.headers = headers,
|
888
|
+
};
|
889
|
+
rb_thread_call_with_gvl(protected_build_headers, &args);
|
890
|
+
|
891
|
+
return args.headers;
|
892
|
+
}
|
893
|
+
|
894
|
+
/* Document-method: build_headers=
|
895
|
+
*
|
896
|
+
* call-seq: build_headers=(func)
|
897
|
+
*
|
898
|
+
* Provide a function to call that builds headers for GraphQL responses. The
|
899
|
+
* function should expect a single request and should return a Hash of the
|
900
|
+
* headers to add. Content-Type and Content-Length should not be set.
|
901
|
+
*/
|
902
|
+
static VALUE
|
903
|
+
graphql_build_headers(VALUE self, VALUE func) {
|
904
|
+
gql_build_headers = build_headers;
|
905
|
+
build_headers_func = func;
|
906
|
+
rb_gc_register_address(&build_headers_func);
|
907
|
+
|
908
|
+
return Qnil;
|
909
|
+
}
|
910
|
+
|
911
|
+
static int
|
912
|
+
headers_cb(VALUE key, VALUE value, VALUE x) {
|
913
|
+
agooText *tp = (agooText*)x;
|
914
|
+
const char *ks = rb_string_value_ptr((VALUE*)&key);
|
915
|
+
volatile VALUE vs = rb_obj_as_string(value);
|
916
|
+
const char *s = rb_string_value_ptr((VALUE*)&vs);
|
917
|
+
struct _agooErr err = AGOO_ERR_INIT;
|
918
|
+
|
919
|
+
if (NULL == (*tp = gql_add_header(&err, *tp, ks, s))) {
|
920
|
+
rb_raise(rb_eStandardError, "%s", err.msg);
|
921
|
+
}
|
922
|
+
return ST_CONTINUE;
|
923
|
+
}
|
924
|
+
|
925
|
+
|
926
|
+
/* Document-method: headers
|
927
|
+
*
|
928
|
+
* call-seq: headers(header_hash)
|
929
|
+
*
|
930
|
+
* Provide a Hash to be used as the headers for GraphQL responses.
|
931
|
+
* Content-Type and Content-Length should not be set.
|
932
|
+
*/
|
933
|
+
static VALUE
|
934
|
+
graphql_headers(VALUE self, VALUE map) {
|
935
|
+
agooText t = agoo_text_allocate(1024);
|
936
|
+
|
937
|
+
rb_hash_foreach(map, headers_cb, (VALUE)&t);
|
938
|
+
gql_headers = t;
|
939
|
+
|
940
|
+
return Qnil;
|
941
|
+
}
|
942
|
+
|
794
943
|
/* Document-class: Agoo::Graphql
|
795
944
|
*
|
796
945
|
* The Agoo::GraphQL class provides support for the GraphQL API as defined in
|
@@ -815,4 +964,9 @@ graphql_init(VALUE mod) {
|
|
815
964
|
rb_define_module_function(graphql_class, "sdl_dump", graphql_sdl_dump, 1);
|
816
965
|
|
817
966
|
rb_define_module_function(graphql_class, "publish", graphql_publish, 2);
|
967
|
+
|
968
|
+
rb_define_module_function(graphql_class, "build_headers=", graphql_build_headers, 1);
|
969
|
+
rb_define_module_function(graphql_class, "headers", graphql_headers, 1);
|
970
|
+
|
971
|
+
call_id = rb_intern("call");
|
818
972
|
}
|