agoo 2.15.14 → 2.15.15
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 +10 -0
- data/ext/agoo/con.c +0 -2
- data/ext/agoo/doc.c +3 -3
- data/ext/agoo/early_hints.c +17 -1
- data/ext/agoo/error_stream.c +17 -1
- data/ext/agoo/gqlvalue.c +1 -1
- data/ext/agoo/graphql.c +2 -2
- data/ext/agoo/http.c +1 -1
- data/ext/agoo/page.c +56 -104
- data/ext/agoo/queue.c +11 -6
- data/ext/agoo/request.c +25 -6
- data/ext/agoo/rresponse.c +17 -1
- data/ext/agoo/rserver.c +19 -1
- data/ext/agoo/rupgraded.c +17 -1
- data/ext/agoo/server.c +6 -6
- data/ext/agoo/text.c +1 -1
- data/lib/agoo/version.rb +1 -1
- data/test/base_handler_test.rb +43 -2
- data/test/static_test.rb +12 -0
- metadata +3 -3
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 4082bd93ed8668165d61bae2e0cc68d6bb4ff4c015172e281f1f4c81193e635f
|
|
4
|
+
data.tar.gz: a93f805c0d630183abd684e1c995b649f42573d41dcb01e48e68949ec520a036
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: c9c668862fd616a3579ab3164ba98a04fbdf58ac4ae86ddd7d28facfbb6e665ced1298becace7ed5047fb6b9a1a0a2a6a79b87661139f1b3fc9561e499277c76
|
|
7
|
+
data.tar.gz: 96f3f2c3c732e0bc26438185399b1aeb0494f63564678e2c2bb6ba8340c199dd8950aec1dd347bcf75513b87bbb50240efba9a858ee9684bc8a3acec396caf10
|
data/CHANGELOG.md
CHANGED
|
@@ -2,6 +2,16 @@
|
|
|
2
2
|
|
|
3
3
|
All changes to the Agoo gem are documented here. Releases follow semantic versioning.
|
|
4
4
|
|
|
5
|
+
## [2.15.15] - 2026-05-09
|
|
6
|
+
|
|
7
|
+
### Fixed
|
|
8
|
+
|
|
9
|
+
- Moved URL decoding to before page lookup invalid denial.
|
|
10
|
+
|
|
11
|
+
- Eliminated deprecated code warnings.
|
|
12
|
+
|
|
13
|
+
- Fix issue Connection string too long error.
|
|
14
|
+
|
|
5
15
|
## [2.15.14] - 2025-09-24
|
|
6
16
|
|
|
7
17
|
### Fixed
|
data/ext/agoo/con.c
CHANGED
data/ext/agoo/doc.c
CHANGED
|
@@ -13,7 +13,7 @@
|
|
|
13
13
|
#define EXP_MAX 100000
|
|
14
14
|
#define DEC_MAX 16
|
|
15
15
|
|
|
16
|
-
static char char_map[
|
|
16
|
+
static char char_map[257] = "\
|
|
17
17
|
.........ww..w..................\
|
|
18
18
|
wpq.....pp..w.p.ttttttttttp..p..\
|
|
19
19
|
pttttttttttttttttttttttttttp.p.t\
|
|
@@ -23,7 +23,7 @@ pttttttttttttttttttttttttttp.p.t\
|
|
|
23
23
|
................................\
|
|
24
24
|
................................";
|
|
25
25
|
|
|
26
|
-
static char json_map[
|
|
26
|
+
static char json_map[257] = "\
|
|
27
27
|
.........ww..w..................\
|
|
28
28
|
wpq.....pp..c.p.ttttttttttp..p..\
|
|
29
29
|
pttttttttttttttttttttttttttp.p.t\
|
|
@@ -33,7 +33,7 @@ pttttttttttttttttttttttttttp.p.t\
|
|
|
33
33
|
................................\
|
|
34
34
|
................................";
|
|
35
35
|
|
|
36
|
-
static char value_map[
|
|
36
|
+
static char value_map[257] = "\
|
|
37
37
|
.........ww..w..................\
|
|
38
38
|
wpq.....pp..ctt.ttttttttttt..p..\
|
|
39
39
|
pttttttttttttttttttttttttttp.p.t\
|
data/ext/agoo/early_hints.c
CHANGED
|
@@ -24,6 +24,22 @@ eh_free(void *ptr) {
|
|
|
24
24
|
}
|
|
25
25
|
}
|
|
26
26
|
|
|
27
|
+
static size_t
|
|
28
|
+
eh_size(const void *ptr) {
|
|
29
|
+
return sizeof(struct _earlyHints);
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
static const rb_data_type_t early_hints_type = {
|
|
33
|
+
.wrap_struct_name = "early_hints",
|
|
34
|
+
.function = {
|
|
35
|
+
.dmark = NULL,
|
|
36
|
+
.dfree = eh_free,
|
|
37
|
+
.dsize = eh_size,
|
|
38
|
+
},
|
|
39
|
+
.data = NULL,
|
|
40
|
+
.flags = RUBY_TYPED_FREE_IMMEDIATELY,
|
|
41
|
+
};
|
|
42
|
+
|
|
27
43
|
VALUE
|
|
28
44
|
agoo_early_hints_new(agooReq req) {
|
|
29
45
|
EarlyHints eh = (EarlyHints)AGOO_CALLOC(1, sizeof(struct _earlyHints));
|
|
@@ -33,7 +49,7 @@ agoo_early_hints_new(agooReq req) {
|
|
|
33
49
|
}
|
|
34
50
|
eh->req = req;
|
|
35
51
|
|
|
36
|
-
return
|
|
52
|
+
return TypedData_Wrap_Struct(eh_class, &early_hints_type, eh);
|
|
37
53
|
}
|
|
38
54
|
|
|
39
55
|
/* Document-method: call
|
data/ext/agoo/error_stream.c
CHANGED
|
@@ -22,6 +22,22 @@ es_free(void *ptr) {
|
|
|
22
22
|
}
|
|
23
23
|
}
|
|
24
24
|
|
|
25
|
+
static size_t
|
|
26
|
+
es_size(const void *ptr) {
|
|
27
|
+
return sizeof(struct _errorStream);
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
static const rb_data_type_t error_stream_type = {
|
|
31
|
+
.wrap_struct_name = "error_stream",
|
|
32
|
+
.function = {
|
|
33
|
+
.dmark = NULL,
|
|
34
|
+
.dfree = es_free,
|
|
35
|
+
.dsize = es_size,
|
|
36
|
+
},
|
|
37
|
+
.data = NULL,
|
|
38
|
+
.flags = RUBY_TYPED_FREE_IMMEDIATELY,
|
|
39
|
+
};
|
|
40
|
+
|
|
25
41
|
VALUE
|
|
26
42
|
error_stream_new(void) {
|
|
27
43
|
ErrorStream es = (ErrorStream)AGOO_MALLOC(sizeof(struct _errorStream));
|
|
@@ -32,7 +48,7 @@ error_stream_new(void) {
|
|
|
32
48
|
es->server = NULL;
|
|
33
49
|
es->text = NULL;
|
|
34
50
|
|
|
35
|
-
return
|
|
51
|
+
return TypedData_Wrap_Struct(es_class, &error_stream_type, es);
|
|
36
52
|
}
|
|
37
53
|
|
|
38
54
|
/* Document-method: puts
|
data/ext/agoo/gqlvalue.c
CHANGED
data/ext/agoo/graphql.c
CHANGED
|
@@ -24,7 +24,7 @@ typedef struct _slot {
|
|
|
24
24
|
|
|
25
25
|
static Slot buckets[BUCKET_SIZE];
|
|
26
26
|
|
|
27
|
-
static uint8_t name_chars[
|
|
27
|
+
static uint8_t name_chars[257] = "\
|
|
28
28
|
\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\
|
|
29
29
|
\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\
|
|
30
30
|
\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\
|
|
@@ -43,7 +43,7 @@ static uint8_t name_chars[256] = "\
|
|
|
43
43
|
\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\
|
|
44
44
|
";
|
|
45
45
|
|
|
46
|
-
static const char spaces[
|
|
46
|
+
static const char spaces[17] = " ";
|
|
47
47
|
|
|
48
48
|
gqlDir gql_directives = NULL;
|
|
49
49
|
|
data/ext/agoo/http.c
CHANGED
|
@@ -27,7 +27,7 @@ struct _cache key_cache;
|
|
|
27
27
|
|
|
28
28
|
// The rack spec indicates the characters (),/:;<=>?@[]{} are invalid which
|
|
29
29
|
// clearly is not consistent with RFC7230 so stick with the RFC.
|
|
30
|
-
static char header_value_chars[
|
|
30
|
+
static char header_value_chars[257] = "\
|
|
31
31
|
xxxxxxxxxxoxxxxxxxxxxxxxxxxxxxxx\
|
|
32
32
|
oooooooooooooooooooooooooooooooo\
|
|
33
33
|
oooooooooooooooooooooooooooooooo\
|
data/ext/agoo/page.c
CHANGED
|
@@ -788,114 +788,66 @@ page_check(agooErr err, agooPage page) {
|
|
|
788
788
|
agooPage
|
|
789
789
|
agoo_page_get(agooErr err, const char *path, int plen, const char *root) {
|
|
790
790
|
agooPage page = NULL;
|
|
791
|
+
char full_path[2048];
|
|
792
|
+
char *s;
|
|
791
793
|
|
|
792
|
-
if (NULL !=
|
|
794
|
+
if (NULL != root) {
|
|
795
|
+
s = stpcpy(full_path, root);
|
|
796
|
+
} else if (NULL != cache.root) {
|
|
797
|
+
s = stpcpy(full_path, cache.root);
|
|
798
|
+
} else {
|
|
799
|
+
s = full_path;
|
|
800
|
+
}
|
|
801
|
+
// This catches the accidental repeated / but not the intentional URL
|
|
802
|
+
// encoding which is detected and denied later.
|
|
803
|
+
if ('/' != *(s - 1) && '/' != *path) {
|
|
804
|
+
*s++ = '/';
|
|
805
|
+
}
|
|
806
|
+
if ((int)sizeof(full_path) <= plen + (s - full_path)) {
|
|
807
|
+
AGOO_ERR_MEM(err, "Page path");
|
|
808
|
+
return NULL;
|
|
809
|
+
}
|
|
810
|
+
if (NULL != memchr(path, '%', plen)) {
|
|
811
|
+
const char *pend = path + plen;
|
|
812
|
+
const char *pp = path;
|
|
813
|
+
|
|
814
|
+
for (; pp < pend; pp++) {
|
|
815
|
+
if ('%' != *pp) {
|
|
816
|
+
*s++ = *pp;
|
|
817
|
+
continue;
|
|
818
|
+
}
|
|
819
|
+
*s++ = parse_percent_seq(pp+1);
|
|
820
|
+
pp += 2;
|
|
821
|
+
}
|
|
822
|
+
} else {
|
|
823
|
+
strncpy(s, path, plen);
|
|
824
|
+
s += plen;
|
|
825
|
+
}
|
|
826
|
+
*s = '\0';
|
|
827
|
+
// full_path is now URL decoded.
|
|
828
|
+
if (NULL != strstr(full_path, "../") || NULL != strstr(full_path, "//")) {
|
|
793
829
|
return NULL;
|
|
794
830
|
}
|
|
795
|
-
|
|
796
|
-
|
|
797
|
-
|
|
798
|
-
|
|
799
|
-
|
|
800
|
-
|
|
801
|
-
|
|
802
|
-
|
|
803
|
-
|
|
804
|
-
|
|
805
|
-
|
|
806
|
-
|
|
807
|
-
|
|
808
|
-
|
|
809
|
-
|
|
810
|
-
|
|
811
|
-
|
|
812
|
-
|
|
813
|
-
|
|
814
|
-
for (; pp < pend; pp++) {
|
|
815
|
-
if ('%' != *pp) {
|
|
816
|
-
*s++ = *pp;
|
|
817
|
-
continue;
|
|
818
|
-
}
|
|
819
|
-
*s++ = parse_percent_seq(pp+1);
|
|
820
|
-
pp += 2;
|
|
821
|
-
}
|
|
822
|
-
} else {
|
|
823
|
-
strncpy(s, path, plen);
|
|
824
|
-
s += plen;
|
|
825
|
-
}
|
|
826
|
-
*s = '\0';
|
|
827
|
-
plen = (int)(s - full_path);
|
|
828
|
-
if (NULL == (page = cache_root_get(full_path, plen))) {
|
|
829
|
-
if (NULL != cache.root) {
|
|
830
|
-
agooPage old;
|
|
831
|
-
|
|
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_root_set(full_path, plen, page))) {
|
|
842
|
-
agoo_page_destroy(old);
|
|
843
|
-
}
|
|
844
|
-
}
|
|
845
|
-
} else {
|
|
846
|
-
page = page_check(err, page);
|
|
847
|
-
}
|
|
831
|
+
plen = (int)(s - full_path);
|
|
832
|
+
if (NULL == (page = cache_root_get(full_path, plen))) {
|
|
833
|
+
if (NULL != cache.root) {
|
|
834
|
+
agooPage old;
|
|
835
|
+
|
|
836
|
+
if (NULL == (page = agoo_page_create(full_path))) {
|
|
837
|
+
AGOO_ERR_MEM(err, "Page");
|
|
838
|
+
return NULL;
|
|
839
|
+
}
|
|
840
|
+
if (!update_contents(page) || NULL == page->resp) {
|
|
841
|
+
agoo_page_destroy(page);
|
|
842
|
+
agoo_err_set(err, AGOO_ERR_NOT_FOUND, "not found.");
|
|
843
|
+
return NULL;
|
|
844
|
+
}
|
|
845
|
+
if (NULL != (old = cache_root_set(full_path, plen, page))) {
|
|
846
|
+
agoo_page_destroy(old);
|
|
847
|
+
}
|
|
848
|
+
}
|
|
848
849
|
} else {
|
|
849
|
-
|
|
850
|
-
bool has_percent = NULL != memchr(path, '%', plen);
|
|
851
|
-
|
|
852
|
-
if (NULL != cache.root || has_percent) {
|
|
853
|
-
agooPage old;
|
|
854
|
-
char full_path[2048];
|
|
855
|
-
char *s = stpcpy(full_path, cache.root);
|
|
856
|
-
|
|
857
|
-
if ('/' != *(s - 1) && '/' != *path) {
|
|
858
|
-
*s++ = '/';
|
|
859
|
-
}
|
|
860
|
-
if ((int)sizeof(full_path) <= plen + (s - full_path)) {
|
|
861
|
-
AGOO_ERR_MEM(err, "Page path");
|
|
862
|
-
return NULL;
|
|
863
|
-
}
|
|
864
|
-
if (has_percent) {
|
|
865
|
-
const char *pend = path + plen;
|
|
866
|
-
const char *pp = path;
|
|
867
|
-
|
|
868
|
-
for (; pp < pend; pp++) {
|
|
869
|
-
if ('%' != *pp) {
|
|
870
|
-
*s++ = *pp;
|
|
871
|
-
continue;
|
|
872
|
-
}
|
|
873
|
-
*s++ = parse_percent_seq(pp+1);
|
|
874
|
-
pp += 2;
|
|
875
|
-
}
|
|
876
|
-
*s = '\0';
|
|
877
|
-
} else {
|
|
878
|
-
strncpy(s, path, plen);
|
|
879
|
-
s[plen] = '\0';
|
|
880
|
-
}
|
|
881
|
-
if (NULL == (page = agoo_page_create(full_path))) { // TBD full_path or original path?
|
|
882
|
-
AGOO_ERR_MEM(err, "Page");
|
|
883
|
-
return NULL;
|
|
884
|
-
}
|
|
885
|
-
plen = (int)strlen(full_path);
|
|
886
|
-
if (!update_contents(page) || NULL == page->resp) {
|
|
887
|
-
agoo_page_destroy(page);
|
|
888
|
-
agoo_err_set(err, AGOO_ERR_NOT_FOUND, "not found.");
|
|
889
|
-
return NULL;
|
|
890
|
-
}
|
|
891
|
-
// Cache key is the original path/plen.
|
|
892
|
-
if (NULL != (old = cache_set(path, plen, page))) {
|
|
893
|
-
agoo_page_destroy(old);
|
|
894
|
-
}
|
|
895
|
-
}
|
|
896
|
-
} else {
|
|
897
|
-
page = page_check(err, page);
|
|
898
|
-
}
|
|
850
|
+
page = page_check(err, page);
|
|
899
851
|
}
|
|
900
852
|
return page;
|
|
901
853
|
}
|
data/ext/agoo/queue.c
CHANGED
|
@@ -57,15 +57,20 @@ agoo_queue_multi_init(agooErr err, agooQueue q, size_t qsize, bool multi_push, b
|
|
|
57
57
|
|
|
58
58
|
void
|
|
59
59
|
agoo_queue_cleanup(agooQueue q) {
|
|
60
|
+
int sock = q->wsock;
|
|
61
|
+
|
|
62
|
+
q->wsock = 0;
|
|
63
|
+
if (0 < sock) {
|
|
64
|
+
close(sock);
|
|
65
|
+
}
|
|
66
|
+
sock = q->rsock;
|
|
67
|
+
q->rsock = 0;
|
|
68
|
+
if (0 < sock) {
|
|
69
|
+
close(sock);
|
|
70
|
+
}
|
|
60
71
|
AGOO_FREE(q->q);
|
|
61
72
|
q->q = NULL;
|
|
62
73
|
q->end = NULL;
|
|
63
|
-
if (0 < q->wsock) {
|
|
64
|
-
close(q->wsock);
|
|
65
|
-
}
|
|
66
|
-
if (0 < q->rsock) {
|
|
67
|
-
close(q->rsock);
|
|
68
|
-
}
|
|
69
74
|
}
|
|
70
75
|
|
|
71
76
|
void
|
data/ext/agoo/request.c
CHANGED
|
@@ -483,7 +483,6 @@ fill_headers(agooReq r, VALUE hash) {
|
|
|
483
483
|
if (NULL == r) {
|
|
484
484
|
rb_raise(rb_eArgError, "Request is no longer valid.");
|
|
485
485
|
}
|
|
486
|
-
|
|
487
486
|
for (; h < end; h++) {
|
|
488
487
|
switch (*h) {
|
|
489
488
|
case ':':
|
|
@@ -515,10 +514,12 @@ fill_headers(agooReq r, VALUE hash) {
|
|
|
515
514
|
} else if (sizeof(connection_key) - 1 == klen && 0 == strncasecmp(key, connection_key, sizeof(connection_key) - 1)) {
|
|
516
515
|
char buf[1024];
|
|
517
516
|
|
|
518
|
-
|
|
519
|
-
|
|
520
|
-
|
|
521
|
-
|
|
517
|
+
if (vend - val < (long)sizeof(buf) - 1) {
|
|
518
|
+
strncpy(buf, val, vend - val);
|
|
519
|
+
buf[sizeof(buf)-1] = '\0';
|
|
520
|
+
if (NULL != strstr(buf, upgrade_key)) {
|
|
521
|
+
upgrade = true;
|
|
522
|
+
}
|
|
522
523
|
}
|
|
523
524
|
} else if (sizeof(accept_key) - 1 == klen && 0 == strncasecmp(key, accept_key, sizeof(accept_key) - 1)) {
|
|
524
525
|
if (sizeof(event_stream_val) - 1 == vend - val &&
|
|
@@ -739,10 +740,28 @@ request_mark(void *ptr) {
|
|
|
739
740
|
}
|
|
740
741
|
}
|
|
741
742
|
|
|
743
|
+
static size_t
|
|
744
|
+
request_size(const void *ptr) {
|
|
745
|
+
agooReq r = (agooReq)ptr;
|
|
746
|
+
|
|
747
|
+
return sizeof(struct _agooReq) + r->mlen - 8;
|
|
748
|
+
}
|
|
749
|
+
|
|
750
|
+
static const rb_data_type_t request_type = {
|
|
751
|
+
.wrap_struct_name = "request",
|
|
752
|
+
.function = {
|
|
753
|
+
.dmark = request_mark,
|
|
754
|
+
.dfree = NULL,
|
|
755
|
+
.dsize = request_size,
|
|
756
|
+
},
|
|
757
|
+
.data = NULL,
|
|
758
|
+
.flags = RUBY_TYPED_FREE_IMMEDIATELY,
|
|
759
|
+
};
|
|
760
|
+
|
|
742
761
|
VALUE
|
|
743
762
|
request_wrap(agooReq req) {
|
|
744
763
|
// freed from the C side of things
|
|
745
|
-
return
|
|
764
|
+
return TypedData_Wrap_Struct(req_class, &request_type, req);
|
|
746
765
|
}
|
|
747
766
|
|
|
748
767
|
/* Document-class: Agoo::Request
|
data/ext/agoo/rresponse.c
CHANGED
|
@@ -24,6 +24,22 @@ response_free(void *ptr) {
|
|
|
24
24
|
AGOO_FREE(ptr);
|
|
25
25
|
}
|
|
26
26
|
|
|
27
|
+
static size_t
|
|
28
|
+
response_size(const void *ptr) {
|
|
29
|
+
return sizeof(struct _agooResponse);
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
static const rb_data_type_t response_type = {
|
|
33
|
+
.wrap_struct_name = "response",
|
|
34
|
+
.function = {
|
|
35
|
+
.dmark = NULL,
|
|
36
|
+
.dfree = response_free,
|
|
37
|
+
.dsize = response_size,
|
|
38
|
+
},
|
|
39
|
+
.data = NULL,
|
|
40
|
+
.flags = RUBY_TYPED_FREE_IMMEDIATELY,
|
|
41
|
+
};
|
|
42
|
+
|
|
27
43
|
VALUE
|
|
28
44
|
response_new(void) {
|
|
29
45
|
agooResponse res = (agooResponse)AGOO_MALLOC(sizeof(struct _agooResponse));
|
|
@@ -34,7 +50,7 @@ response_new(void) {
|
|
|
34
50
|
memset(res, 0, sizeof(struct _agooResponse));
|
|
35
51
|
res->code = 200;
|
|
36
52
|
|
|
37
|
-
return
|
|
53
|
+
return TypedData_Wrap_Struct(res_class, &response_type, res);
|
|
38
54
|
}
|
|
39
55
|
|
|
40
56
|
/* Document-method: to_s
|
data/ext/agoo/rserver.c
CHANGED
|
@@ -1292,6 +1292,23 @@ use(int argc, VALUE *argv, VALUE self) {
|
|
|
1292
1292
|
return Qnil;
|
|
1293
1293
|
}
|
|
1294
1294
|
|
|
1295
|
+
static size_t
|
|
1296
|
+
server_size(const void *ptr) {
|
|
1297
|
+
return sizeof(struct _agooServer);
|
|
1298
|
+
}
|
|
1299
|
+
|
|
1300
|
+
static const rb_data_type_t server_type = {
|
|
1301
|
+
.wrap_struct_name = "server",
|
|
1302
|
+
.function = {
|
|
1303
|
+
.dmark = server_mark,
|
|
1304
|
+
.dfree = NULL,
|
|
1305
|
+
.dsize = server_size,
|
|
1306
|
+
},
|
|
1307
|
+
.data = NULL,
|
|
1308
|
+
.flags = 0,
|
|
1309
|
+
};
|
|
1310
|
+
|
|
1311
|
+
|
|
1295
1312
|
/* Document-class: Agoo::Server
|
|
1296
1313
|
*
|
|
1297
1314
|
* An HTTP server that support the rack API as well as some other optimized
|
|
@@ -1335,7 +1352,8 @@ server_init(VALUE mod) {
|
|
|
1335
1352
|
|
|
1336
1353
|
push_env_key = rb_str_new_cstr("rack.upgrade"); rb_gc_register_address(&push_env_key);
|
|
1337
1354
|
|
|
1338
|
-
rserver =
|
|
1355
|
+
rserver = TypedData_Wrap_Struct(rb_cObject, &server_type, strdup("dummy"));
|
|
1356
|
+
|
|
1339
1357
|
rb_gc_register_address(&rserver);
|
|
1340
1358
|
|
|
1341
1359
|
agoo_http_init();
|
data/ext/agoo/rupgraded.c
CHANGED
|
@@ -231,6 +231,22 @@ on_destroy(agooUpgraded up) {
|
|
|
231
231
|
}
|
|
232
232
|
}
|
|
233
233
|
|
|
234
|
+
static size_t
|
|
235
|
+
upgraded_size(const void *ptr) {
|
|
236
|
+
return sizeof(struct _agooUpgraded);
|
|
237
|
+
}
|
|
238
|
+
|
|
239
|
+
static const rb_data_type_t upgraded_type = {
|
|
240
|
+
.wrap_struct_name = "upgraded",
|
|
241
|
+
.function = {
|
|
242
|
+
.dmark = NULL,
|
|
243
|
+
.dfree = NULL,
|
|
244
|
+
.dsize = upgraded_size,
|
|
245
|
+
},
|
|
246
|
+
.data = NULL,
|
|
247
|
+
.flags = 0,
|
|
248
|
+
};
|
|
249
|
+
|
|
234
250
|
agooUpgraded
|
|
235
251
|
rupgraded_create(agooCon c, VALUE obj, VALUE env) {
|
|
236
252
|
agooUpgraded up;
|
|
@@ -246,7 +262,7 @@ rupgraded_create(agooCon c, VALUE obj, VALUE env) {
|
|
|
246
262
|
up->on_error = rb_respond_to(obj, rb_intern("on_error"));
|
|
247
263
|
up->on_destroy = on_destroy;
|
|
248
264
|
|
|
249
|
-
up->wrap = (void*)
|
|
265
|
+
up->wrap = (void*)TypedData_Wrap_Struct(upgraded_class, &upgraded_type, up);
|
|
250
266
|
|
|
251
267
|
agoo_server_add_upgraded(up);
|
|
252
268
|
|
data/ext/agoo/server.c
CHANGED
|
@@ -163,12 +163,12 @@ listen_loop(void *x) {
|
|
|
163
163
|
agoo_log_cat(&agoo_con_cat, "Server with pid %d accepted connection %llu on %s [%d] from %s",
|
|
164
164
|
getpid(), (unsigned long long)cnt, b->id, con->sock, con->remote);
|
|
165
165
|
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
166
|
+
/* TBD
|
|
167
|
+
con_cnt = atomic_fetch_add(&agoo_server.con_cnt, 1);
|
|
168
|
+
if (agoo_server.loop_max > agoo_server.loop_cnt && agoo_server.loop_cnt * LOOP_UP < con_cnt) {
|
|
169
|
+
add_con_loop();
|
|
170
|
+
}
|
|
171
|
+
*/
|
|
172
172
|
agoo_queue_push(&agoo_server.con_queue, (void*)con);
|
|
173
173
|
}
|
|
174
174
|
}
|
data/ext/agoo/text.c
CHANGED
data/lib/agoo/version.rb
CHANGED
data/test/base_handler_test.rb
CHANGED
|
@@ -32,8 +32,6 @@ class BaseHandlerTest < Minitest::Test
|
|
|
32
32
|
elsif 'DELETE' == req.request_method
|
|
33
33
|
res.code = 200
|
|
34
34
|
res.body = req.body
|
|
35
|
-
|
|
36
|
-
|
|
37
35
|
end
|
|
38
36
|
end
|
|
39
37
|
end
|
|
@@ -131,6 +129,49 @@ class BaseHandlerTest < Minitest::Test
|
|
|
131
129
|
}
|
|
132
130
|
end
|
|
133
131
|
|
|
132
|
+
def test_long_connection
|
|
133
|
+
uri = URI('http://localhost:6470/tellme?a=1')
|
|
134
|
+
req = Net::HTTP::Get.new(uri)
|
|
135
|
+
# Set the headers the way we want them.
|
|
136
|
+
req['Accept-Encoding'] = '*'
|
|
137
|
+
req['Accept'] = 'application/json'
|
|
138
|
+
req['User-Agent'] = 'Ruby'
|
|
139
|
+
req['Connection'] = 'X'* 1024 # should not cause a failure
|
|
140
|
+
|
|
141
|
+
res = Net::HTTP.start(uri.hostname, uri.port) { |h|
|
|
142
|
+
h.request(req)
|
|
143
|
+
}
|
|
144
|
+
content = res.body
|
|
145
|
+
obj = Oj.load(content, mode: :strict)
|
|
146
|
+
|
|
147
|
+
expect = {
|
|
148
|
+
"HTTP_ACCEPT" => "application/json",
|
|
149
|
+
"HTTP_ACCEPT_ENCODING" => "*",
|
|
150
|
+
"HTTP_USER_AGENT" => "Ruby",
|
|
151
|
+
"PATH_INFO" => "/tellme",
|
|
152
|
+
"QUERY_STRING" => "a=1",
|
|
153
|
+
"REQUEST_METHOD" => "GET",
|
|
154
|
+
"SCRIPT_NAME" => "",
|
|
155
|
+
"SERVER_NAME" => "localhost",
|
|
156
|
+
"SERVER_PORT" => "6470",
|
|
157
|
+
"rack.errors" => nil,
|
|
158
|
+
"rack.input" => nil,
|
|
159
|
+
"rack.multiprocess" => false,
|
|
160
|
+
"rack.multithread" => false,
|
|
161
|
+
"rack.run_once" => false,
|
|
162
|
+
"rack.url_scheme" => "http",
|
|
163
|
+
"rack.version" => [1, 3],
|
|
164
|
+
"rack.logger" => nil,
|
|
165
|
+
}
|
|
166
|
+
expect.each_pair { |k,v|
|
|
167
|
+
if v.nil?
|
|
168
|
+
assert_nil(obj[k], k)
|
|
169
|
+
else
|
|
170
|
+
assert_equal(v, obj[k], k)
|
|
171
|
+
end
|
|
172
|
+
}
|
|
173
|
+
end
|
|
174
|
+
|
|
134
175
|
def test_post
|
|
135
176
|
uri = URI('http://localhost:6470/makeme')
|
|
136
177
|
req = Net::HTTP::Post.new(uri)
|
data/test/static_test.rb
CHANGED
|
@@ -124,4 +124,16 @@ class StaticTest < Minitest::Test
|
|
|
124
124
|
assert_equal("404", res.code)
|
|
125
125
|
end
|
|
126
126
|
|
|
127
|
+
def test_fetch_encoded
|
|
128
|
+
uri = URI('http://localhost:6469/%2e%2e%2ftests.sh')
|
|
129
|
+
res = Net::HTTP.get_response(uri)
|
|
130
|
+
assert_equal("404", res.code)
|
|
131
|
+
end
|
|
132
|
+
|
|
133
|
+
def test_fetch_double_slash
|
|
134
|
+
uri = URI('http://localhost:6469/%2f/nest/something.txt')
|
|
135
|
+
res = Net::HTTP.get_response(uri)
|
|
136
|
+
assert_equal("404", res.code)
|
|
137
|
+
end
|
|
138
|
+
|
|
127
139
|
end
|
metadata
CHANGED
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: agoo
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 2.15.
|
|
4
|
+
version: 2.15.15
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Peter Ohler
|
|
8
8
|
bindir: bin
|
|
9
9
|
cert_chain: []
|
|
10
|
-
date:
|
|
10
|
+
date: 2026-05-09 00:00:00.000000000 Z
|
|
11
11
|
dependencies:
|
|
12
12
|
- !ruby/object:Gem::Dependency
|
|
13
13
|
name: oj
|
|
@@ -207,7 +207,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
|
207
207
|
version: '0'
|
|
208
208
|
requirements:
|
|
209
209
|
- Linux or macOS
|
|
210
|
-
rubygems_version:
|
|
210
|
+
rubygems_version: 4.0.3
|
|
211
211
|
specification_version: 4
|
|
212
212
|
summary: An HTTP server
|
|
213
213
|
test_files:
|