agoo 2.8.4 → 2.9.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 +13 -0
- data/ext/agoo/agoo.c +2 -0
- data/ext/agoo/con.c +74 -43
- data/ext/agoo/debug.h +1 -0
- data/ext/agoo/domain.c +145 -0
- data/ext/agoo/domain.h +16 -0
- data/ext/agoo/early.c +28 -0
- data/ext/agoo/early.h +23 -0
- data/ext/agoo/early_hints.c +116 -0
- data/ext/agoo/early_hints.h +13 -0
- data/ext/agoo/gqleval.c +2 -2
- data/ext/agoo/graphql.c +1 -1
- data/ext/agoo/page.c +139 -52
- data/ext/agoo/page.h +4 -4
- data/ext/agoo/request.c +9 -1
- data/ext/agoo/res.c +65 -7
- data/ext/agoo/res.h +11 -8
- data/ext/agoo/rserver.c +75 -8
- data/ext/agoo/server.c +2 -0
- data/ext/agoo/server.h +1 -0
- data/ext/agoo/text.c +3 -0
- data/ext/agoo/text.h +6 -5
- data/lib/agoo/version.rb +1 -1
- data/test/domain_test.rb +84 -0
- data/test/early_hints_test.rb +104 -0
- data/test/rack_handler_test.rb +4 -4
- metadata +16 -6
data/ext/agoo/domain.h
ADDED
@@ -0,0 +1,16 @@
|
|
1
|
+
// Copyright 2019 by Peter Ohler, All Rights Reserved
|
2
|
+
|
3
|
+
#ifndef AGOO_DOMAIN_H
|
4
|
+
#define AGOO_DOMAIN_H
|
5
|
+
|
6
|
+
#include <stdbool.h>
|
7
|
+
|
8
|
+
#include "err.h"
|
9
|
+
|
10
|
+
extern bool agoo_domain_use();
|
11
|
+
extern int agoo_domain_add(agooErr err, const char *host, const char *path);
|
12
|
+
extern int agoo_domain_add_regex(agooErr err, const char *host, const char *path);
|
13
|
+
extern const char* agoo_domain_resolve(const char *host, char *buf, size_t blen);
|
14
|
+
extern void agoo_domain_cleanup();
|
15
|
+
|
16
|
+
#endif // AGOO_DOMAIN_H
|
data/ext/agoo/early.c
ADDED
@@ -0,0 +1,28 @@
|
|
1
|
+
// Copyright (c) 2019, Peter Ohler, All rights reserved.
|
2
|
+
|
3
|
+
#include "debug.h"
|
4
|
+
#include "early.h"
|
5
|
+
|
6
|
+
agooEarly
|
7
|
+
agoo_early_create(const char *link) {
|
8
|
+
agooEarly early = (agooEarly)AGOO_CALLOC(1, sizeof(struct _agooEarly));
|
9
|
+
|
10
|
+
if (NULL != early) {
|
11
|
+
if (NULL == (early->link = AGOO_STRDUP(link))) {
|
12
|
+
AGOO_FREE(early);
|
13
|
+
return NULL;
|
14
|
+
}
|
15
|
+
}
|
16
|
+
return early;
|
17
|
+
}
|
18
|
+
|
19
|
+
void
|
20
|
+
agoo_early_destroy(agooEarly early) {
|
21
|
+
if (NULL != early) {
|
22
|
+
if (NULL != early->next) {
|
23
|
+
agoo_early_destroy(early->next);
|
24
|
+
}
|
25
|
+
AGOO_FREE(early->link);
|
26
|
+
AGOO_FREE(early);
|
27
|
+
}
|
28
|
+
}
|
data/ext/agoo/early.h
ADDED
@@ -0,0 +1,23 @@
|
|
1
|
+
// Copyright (c) 2019, Peter Ohler, All rights reserved.
|
2
|
+
|
3
|
+
#ifndef AGOO_EARLY_H
|
4
|
+
#define AGOO_EARLY_H
|
5
|
+
|
6
|
+
#include <stdbool.h>
|
7
|
+
|
8
|
+
#include "atomic.h"
|
9
|
+
#include "con.h"
|
10
|
+
#include "text.h"
|
11
|
+
|
12
|
+
struct _agooCon;
|
13
|
+
|
14
|
+
typedef struct _agooEarly {
|
15
|
+
struct _agooEarly *next;
|
16
|
+
bool sent;
|
17
|
+
char *link;
|
18
|
+
} *agooEarly;
|
19
|
+
|
20
|
+
extern agooEarly agoo_early_create(const char *link);
|
21
|
+
extern void agoo_early_destroy(agooEarly early);
|
22
|
+
|
23
|
+
#endif // AGOO_EARLY_H
|
@@ -0,0 +1,116 @@
|
|
1
|
+
// Copyright (c) 2019, Peter Ohler, All rights reserved.
|
2
|
+
|
3
|
+
#include <stdio.h>
|
4
|
+
#include <stdlib.h>
|
5
|
+
#include <ctype.h>
|
6
|
+
|
7
|
+
#include "debug.h"
|
8
|
+
#include "early.h"
|
9
|
+
#include "early_hints.h"
|
10
|
+
#include "req.h"
|
11
|
+
#include "res.h"
|
12
|
+
|
13
|
+
static VALUE eh_class = Qundef;
|
14
|
+
|
15
|
+
typedef struct _earlyHints {
|
16
|
+
agooReq req;
|
17
|
+
agooEarly links;
|
18
|
+
} *EarlyHints;
|
19
|
+
|
20
|
+
static void
|
21
|
+
eh_free(void *ptr) {
|
22
|
+
if (NULL != ptr) {
|
23
|
+
AGOO_FREE(ptr);
|
24
|
+
}
|
25
|
+
}
|
26
|
+
|
27
|
+
VALUE
|
28
|
+
agoo_early_hints_new(agooReq req) {
|
29
|
+
EarlyHints eh = (EarlyHints)AGOO_CALLOC(1, sizeof(struct _earlyHints));
|
30
|
+
|
31
|
+
if (NULL == eh) {
|
32
|
+
rb_raise(rb_eNoMemError, "Failed to allocate memory for an early hints object.");
|
33
|
+
}
|
34
|
+
eh->req = req;
|
35
|
+
|
36
|
+
return Data_Wrap_Struct(eh_class, NULL, eh_free, eh);
|
37
|
+
}
|
38
|
+
|
39
|
+
/* Document-method: call
|
40
|
+
*
|
41
|
+
* call-seq: call(links)
|
42
|
+
*
|
43
|
+
* Write early hints, response with status 103 using the provided headers in
|
44
|
+
* an Array of Array.
|
45
|
+
*
|
46
|
+
* Example:
|
47
|
+
*
|
48
|
+
* early_hints.call([
|
49
|
+
* ["link", "</style.css>; rel=preload; as=style"],
|
50
|
+
* ["link", "</script.js>; rel=preload; as=script"],
|
51
|
+
* ])
|
52
|
+
*/
|
53
|
+
static VALUE
|
54
|
+
eh_call(VALUE self, VALUE links) {
|
55
|
+
EarlyHints eh = (EarlyHints)DATA_PTR(self);
|
56
|
+
agooEarly link;
|
57
|
+
agooEarly ll = NULL;
|
58
|
+
int i, cnt;
|
59
|
+
VALUE lv;
|
60
|
+
VALUE v;
|
61
|
+
const char *key;
|
62
|
+
const char *content;
|
63
|
+
|
64
|
+
if (NULL == eh) {
|
65
|
+
rb_raise(rb_eIOError, "early hints has been closed.");
|
66
|
+
}
|
67
|
+
rb_check_type(links, RUBY_T_ARRAY);
|
68
|
+
|
69
|
+
// Link: </style.css>; rel=preload; as=style
|
70
|
+
cnt = (int)RARRAY_LEN(links);
|
71
|
+
for (i = cnt - 1; 0 <= i; i--) {
|
72
|
+
lv = rb_ary_entry(links, i);
|
73
|
+
switch (rb_type(lv)) {
|
74
|
+
case RUBY_T_STRING:
|
75
|
+
content = rb_string_value_ptr((VALUE*)&v);
|
76
|
+
if (NULL == (link = agoo_early_create(content))) {
|
77
|
+
rb_raise(rb_eNoMemError, "out of memory");
|
78
|
+
}
|
79
|
+
break;
|
80
|
+
case RUBY_T_ARRAY:
|
81
|
+
if (2 != RARRAY_LEN(lv)) {
|
82
|
+
rb_raise(rb_eArgError, "early hints call argument must be an array of arrays that have 2 string members.");
|
83
|
+
}
|
84
|
+
v = rb_ary_entry(lv, 0);
|
85
|
+
key = rb_string_value_ptr((VALUE*)&v);
|
86
|
+
if (0 != strcasecmp("link", key)) {
|
87
|
+
rb_raise(rb_eArgError, "Only a 'Link' header is allowed in early hints. '%s' is not allowed", key);
|
88
|
+
}
|
89
|
+
v = rb_ary_entry(lv, 1);
|
90
|
+
content = rb_string_value_ptr((VALUE*)&v);
|
91
|
+
if (NULL == (link = agoo_early_create(content))) {
|
92
|
+
rb_raise(rb_eNoMemError, "out of memory");
|
93
|
+
}
|
94
|
+
break;
|
95
|
+
default:
|
96
|
+
rb_raise(rb_eArgError, "early hints call argument must be an array of arrays or an array of strings.");
|
97
|
+
}
|
98
|
+
link->next = ll;
|
99
|
+
ll = link;
|
100
|
+
}
|
101
|
+
agoo_res_add_early(eh->req->res, ll);
|
102
|
+
agoo_early_destroy(ll);
|
103
|
+
|
104
|
+
return Qnil;
|
105
|
+
}
|
106
|
+
|
107
|
+
/* Document-class: Agoo::EarlyHints
|
108
|
+
*
|
109
|
+
* Used to provide early hints (HTTP 103) responses to requests.
|
110
|
+
*/
|
111
|
+
void
|
112
|
+
early_hints_init(VALUE mod) {
|
113
|
+
eh_class = rb_define_class_under(mod, "EarlyHints", rb_cObject);
|
114
|
+
|
115
|
+
rb_define_method(eh_class, "call", eh_call, 1);
|
116
|
+
}
|
@@ -0,0 +1,13 @@
|
|
1
|
+
// Copyright (c) 2019, Peter Ohler, All rights reserved.
|
2
|
+
|
3
|
+
#ifndef AGOO_EARLY_HINTS_H
|
4
|
+
#define AGOO_EARLY_HINTS_H
|
5
|
+
|
6
|
+
#include <ruby.h>
|
7
|
+
|
8
|
+
struct _agooReq;
|
9
|
+
|
10
|
+
extern void early_hints_init(VALUE mod);
|
11
|
+
extern VALUE agoo_early_hints_new(struct _agooReq *req);
|
12
|
+
|
13
|
+
#endif // AGOO_EARLY_HINTS_H
|
data/ext/agoo/gqleval.c
CHANGED
@@ -54,7 +54,7 @@ err_resp(agooRes res, agooErr err, int status) {
|
|
54
54
|
code,
|
55
55
|
at.year, at.mon, at.day, at.hour, at.min, at.sec, frac);
|
56
56
|
|
57
|
-
|
57
|
+
agoo_res_message_push(res, agoo_text_create(buf, cnt), true);
|
58
58
|
}
|
59
59
|
|
60
60
|
static void
|
@@ -84,7 +84,7 @@ value_resp(agooRes res, gqlValue result, int status, int indent) {
|
|
84
84
|
if (NULL == (text = agoo_text_prepend(text, buf, cnt))) {
|
85
85
|
agoo_log_cat(&agoo_error_cat, "Failed to allocate memory for a response.");
|
86
86
|
}
|
87
|
-
|
87
|
+
agoo_res_message_push(res, text, true);
|
88
88
|
}
|
89
89
|
|
90
90
|
gqlValue
|
data/ext/agoo/graphql.c
CHANGED
@@ -1647,7 +1647,7 @@ gql_dump_hook(agooReq req) {
|
|
1647
1647
|
if (NULL == (text = agoo_text_prepend(text, buf, cnt))) {
|
1648
1648
|
agoo_log_cat(&agoo_error_cat, "Failed to allocate memory for a GraphQL dump.");
|
1649
1649
|
}
|
1650
|
-
|
1650
|
+
agoo_res_message_push(req->res, text, true);
|
1651
1651
|
}
|
1652
1652
|
|
1653
1653
|
gqlField
|
data/ext/agoo/page.c
CHANGED
@@ -48,6 +48,7 @@ typedef struct _mimeSlot {
|
|
48
48
|
|
49
49
|
typedef struct _cache {
|
50
50
|
Slot buckets[PAGE_BUCKET_SIZE];
|
51
|
+
Slot ruckets[PAGE_BUCKET_SIZE];
|
51
52
|
MimeSlot muckets[MIME_BUCKET_SIZE];
|
52
53
|
char *root;
|
53
54
|
agooGroup groups;
|
@@ -112,6 +113,7 @@ static const char page_min_fmt[] = "HTTP/1.1 200 OK\r\nContent-Length: %ld\r\n";
|
|
112
113
|
|
113
114
|
static struct _cache cache = {
|
114
115
|
.buckets = {0},
|
116
|
+
.ruckets = {0},
|
115
117
|
.muckets = {0},
|
116
118
|
.root = NULL,
|
117
119
|
.groups = NULL,
|
@@ -150,6 +152,11 @@ get_bucketp(uint64_t h) {
|
|
150
152
|
return cache.buckets + (PAGE_BUCKET_MASK & (h ^ (h << 5) ^ (h >> 7)));
|
151
153
|
}
|
152
154
|
|
155
|
+
static Slot*
|
156
|
+
get_rucketp(uint64_t h) {
|
157
|
+
return cache.ruckets + (PAGE_BUCKET_MASK & (h ^ (h << 5) ^ (h >> 7)));
|
158
|
+
}
|
159
|
+
|
153
160
|
static MimeSlot*
|
154
161
|
get_mime_bucketp(uint64_t h) {
|
155
162
|
return cache.muckets + (MIME_BUCKET_MASK & (h ^ (h << 5) ^ (h >> 7)));
|
@@ -192,6 +199,24 @@ cache_get(const char *key, int klen) {
|
|
192
199
|
return v;
|
193
200
|
}
|
194
201
|
|
202
|
+
agooPage
|
203
|
+
cache_root_get(const char *key, int klen) {
|
204
|
+
int len = klen;
|
205
|
+
int64_t h = calc_hash(key, &len);
|
206
|
+
Slot *bucket = get_rucketp(h);
|
207
|
+
Slot s;
|
208
|
+
agooPage v = NULL;
|
209
|
+
|
210
|
+
for (s = *bucket; NULL != s; s = s->next) {
|
211
|
+
if (h == (int64_t)s->hash && len == (int)s->klen &&
|
212
|
+
((0 <= len && len <= MAX_KEY_UNIQ) || 0 == strncmp(s->key, key, klen))) {
|
213
|
+
v = s->value;
|
214
|
+
break;
|
215
|
+
}
|
216
|
+
}
|
217
|
+
return v;
|
218
|
+
}
|
219
|
+
|
195
220
|
int
|
196
221
|
mime_set(agooErr err, const char *key, const char *value) {
|
197
222
|
int klen = (int)strlen(key);
|
@@ -199,7 +224,7 @@ mime_set(agooErr err, const char *key, const char *value) {
|
|
199
224
|
int64_t h = calc_hash(key, &len);
|
200
225
|
MimeSlot *bucket = get_mime_bucketp(h);
|
201
226
|
MimeSlot s;
|
202
|
-
|
227
|
+
|
203
228
|
if (MAX_MIME_KEY_LEN < len) {
|
204
229
|
return agoo_err_set(err, AGOO_ERR_ARG, "%s is too long for a file extension. Maximum is %d", key, MAX_MIME_KEY_LEN);
|
205
230
|
}
|
@@ -235,19 +260,16 @@ mime_set(agooErr err, const char *key, const char *value) {
|
|
235
260
|
}
|
236
261
|
|
237
262
|
static agooPage
|
238
|
-
|
239
|
-
int len = klen;
|
240
|
-
int64_t h = calc_hash(key, &len);
|
241
|
-
Slot *bucket = get_bucketp(h);
|
263
|
+
bucket_set(Slot *bucket, int64_t h, const char *key, int klen, agooPage value) {
|
242
264
|
Slot s;
|
243
265
|
agooPage old = NULL;
|
244
|
-
|
245
|
-
if (MAX_KEY_LEN <
|
266
|
+
|
267
|
+
if (MAX_KEY_LEN < klen) {
|
246
268
|
return value;
|
247
269
|
}
|
248
270
|
for (s = *bucket; NULL != s; s = s->next) {
|
249
|
-
if (h == (int64_t)s->hash &&
|
250
|
-
((0 <=
|
271
|
+
if (h == (int64_t)s->hash && klen == s->klen &&
|
272
|
+
((0 <= klen && klen <= MAX_KEY_UNIQ) || 0 == strncmp(s->key, key, klen))) {
|
251
273
|
|
252
274
|
old = s->value;
|
253
275
|
// replace
|
@@ -260,12 +282,12 @@ cache_set(const char *key, int klen, agooPage value) {
|
|
260
282
|
return value;
|
261
283
|
}
|
262
284
|
s->hash = h;
|
263
|
-
s->klen =
|
285
|
+
s->klen = klen;
|
264
286
|
if (NULL == key) {
|
265
287
|
*s->key = '\0';
|
266
288
|
} else {
|
267
|
-
strncpy(s->key, key,
|
268
|
-
s->key[
|
289
|
+
strncpy(s->key, key, klen);
|
290
|
+
s->key[klen] = '\0';
|
269
291
|
}
|
270
292
|
s->value = value;
|
271
293
|
s->next = *bucket;
|
@@ -274,10 +296,28 @@ cache_set(const char *key, int klen, agooPage value) {
|
|
274
296
|
return old;
|
275
297
|
}
|
276
298
|
|
299
|
+
static agooPage
|
300
|
+
cache_set(const char *key, int klen, agooPage value) {
|
301
|
+
int len = klen;
|
302
|
+
int64_t h = calc_hash(key, &len);
|
303
|
+
Slot *bucket = get_bucketp(h);
|
304
|
+
|
305
|
+
return bucket_set(bucket, h, key, len, value);
|
306
|
+
}
|
307
|
+
|
308
|
+
static agooPage
|
309
|
+
cache_root_set(const char *key, int klen, agooPage value) {
|
310
|
+
int len = klen;
|
311
|
+
int64_t h = calc_hash(key, &len);
|
312
|
+
Slot *bucket = get_rucketp(h);
|
313
|
+
|
314
|
+
return bucket_set(bucket, h, key, len, value);
|
315
|
+
}
|
316
|
+
|
277
317
|
int
|
278
318
|
agoo_pages_init(agooErr err) {
|
279
319
|
Mime m;
|
280
|
-
|
320
|
+
|
281
321
|
memset(&cache, 0, sizeof(struct _cache));
|
282
322
|
if (NULL == (cache.root = AGOO_STRDUP("."))) {
|
283
323
|
return agoo_err_set(err, AGOO_ERR_ARG, "out of memory allocating root path");
|
@@ -330,6 +370,14 @@ agoo_pages_cleanup() {
|
|
330
370
|
}
|
331
371
|
*sp = NULL;
|
332
372
|
}
|
373
|
+
for (sp = cache.ruckets, i = PAGE_BUCKET_SIZE; 0 < i; i--, sp++) {
|
374
|
+
for (s = *sp; NULL != s; s = n) {
|
375
|
+
n = s->next;
|
376
|
+
agoo_page_destroy(s->value);
|
377
|
+
AGOO_FREE(s);
|
378
|
+
}
|
379
|
+
*sp = NULL;
|
380
|
+
}
|
333
381
|
for (i = MIME_BUCKET_SIZE; 0 < i; i--, mp++) {
|
334
382
|
for (sm = *mp; NULL != sm; sm = m) {
|
335
383
|
m = sm->next;
|
@@ -461,10 +509,10 @@ agoo_page_immutable(agooErr err, const char *path, const char *content, int clen
|
|
461
509
|
int plen = 0;
|
462
510
|
long hlen = 0;
|
463
511
|
HeadRule hr;
|
464
|
-
|
512
|
+
|
465
513
|
if (NULL == p) {
|
466
514
|
AGOO_ERR_MEM(err, "Page");
|
467
|
-
return NULL;
|
515
|
+
return NULL;
|
468
516
|
}
|
469
517
|
if (NULL == path) {
|
470
518
|
p->path = NULL;
|
@@ -476,7 +524,7 @@ agoo_page_immutable(agooErr err, const char *path, const char *content, int clen
|
|
476
524
|
plen = (int)strlen(path);
|
477
525
|
if (NULL != cache.root) {
|
478
526
|
int rlen = strlen(cache.root);
|
479
|
-
|
527
|
+
|
480
528
|
if (0 == strncmp(cache.root, p->path, rlen) && '/' == p->path[rlen]) {
|
481
529
|
rel_path = p->path + rlen + 1;
|
482
530
|
} else {
|
@@ -509,7 +557,7 @@ agoo_page_immutable(agooErr err, const char *path, const char *content, int clen
|
|
509
557
|
}
|
510
558
|
if (0 < hlen) {
|
511
559
|
bool has_ct;
|
512
|
-
|
560
|
+
|
513
561
|
cnt = sprintf(p->resp->text, page_min_fmt, (long)clen); // HTTP/1.1 200 OK\r\nContent-Length: %ld\r\n
|
514
562
|
for (hr = cache.head_rules; NULL != hr; hr = hr->next) {
|
515
563
|
if (head_rule_match(hr, rel_path, mime)) {
|
@@ -610,7 +658,7 @@ update_contents(agooPage p) {
|
|
610
658
|
|
611
659
|
if (NULL != cache.root) {
|
612
660
|
int rlen = strlen(cache.root);
|
613
|
-
|
661
|
+
|
614
662
|
if (0 == strncmp(cache.root, path, rlen) && '/' == path[rlen]) {
|
615
663
|
rel_path = path + rlen + 1;
|
616
664
|
}
|
@@ -628,7 +676,7 @@ update_contents(agooPage p) {
|
|
628
676
|
}
|
629
677
|
if (0 < hlen) {
|
630
678
|
bool has_ct = false;
|
631
|
-
|
679
|
+
|
632
680
|
cnt = sprintf(t->text, page_min_fmt, size); // HTTP/1.1 200 OK\r\nContent-Length: %ld\r\n
|
633
681
|
for (hr = cache.head_rules; NULL != hr; hr = hr->next) {
|
634
682
|
if (head_rule_match(hr, rel_path, mime)) {
|
@@ -722,48 +770,87 @@ page_check(agooErr err, agooPage page) {
|
|
722
770
|
}
|
723
771
|
|
724
772
|
agooPage
|
725
|
-
agoo_page_get(agooErr err, const char *path, int plen) {
|
726
|
-
agooPage page;
|
773
|
+
agoo_page_get(agooErr err, const char *path, int plen, const char *root) {
|
774
|
+
agooPage page = NULL;
|
727
775
|
|
728
776
|
if (NULL != strstr(path, "../")) {
|
729
777
|
return NULL;
|
730
778
|
}
|
731
|
-
if (NULL
|
732
|
-
|
733
|
-
|
734
|
-
char full_path[2048];
|
735
|
-
char *s = stpcpy(full_path, cache.root);
|
779
|
+
if (NULL != root) {
|
780
|
+
char full_path[2048];
|
781
|
+
char *s = stpcpy(full_path, root);
|
736
782
|
|
737
|
-
|
738
|
-
|
739
|
-
|
740
|
-
|
741
|
-
|
742
|
-
|
743
|
-
|
744
|
-
|
745
|
-
s
|
746
|
-
|
747
|
-
|
748
|
-
|
749
|
-
|
750
|
-
|
751
|
-
|
752
|
-
|
753
|
-
|
754
|
-
|
755
|
-
|
756
|
-
|
783
|
+
if (NULL != strstr(path, "../")) {
|
784
|
+
return NULL;
|
785
|
+
}
|
786
|
+
if ((int)sizeof(full_path) <= plen + (s - full_path)) {
|
787
|
+
AGOO_ERR_MEM(err, "Page path");
|
788
|
+
return NULL;
|
789
|
+
}
|
790
|
+
if ('/' != *root && '/' != *(s - 1) && '/' != *path) {
|
791
|
+
*s++ = '/';
|
792
|
+
}
|
793
|
+
strncpy(s, path, plen);
|
794
|
+
s[plen] = '\0';
|
795
|
+
|
796
|
+
if (NULL == (page = cache_root_get(full_path, plen))) {
|
797
|
+
if (NULL != cache.root) {
|
798
|
+
agooPage old;
|
799
|
+
|
800
|
+
if (NULL == (page = agoo_page_create(full_path))) {
|
801
|
+
AGOO_ERR_MEM(err, "Page");
|
802
|
+
return NULL;
|
803
|
+
}
|
804
|
+
if (!update_contents(page) || NULL == page->resp) {
|
805
|
+
agoo_page_destroy(page);
|
806
|
+
agoo_err_set(err, AGOO_ERR_NOT_FOUND, "not found.");
|
807
|
+
return NULL;
|
808
|
+
}
|
809
|
+
if (NULL != (old = cache_root_set(full_path, plen, page))) {
|
810
|
+
agoo_page_destroy(old);
|
811
|
+
}
|
757
812
|
}
|
813
|
+
} else {
|
814
|
+
page = page_check(err, page);
|
758
815
|
}
|
759
816
|
} else {
|
760
|
-
page =
|
817
|
+
if (NULL == (page = cache_get(path, plen))) {
|
818
|
+
if (NULL != cache.root) {
|
819
|
+
agooPage old;
|
820
|
+
char full_path[2048];
|
821
|
+
char *s = stpcpy(full_path, cache.root);
|
822
|
+
|
823
|
+
if ('/' != *cache.root && '/' != *path) {
|
824
|
+
*s++ = '/';
|
825
|
+
}
|
826
|
+
if ((int)sizeof(full_path) <= plen + (s - full_path)) {
|
827
|
+
AGOO_ERR_MEM(err, "Page path");
|
828
|
+
return NULL;
|
829
|
+
}
|
830
|
+
strncpy(s, path, plen);
|
831
|
+
s[plen] = '\0';
|
832
|
+
if (NULL == (page = agoo_page_create(full_path))) {
|
833
|
+
AGOO_ERR_MEM(err, "Page");
|
834
|
+
return NULL;
|
835
|
+
}
|
836
|
+
if (!update_contents(page) || NULL == page->resp) {
|
837
|
+
agoo_page_destroy(page);
|
838
|
+
agoo_err_set(err, AGOO_ERR_NOT_FOUND, "not found.");
|
839
|
+
return NULL;
|
840
|
+
}
|
841
|
+
if (NULL != (old = cache_set(path, plen, page))) {
|
842
|
+
agoo_page_destroy(old);
|
843
|
+
}
|
844
|
+
}
|
845
|
+
} else {
|
846
|
+
page = page_check(err, page);
|
847
|
+
}
|
761
848
|
}
|
762
849
|
return page;
|
763
850
|
}
|
764
851
|
|
765
852
|
agooPage
|
766
|
-
|
853
|
+
agoo_group_get(agooErr err, const char *path, int plen) {
|
767
854
|
agooPage page = NULL;
|
768
855
|
agooGroup g = NULL;
|
769
856
|
char full_path[2048];
|
@@ -833,7 +920,7 @@ group_get(agooErr err, const char *path, int plen) {
|
|
833
920
|
}
|
834
921
|
|
835
922
|
agooGroup
|
836
|
-
|
923
|
+
agoo_group_create(const char *path) {
|
837
924
|
agooGroup g = (agooGroup)AGOO_MALLOC(sizeof(struct _agooGroup));
|
838
925
|
|
839
926
|
if (NULL != g) {
|
@@ -850,7 +937,7 @@ group_create(const char *path) {
|
|
850
937
|
}
|
851
938
|
|
852
939
|
agooDir
|
853
|
-
|
940
|
+
agoo_group_add(agooErr err, agooGroup g, const char *dir) {
|
854
941
|
agooDir d = (agooDir)AGOO_MALLOC(sizeof(struct _agooDir));
|
855
942
|
|
856
943
|
if (NULL != d) {
|
@@ -877,7 +964,7 @@ agoo_header_rule(agooErr err, const char *path, const char *mime, const char *ke
|
|
877
964
|
}
|
878
965
|
if (NULL == (hr->path = AGOO_STRDUP(path)) ||
|
879
966
|
NULL == (hr->key = AGOO_STRDUP(key)) ||
|
880
|
-
NULL == (hr->value = AGOO_STRDUP(value))) {
|
967
|
+
NULL == (hr->value = AGOO_STRDUP(value))) {
|
881
968
|
goto ERROR;
|
882
969
|
}
|
883
970
|
if ('*' == *mime && '\0' == mime[1]) {
|
@@ -888,7 +975,7 @@ agoo_header_rule(agooErr err, const char *path, const char *mime, const char *ke
|
|
888
975
|
hr->len = strlen(hr->key) + strlen(hr->value) + 4;
|
889
976
|
hr->next = cache.head_rules;
|
890
977
|
cache.head_rules = hr;
|
891
|
-
|
978
|
+
|
892
979
|
return AGOO_ERR_OK;
|
893
980
|
|
894
981
|
ERROR:
|