agoo 2.6.1 → 2.7.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 +8 -0
- data/ext/agoo/agoo.c +5 -1
- data/ext/agoo/bind.c +17 -18
- data/ext/agoo/con.c +14 -7
- data/ext/agoo/debug.c +113 -63
- data/ext/agoo/debug.h +3 -0
- data/ext/agoo/err.c +7 -0
- data/ext/agoo/err.h +4 -0
- data/ext/agoo/error_stream.c +6 -0
- data/ext/agoo/gqleval.c +1 -1
- data/ext/agoo/gqlvalue.c +10 -11
- data/ext/agoo/graphql.c +181 -105
- data/ext/agoo/graphql.h +9 -0
- data/ext/agoo/hook.c +17 -7
- data/ext/agoo/log.c +8 -10
- data/ext/agoo/log.h +1 -1
- data/ext/agoo/page.c +242 -31
- data/ext/agoo/page.h +4 -3
- data/ext/agoo/queue.c +10 -7
- data/ext/agoo/queue.h +3 -2
- data/ext/agoo/ready.c +8 -7
- data/ext/agoo/rgraphql.c +29 -25
- data/ext/agoo/rlog.c +2 -2
- data/ext/agoo/rresponse.c +6 -0
- data/ext/agoo/rserver.c +49 -8
- data/ext/agoo/sdl.c +82 -35
- data/ext/agoo/sdl.h +3 -1
- data/ext/agoo/server.c +10 -6
- data/ext/agoo/server.h +2 -1
- data/ext/agoo/upgraded.c +2 -3
- data/lib/agoo/version.rb +1 -1
- data/test/static_test.rb +6 -1
- metadata +2 -2
data/ext/agoo/graphql.h
CHANGED
@@ -231,6 +231,15 @@ extern gqlArg gql_field_arg(agooErr err,
|
|
231
231
|
struct _gqlValue *def_value,
|
232
232
|
bool required);
|
233
233
|
|
234
|
+
extern gqlArg gql_input_arg(agooErr err,
|
235
|
+
gqlType input,
|
236
|
+
const char *name,
|
237
|
+
gqlType type,
|
238
|
+
const char *desc,
|
239
|
+
size_t dlen,
|
240
|
+
struct _gqlValue *def_value,
|
241
|
+
bool required);
|
242
|
+
|
234
243
|
extern gqlType gql_scalar_create(agooErr err, const char *name, const char *desc, size_t dlen);
|
235
244
|
|
236
245
|
extern gqlDir gql_directive_create(agooErr err, const char *name, const char *desc, size_t dlen);
|
data/ext/agoo/hook.c
CHANGED
@@ -17,10 +17,16 @@ agoo_hook_create(agooMethod method, const char *pattern, void *handler, agooHook
|
|
17
17
|
|
18
18
|
if (NULL == pattern) {
|
19
19
|
if (AGOO_NONE != method) {
|
20
|
-
pat = AGOO_STRDUP("")
|
20
|
+
if (NULL == (pat = AGOO_STRDUP(""))) {
|
21
|
+
AGOO_FREE(hook);
|
22
|
+
return NULL;
|
23
|
+
}
|
21
24
|
}
|
22
25
|
} else {
|
23
|
-
pat = AGOO_STRDUP(pattern)
|
26
|
+
if (NULL == (pat = AGOO_STRDUP(pattern))) {
|
27
|
+
AGOO_FREE(hook);
|
28
|
+
return NULL;
|
29
|
+
}
|
24
30
|
}
|
25
31
|
hook->pattern = pat;
|
26
32
|
hook->next = NULL;
|
@@ -42,10 +48,16 @@ agoo_hook_func_create(agooMethod method, const char *pattern, void (*func)(agooR
|
|
42
48
|
|
43
49
|
if (NULL == pattern) {
|
44
50
|
if (AGOO_NONE != method) {
|
45
|
-
pat = AGOO_STRDUP("")
|
51
|
+
if (NULL == (pat = AGOO_STRDUP(""))) {
|
52
|
+
AGOO_FREE(hook);
|
53
|
+
return NULL;
|
54
|
+
}
|
46
55
|
}
|
47
56
|
} else {
|
48
|
-
pat = AGOO_STRDUP(pattern)
|
57
|
+
if (NULL == (pat = AGOO_STRDUP(pattern))) {
|
58
|
+
AGOO_FREE(hook);
|
59
|
+
return NULL;
|
60
|
+
}
|
49
61
|
}
|
50
62
|
hook->pattern = pat;
|
51
63
|
hook->next = NULL;
|
@@ -60,9 +72,7 @@ agoo_hook_func_create(agooMethod method, const char *pattern, void (*func)(agooR
|
|
60
72
|
|
61
73
|
void
|
62
74
|
agoo_hook_destroy(agooHook hook) {
|
63
|
-
|
64
|
-
AGOO_FREE(hook->pattern);
|
65
|
-
}
|
75
|
+
AGOO_FREE(hook->pattern);
|
66
76
|
AGOO_FREE(hook);
|
67
77
|
}
|
68
78
|
|
data/ext/agoo/log.c
CHANGED
@@ -327,12 +327,8 @@ loop(void *ctx) {
|
|
327
327
|
agoo_log_rotate();
|
328
328
|
}
|
329
329
|
}
|
330
|
-
|
331
|
-
|
332
|
-
}
|
333
|
-
if (NULL != e->tidp) {
|
334
|
-
AGOO_FREE(e->tidp);
|
335
|
-
}
|
330
|
+
AGOO_FREE(e->whatp);
|
331
|
+
AGOO_FREE(e->tidp);
|
336
332
|
e->ready = false;
|
337
333
|
}
|
338
334
|
}
|
@@ -590,8 +586,8 @@ agoo_log_start(agooErr err, bool with_pid) {
|
|
590
586
|
return AGOO_ERR_OK;
|
591
587
|
}
|
592
588
|
|
593
|
-
|
594
|
-
agoo_log_init(const char *app) {
|
589
|
+
int
|
590
|
+
agoo_log_init(agooErr err, const char *app) {
|
595
591
|
time_t t = time(NULL);
|
596
592
|
struct tm *tm = localtime(&t);
|
597
593
|
int qsize = 1024;
|
@@ -615,9 +611,10 @@ agoo_log_init(const char *app) {
|
|
615
611
|
*agoo_log.day_buf = '\0';
|
616
612
|
agoo_log.thread = 0;
|
617
613
|
|
618
|
-
agoo_log.q = (agooLogEntry)
|
614
|
+
if (NULL == (agoo_log.q = (agooLogEntry)AGOO_CALLOC(qsize, sizeof(struct _agooLogEntry)))) {
|
615
|
+
return AGOO_ERR_MEM(err, "Log Queue");
|
616
|
+
}
|
619
617
|
agoo_log.end = agoo_log.q + qsize;
|
620
|
-
memset(agoo_log.q, 0, sizeof(struct _agooLogEntry) * qsize);
|
621
618
|
atomic_init(&agoo_log.head, agoo_log.q);
|
622
619
|
atomic_init(&agoo_log.tail, agoo_log.q + 1);
|
623
620
|
|
@@ -639,4 +636,5 @@ agoo_log_init(const char *app) {
|
|
639
636
|
agoo_log_cat_reg(&agoo_push_cat, "push", AGOO_INFO, AGOO_DARK_CYAN, false);
|
640
637
|
|
641
638
|
//agoo_log_start(false);
|
639
|
+
return AGOO_ERR_OK;
|
642
640
|
}
|
data/ext/agoo/log.h
CHANGED
@@ -105,7 +105,7 @@ extern struct _agooLogCat agoo_resp_cat;
|
|
105
105
|
extern struct _agooLogCat agoo_eval_cat;
|
106
106
|
extern struct _agooLogCat agoo_push_cat;
|
107
107
|
|
108
|
-
extern
|
108
|
+
extern int agoo_log_init(agooErr err, const char *app);
|
109
109
|
extern void agoo_log_open_file();
|
110
110
|
|
111
111
|
extern void agoo_log_close();
|
data/ext/agoo/page.c
CHANGED
@@ -29,6 +29,15 @@ typedef struct _slot {
|
|
29
29
|
int klen;
|
30
30
|
} *Slot;
|
31
31
|
|
32
|
+
typedef struct _headRule {
|
33
|
+
struct _headRule *next;
|
34
|
+
char *path;
|
35
|
+
char *mime;
|
36
|
+
char *key;
|
37
|
+
char *value;
|
38
|
+
int len; // length of key + value + ': ' + '\r\n'
|
39
|
+
} *HeadRule;
|
40
|
+
|
32
41
|
typedef struct _mimeSlot {
|
33
42
|
struct _mimeSlot *next;
|
34
43
|
char key[MAX_MIME_KEY_LEN + 1];
|
@@ -42,6 +51,7 @@ typedef struct _cache {
|
|
42
51
|
MimeSlot muckets[MIME_BUCKET_SIZE];
|
43
52
|
char *root;
|
44
53
|
agooGroup groups;
|
54
|
+
HeadRule head_rules;
|
45
55
|
} *Cache;
|
46
56
|
|
47
57
|
typedef struct _mime {
|
@@ -98,12 +108,14 @@ static struct _mime mime_map[] = {
|
|
98
108
|
};
|
99
109
|
|
100
110
|
static const char page_fmt[] = "HTTP/1.1 200 OK\r\nContent-Type: %s\r\nContent-Length: %ld\r\n\r\n";
|
111
|
+
static const char page_min_fmt[] = "HTTP/1.1 200 OK\r\nContent-Length: %ld\r\n";
|
101
112
|
|
102
113
|
static struct _cache cache = {
|
103
114
|
.buckets = {0},
|
104
115
|
.muckets = {0},
|
105
116
|
.root = NULL,
|
106
117
|
.groups = NULL,
|
118
|
+
.head_rules = NULL,
|
107
119
|
};
|
108
120
|
|
109
121
|
static uint64_t
|
@@ -196,12 +208,14 @@ mime_set(agooErr err, const char *key, const char *value) {
|
|
196
208
|
((0 <= len && len <= MAX_KEY_UNIQ) || 0 == strncmp(s->key, key, len))) {
|
197
209
|
|
198
210
|
AGOO_FREE(s->value);
|
199
|
-
s->value = AGOO_STRDUP(value)
|
211
|
+
if (NULL == (s->value = AGOO_STRDUP(value))) {
|
212
|
+
return agoo_err_set(err, AGOO_ERR_ARG, "out of memory adding %s", key);
|
213
|
+
}
|
200
214
|
return AGOO_ERR_OK;
|
201
215
|
}
|
202
216
|
}
|
203
217
|
if (NULL == (s = (MimeSlot)AGOO_MALLOC(sizeof(struct _mimeSlot)))) {
|
204
|
-
return
|
218
|
+
return AGOO_ERR_MEM(err, "mime key and value");
|
205
219
|
}
|
206
220
|
s->hash = h;
|
207
221
|
s->klen = len;
|
@@ -210,7 +224,10 @@ mime_set(agooErr err, const char *key, const char *value) {
|
|
210
224
|
} else {
|
211
225
|
strcpy(s->key, key);
|
212
226
|
}
|
213
|
-
s->value = AGOO_STRDUP(value)
|
227
|
+
if (NULL == (s->value = AGOO_STRDUP(value))) {
|
228
|
+
AGOO_FREE(s);
|
229
|
+
return AGOO_ERR_MEM(err, "mime key and value");
|
230
|
+
}
|
214
231
|
s->next = *bucket;
|
215
232
|
*bucket = s;
|
216
233
|
|
@@ -257,26 +274,31 @@ cache_set(const char *key, int klen, agooPage value) {
|
|
257
274
|
return old;
|
258
275
|
}
|
259
276
|
|
260
|
-
|
261
|
-
agoo_pages_init() {
|
277
|
+
int
|
278
|
+
agoo_pages_init(agooErr err) {
|
262
279
|
Mime m;
|
263
|
-
struct _agooErr err = AGOO_ERR_INIT;
|
264
280
|
|
265
281
|
memset(&cache, 0, sizeof(struct _cache));
|
266
|
-
cache.root = AGOO_STRDUP(".")
|
282
|
+
if (NULL == (cache.root = AGOO_STRDUP("."))) {
|
283
|
+
return agoo_err_set(err, AGOO_ERR_ARG, "out of memory allocating root path");
|
284
|
+
}
|
267
285
|
for (m = mime_map; NULL != m->suffix; m++) {
|
268
|
-
mime_set(
|
286
|
+
mime_set(err, m->suffix, m->type);
|
269
287
|
}
|
288
|
+
return err->code;
|
270
289
|
}
|
271
290
|
|
272
|
-
|
273
|
-
agoo_pages_set_root(const char *root) {
|
291
|
+
int
|
292
|
+
agoo_pages_set_root(agooErr err, const char *root) {
|
274
293
|
AGOO_FREE(cache.root);
|
275
294
|
if (NULL == root) {
|
276
295
|
cache.root = NULL;
|
277
296
|
} else {
|
278
|
-
cache.root = AGOO_STRDUP(root)
|
297
|
+
if (NULL == (cache.root = AGOO_STRDUP(root))) {
|
298
|
+
return agoo_err_set(err, AGOO_ERR_ARG, "out of memory allocating root path");
|
299
|
+
}
|
279
300
|
}
|
301
|
+
return AGOO_ERR_OK;
|
280
302
|
}
|
281
303
|
|
282
304
|
static void
|
@@ -297,6 +319,7 @@ agoo_pages_cleanup() {
|
|
297
319
|
MimeSlot *mp = cache.muckets;
|
298
320
|
MimeSlot sm;
|
299
321
|
MimeSlot m;
|
322
|
+
HeadRule hr;
|
300
323
|
int i;
|
301
324
|
|
302
325
|
for (i = PAGE_BUCKET_SIZE; 0 < i; i--, sp++) {
|
@@ -315,6 +338,14 @@ agoo_pages_cleanup() {
|
|
315
338
|
}
|
316
339
|
*mp = NULL;
|
317
340
|
}
|
341
|
+
while (NULL != (hr = cache.head_rules)) {
|
342
|
+
cache.head_rules = hr->next;
|
343
|
+
AGOO_FREE(hr->path);
|
344
|
+
AGOO_FREE(hr->mime);
|
345
|
+
AGOO_FREE(hr->key);
|
346
|
+
AGOO_FREE(hr->value);
|
347
|
+
AGOO_FREE(hr);
|
348
|
+
}
|
318
349
|
AGOO_FREE(cache.root);
|
319
350
|
}
|
320
351
|
|
@@ -339,6 +370,64 @@ path_mime(const char *path) {
|
|
339
370
|
return mime;
|
340
371
|
}
|
341
372
|
|
373
|
+
static const char*
|
374
|
+
path_suffix(const char *path) {
|
375
|
+
const char *suffix = path + strlen(path) - 1;
|
376
|
+
|
377
|
+
for (; '.' != *suffix; suffix--) {
|
378
|
+
if (suffix <= path) {
|
379
|
+
suffix = NULL;
|
380
|
+
break;
|
381
|
+
}
|
382
|
+
}
|
383
|
+
if (suffix <= path) {
|
384
|
+
suffix = NULL;
|
385
|
+
}
|
386
|
+
if (NULL != suffix) {
|
387
|
+
suffix++;
|
388
|
+
}
|
389
|
+
return suffix;
|
390
|
+
}
|
391
|
+
|
392
|
+
static bool
|
393
|
+
path_match(const char *pat, const char *path) {
|
394
|
+
if (NULL == pat) {
|
395
|
+
return true;
|
396
|
+
}
|
397
|
+
if (NULL == path) {
|
398
|
+
return '*' == *pat && '*' == pat[1] && '\0' == pat[2];
|
399
|
+
}
|
400
|
+
if ('/' == *path) {
|
401
|
+
path++;
|
402
|
+
}
|
403
|
+
for (; '\0' != *pat && '\0' != *path; pat++) {
|
404
|
+
if (*path == *pat) {
|
405
|
+
path++;
|
406
|
+
} else if ('*' == *pat) {
|
407
|
+
if ('*' == *(pat + 1)) {
|
408
|
+
return true;
|
409
|
+
}
|
410
|
+
for (; '\0' != *path && '/' != *path; path++) {
|
411
|
+
}
|
412
|
+
} else {
|
413
|
+
break;
|
414
|
+
}
|
415
|
+
}
|
416
|
+
return '\0' == *pat && '\0' == *path;
|
417
|
+
}
|
418
|
+
|
419
|
+
static bool
|
420
|
+
head_rule_match(HeadRule rule, const char *path, const char *mime) {
|
421
|
+
const char *suffix = NULL;
|
422
|
+
|
423
|
+
if (NULL != path) {
|
424
|
+
suffix = path_suffix(path);
|
425
|
+
}
|
426
|
+
return path_match(rule->path, path) &&
|
427
|
+
(NULL == rule->mime || 0 == strcmp(rule->mime, mime) ||
|
428
|
+
(NULL != suffix && 0 == strcmp(rule->mime, suffix)));
|
429
|
+
}
|
430
|
+
|
342
431
|
// The page resp points to the page resp msg to save memory and reduce
|
343
432
|
// allocations.
|
344
433
|
agooPage
|
@@ -350,7 +439,10 @@ agoo_page_create(const char *path) {
|
|
350
439
|
if (NULL == path) {
|
351
440
|
p->path = NULL;
|
352
441
|
} else {
|
353
|
-
p->path = AGOO_STRDUP(path)
|
442
|
+
if (NULL == (p->path = AGOO_STRDUP(path))) {
|
443
|
+
AGOO_FREE(p);
|
444
|
+
return NULL;
|
445
|
+
}
|
354
446
|
}
|
355
447
|
p->mtime = 0;
|
356
448
|
p->last_check = 0.0;
|
@@ -363,19 +455,34 @@ agooPage
|
|
363
455
|
agoo_page_immutable(agooErr err, const char *path, const char *content, int clen) {
|
364
456
|
agooPage p = (agooPage)AGOO_MALLOC(sizeof(struct _agooPage));
|
365
457
|
const char *mime = path_mime(path);
|
458
|
+
char *rel_path = NULL;
|
366
459
|
long msize;
|
367
460
|
int cnt;
|
368
461
|
int plen = 0;
|
462
|
+
long hlen = 0;
|
463
|
+
HeadRule hr;
|
369
464
|
|
370
465
|
if (NULL == p) {
|
371
|
-
|
466
|
+
AGOO_ERR_MEM(err, "Page");
|
372
467
|
return NULL;
|
373
468
|
}
|
374
469
|
if (NULL == path) {
|
375
470
|
p->path = NULL;
|
376
471
|
} else {
|
377
|
-
p->path = AGOO_STRDUP(path)
|
472
|
+
if (NULL == (p->path = AGOO_STRDUP(path))) {
|
473
|
+
AGOO_FREE(p);
|
474
|
+
return NULL;
|
475
|
+
}
|
378
476
|
plen = (int)strlen(path);
|
477
|
+
if (NULL != cache.root) {
|
478
|
+
int rlen = strlen(cache.root);
|
479
|
+
|
480
|
+
if (0 == strncmp(cache.root, p->path, rlen) && '/' == p->path[rlen]) {
|
481
|
+
rel_path = p->path + rlen + 1;
|
482
|
+
} else {
|
483
|
+
rel_path = NULL;
|
484
|
+
}
|
485
|
+
}
|
379
486
|
}
|
380
487
|
p->mtime = 0;
|
381
488
|
p->last_check = 0.0;
|
@@ -387,15 +494,40 @@ agoo_page_immutable(agooErr err, const char *path, const char *content, int clen
|
|
387
494
|
if (0 == clen) {
|
388
495
|
clen = (int)strlen(content);
|
389
496
|
}
|
497
|
+
for (hr = cache.head_rules; NULL != hr; hr = hr->next) {
|
498
|
+
if (head_rule_match(hr, rel_path, mime)) {
|
499
|
+
hlen += hr->len;
|
500
|
+
}
|
501
|
+
}
|
390
502
|
// Format size plus space for the length, the mime type, and some
|
391
503
|
// padding. Then add the content length.
|
392
504
|
msize = sizeof(page_fmt) + 60 + clen;
|
393
505
|
if (NULL == (p->resp = agoo_text_allocate((int)msize))) {
|
506
|
+
AGOO_ERR_MEM(err, "Page content");
|
394
507
|
AGOO_FREE(p);
|
395
|
-
agoo_err_set(err, AGOO_ERR_MEMORY, "Failed to allocate memory for page content.");
|
396
508
|
return NULL;
|
397
509
|
}
|
398
|
-
|
510
|
+
if (0 < hlen) {
|
511
|
+
bool has_ct;
|
512
|
+
|
513
|
+
cnt = sprintf(p->resp->text, page_min_fmt, (long)clen); // HTTP/1.1 200 OK\r\nContent-Length: %ld\r\n
|
514
|
+
for (hr = cache.head_rules; NULL != hr; hr = hr->next) {
|
515
|
+
if (head_rule_match(hr, rel_path, mime)) {
|
516
|
+
cnt += sprintf(p->resp->text + cnt, "%s: %s\r\n", hr->key, hr->value);
|
517
|
+
if (0 == strcasecmp("Content-Type", hr->key)) {
|
518
|
+
has_ct = true;
|
519
|
+
}
|
520
|
+
}
|
521
|
+
}
|
522
|
+
if (!has_ct) {
|
523
|
+
cnt += sprintf(p->resp->text + cnt, "Content-Type: %s\r\n\r\n", mime);
|
524
|
+
} else {
|
525
|
+
strcpy(p->resp->text + cnt, "\r\n");
|
526
|
+
cnt += 2;
|
527
|
+
}
|
528
|
+
} else {
|
529
|
+
cnt = sprintf(p->resp->text, page_fmt, mime, (long)clen);
|
530
|
+
}
|
399
531
|
msize = cnt + clen;
|
400
532
|
memcpy(p->resp->text + cnt, content, clen);
|
401
533
|
p->resp->text[msize] = '\0';
|
@@ -416,15 +548,21 @@ close_return_false(FILE *f) {
|
|
416
548
|
static bool
|
417
549
|
update_contents(agooPage p) {
|
418
550
|
const char *mime = path_mime(p->path);
|
551
|
+
char path[1024];
|
552
|
+
char *rel_path = NULL;
|
419
553
|
int plen = (int)strlen(p->path);
|
420
554
|
long size;
|
421
555
|
struct stat fattr;
|
422
556
|
long msize;
|
557
|
+
long hlen = 0;
|
423
558
|
int cnt;
|
424
559
|
struct stat fs;
|
425
560
|
agooText t;
|
426
561
|
FILE *f = fopen(p->path, "rb");
|
427
|
-
|
562
|
+
HeadRule hr;
|
563
|
+
|
564
|
+
strncpy(path, p->path, sizeof(path));
|
565
|
+
path[sizeof(path) - 1] = '\0';
|
428
566
|
// On linux a directory is opened by fopen (sometimes? all the time?) so
|
429
567
|
// fstat is called to get the file mode and verify it is a regular file or
|
430
568
|
// a symlink.
|
@@ -441,7 +579,6 @@ update_contents(agooPage p) {
|
|
441
579
|
if (NULL == f) {
|
442
580
|
// If not found how about with a /index.html added?
|
443
581
|
if (NULL == mime) {
|
444
|
-
char path[1024];
|
445
582
|
int cnt;
|
446
583
|
|
447
584
|
if ('/' == p->path[plen - 1]) {
|
@@ -471,13 +608,45 @@ update_contents(agooPage p) {
|
|
471
608
|
}
|
472
609
|
rewind(f);
|
473
610
|
|
611
|
+
if (NULL != cache.root) {
|
612
|
+
int rlen = strlen(cache.root);
|
613
|
+
|
614
|
+
if (0 == strncmp(cache.root, path, rlen) && '/' == path[rlen]) {
|
615
|
+
rel_path = path + rlen + 1;
|
616
|
+
}
|
617
|
+
}
|
618
|
+
for (hr = cache.head_rules; NULL != hr; hr = hr->next) {
|
619
|
+
if (head_rule_match(hr, rel_path, mime)) {
|
620
|
+
hlen += hr->len;
|
621
|
+
}
|
622
|
+
}
|
474
623
|
// Format size plus space for the length, the mime type, and some
|
475
|
-
// padding. Then add the content length.
|
476
|
-
msize = sizeof(page_fmt) + 60 + size;
|
624
|
+
// padding. Then add the header rule and content length.
|
625
|
+
msize = sizeof(page_fmt) + 60 + size + hlen;
|
477
626
|
if (NULL == (t = agoo_text_allocate((int)msize))) {
|
478
627
|
return close_return_false(f);
|
479
628
|
}
|
480
|
-
|
629
|
+
if (0 < hlen) {
|
630
|
+
bool has_ct = false;
|
631
|
+
|
632
|
+
cnt = sprintf(t->text, page_min_fmt, size); // HTTP/1.1 200 OK\r\nContent-Length: %ld\r\n
|
633
|
+
for (hr = cache.head_rules; NULL != hr; hr = hr->next) {
|
634
|
+
if (head_rule_match(hr, rel_path, mime)) {
|
635
|
+
cnt += sprintf(t->text + cnt, "%s: %s\r\n", hr->key, hr->value);
|
636
|
+
if (0 == strcasecmp("Content-Type", hr->key)) {
|
637
|
+
has_ct = true;
|
638
|
+
}
|
639
|
+
}
|
640
|
+
}
|
641
|
+
if (!has_ct) {
|
642
|
+
cnt += sprintf(t->text + cnt, "Content-Type: %s\r\n\r\n", mime);
|
643
|
+
} else {
|
644
|
+
strcpy(t->text + cnt, "\r\n");
|
645
|
+
cnt += 2;
|
646
|
+
}
|
647
|
+
} else {
|
648
|
+
cnt = sprintf(t->text, page_fmt, mime, size);
|
649
|
+
}
|
481
650
|
msize = cnt + size;
|
482
651
|
if (0 < size) {
|
483
652
|
if (size != (long)fread(t->text + cnt, 1, size, f)) {
|
@@ -569,13 +738,13 @@ agoo_page_get(agooErr err, const char *path, int plen) {
|
|
569
738
|
*s++ = '/';
|
570
739
|
}
|
571
740
|
if ((int)sizeof(full_path) <= plen + (s - full_path)) {
|
572
|
-
|
741
|
+
AGOO_ERR_MEM(err, "Page path");
|
573
742
|
return NULL;
|
574
743
|
}
|
575
744
|
strncpy(s, path, plen);
|
576
745
|
s[plen] = '\0';
|
577
746
|
if (NULL == (page = agoo_page_create(full_path))) {
|
578
|
-
|
747
|
+
AGOO_ERR_MEM(err, "Page");
|
579
748
|
return NULL;
|
580
749
|
}
|
581
750
|
if (!update_contents(page) || NULL == page->resp) {
|
@@ -646,7 +815,7 @@ group_get(agooErr err, const char *path, int plen) {
|
|
646
815
|
agooPage old;
|
647
816
|
|
648
817
|
if (NULL == (page = agoo_page_create(path))) {
|
649
|
-
|
818
|
+
AGOO_ERR_MEM(err, "Page");
|
650
819
|
return NULL;
|
651
820
|
}
|
652
821
|
if (!update_contents(page) || NULL == page->resp) {
|
@@ -668,23 +837,65 @@ group_create(const char *path) {
|
|
668
837
|
agooGroup g = (agooGroup)AGOO_MALLOC(sizeof(struct _agooGroup));
|
669
838
|
|
670
839
|
if (NULL != g) {
|
671
|
-
g->
|
672
|
-
|
673
|
-
|
840
|
+
if (NULL == (g->path = AGOO_STRDUP(path))) {
|
841
|
+
AGOO_FREE(g);
|
842
|
+
return NULL;
|
843
|
+
}
|
674
844
|
g->plen = (int)strlen(path);
|
675
845
|
g->dirs = NULL;
|
846
|
+
g->next = cache.groups;
|
847
|
+
cache.groups = g;
|
676
848
|
}
|
677
849
|
return g;
|
678
850
|
}
|
679
851
|
|
680
|
-
|
681
|
-
group_add(agooGroup g, const char *dir) {
|
852
|
+
agooDir
|
853
|
+
group_add(agooErr err, agooGroup g, const char *dir) {
|
682
854
|
agooDir d = (agooDir)AGOO_MALLOC(sizeof(struct _agooDir));
|
683
855
|
|
684
856
|
if (NULL != d) {
|
857
|
+
if (NULL == (d->path = AGOO_STRDUP(dir))) {
|
858
|
+
AGOO_ERR_MEM(err, "Group");
|
859
|
+
return NULL;
|
860
|
+
}
|
861
|
+
d->plen = (int)strlen(dir);
|
685
862
|
d->next = g->dirs;
|
686
863
|
g->dirs = d;
|
687
|
-
d->path = AGOO_STRDUP(dir);
|
688
|
-
d->plen = (int)strlen(dir);
|
689
864
|
}
|
865
|
+
return d;
|
866
|
+
}
|
867
|
+
|
868
|
+
int
|
869
|
+
agoo_header_rule(agooErr err, const char *path, const char *mime, const char *key, const char *value) {
|
870
|
+
HeadRule hr;
|
871
|
+
|
872
|
+
if (0 == strcasecmp("Content-Length", key)) {
|
873
|
+
return agoo_err_set(err, AGOO_ERR_ARG, "Can not mask Content-Length with a header rule.");
|
874
|
+
}
|
875
|
+
if (NULL == (hr = (HeadRule)AGOO_CALLOC(1, sizeof(struct _headRule)))) {
|
876
|
+
return AGOO_ERR_MEM(err, "Header Rule");
|
877
|
+
}
|
878
|
+
if (NULL == (hr->path = AGOO_STRDUP(path)) ||
|
879
|
+
NULL == (hr->key = AGOO_STRDUP(key)) ||
|
880
|
+
NULL == (hr->value = AGOO_STRDUP(value))) {
|
881
|
+
goto ERROR;
|
882
|
+
}
|
883
|
+
if ('*' == *mime && '\0' == mime[1]) {
|
884
|
+
hr->mime = NULL;
|
885
|
+
} else if (NULL == (hr->mime = AGOO_STRDUP(mime))) {
|
886
|
+
goto ERROR;
|
887
|
+
}
|
888
|
+
hr->len = strlen(hr->key) + strlen(hr->value) + 4;
|
889
|
+
hr->next = cache.head_rules;
|
890
|
+
cache.head_rules = hr;
|
891
|
+
|
892
|
+
return AGOO_ERR_OK;
|
893
|
+
|
894
|
+
ERROR:
|
895
|
+
AGOO_FREE(hr->path);
|
896
|
+
AGOO_FREE(hr->key);
|
897
|
+
AGOO_FREE(hr->value);
|
898
|
+
AGOO_FREE(hr);
|
899
|
+
|
900
|
+
return AGOO_ERR_MEM(err, "Header Rule");
|
690
901
|
}
|