Skip to content

Commit c79a12b

Browse files
authored
feat: support fetching response status (#82)
1 parent 8ffa37c commit c79a12b

File tree

5 files changed

+211
-73
lines changed

5 files changed

+211
-73
lines changed

src/http/ngx_http_wasm_api.c

Lines changed: 125 additions & 61 deletions
Original file line numberDiff line numberDiff line change
@@ -40,15 +40,25 @@ typedef struct {
4040
return NGX_ERROR; \
4141
}
4242

43-
#define PROXY_WASM_HEADER_STATIC_TABLE_ENTRIES \
44-
(sizeof(wasm_h2_header_static_table) \
43+
#define PROXY_WASM_REQ_HEADER_STATIC_TABLE_ENTRIES \
44+
(sizeof(wasm_h2_req_header_static_table) \
45+
/ sizeof(ngx_http_wasm_h2_header_t))
46+
47+
#define PROXY_WASM_RESP_HEADER_STATIC_TABLE_ENTRIES \
48+
(sizeof(wasm_h2_resp_header_static_table) \
4549
/ sizeof(ngx_http_wasm_h2_header_t))
4650

4751

4852
static ngx_str_t *ngx_http_wasm_get_path(ngx_http_request_t *r);
4953
static ngx_str_t *ngx_http_wasm_get_method(ngx_http_request_t *r);
5054
static ngx_str_t *ngx_http_wasm_get_scheme(ngx_http_request_t *r);
51-
55+
static ngx_str_t *ngx_http_wasm_get_status(ngx_http_request_t *r);
56+
static ngx_str_t *ngx_http_wasm_get_h2_header(ngx_http_request_t *r,
57+
u_char *key_data, size_t key_size, int ty);
58+
static ngx_str_t *ngx_http_wasm_get_h2_req_header(ngx_http_request_t *r,
59+
u_char *key_data, size_t key_size);
60+
static ngx_str_t *ngx_http_wasm_get_h2_resp_header(ngx_http_request_t *r,
61+
u_char *key_data, size_t key_size);
5262

5363
static int (*get_phase) (ngx_http_request_t *r, char **err);
5464
static int (*set_resp_header) (ngx_http_request_t *r,
@@ -78,11 +88,16 @@ static char *str_buf[STR_BUF_SIZE] = {0};
7888

7989
static ngx_str_t scheme_https = ngx_string("https");
8090
static ngx_str_t scheme_http = ngx_string("http");
91+
static ngx_str_t status_ok = ngx_string("200");
92+
93+
static ngx_http_wasm_h2_header_t wasm_h2_req_header_static_table[] = {
94+
{ngx_string(":path"), PROXY_WASM_REQUEST_HEADER_PATH, ngx_http_wasm_get_path},
95+
{ngx_string(":method"), PROXY_WASM_REQUEST_HEADER_METHOD, ngx_http_wasm_get_method},
96+
{ngx_string(":scheme"), PROXY_WASM_REQUEST_HEADER_SCHEME, ngx_http_wasm_get_scheme},
97+
};
8198

82-
static ngx_http_wasm_h2_header_t wasm_h2_header_static_table[] = {
83-
{ngx_string(":path"), PROXY_WASM_HEADER_PATH, ngx_http_wasm_get_path},
84-
{ngx_string(":method"), PROXY_WASM_HEADER_METHOD, ngx_http_wasm_get_method},
85-
{ngx_string(":scheme"), PROXY_WASM_HEADER_SCHEME, ngx_http_wasm_get_scheme},
99+
static ngx_http_wasm_h2_header_t wasm_h2_resp_header_static_table[] = {
100+
{ngx_string(":status"), PROXY_WASM_RESPONSE_HEADER_STATUS, ngx_http_wasm_get_status},
86101
};
87102

88103

@@ -632,6 +647,85 @@ static ngx_str_t *ngx_http_wasm_get_scheme(ngx_http_request_t *r)
632647
}
633648

634649

650+
static ngx_str_t *
651+
ngx_http_wasm_get_status(ngx_http_request_t *r)
652+
{
653+
ngx_str_t *sc;
654+
ngx_uint_t status;
655+
u_char *p;
656+
657+
if (r->err_status) {
658+
status = r->err_status;
659+
} else {
660+
status = r->headers_out.status;
661+
}
662+
663+
sc = &status_ok;
664+
665+
p = ngx_http_wasm_get_string_buf(r->pool, sizeof(u_char));
666+
if (p == NULL) {
667+
return NULL;
668+
}
669+
670+
sc->len = ngx_sprintf(p, "%ui", status) - p;
671+
sc->data = p;
672+
673+
return sc;
674+
}
675+
676+
677+
static ngx_str_t *
678+
ngx_http_wasm_get_h2_header(ngx_http_request_t *r, u_char *key_data, size_t key_size, int ty) {
679+
ngx_str_t *h = NULL;
680+
ngx_uint_t i, entries;
681+
ngx_http_wasm_h2_header_t *wh, *whs;
682+
683+
if (ty == PROXY_WASM_REQUEST_HEADER) {
684+
entries = (ngx_uint_t) PROXY_WASM_REQ_HEADER_STATIC_TABLE_ENTRIES;
685+
whs = &wasm_h2_req_header_static_table[0];
686+
687+
} else if (ty == PROXY_WASM_RESPONSE_HEADER) {
688+
entries = (ngx_uint_t) PROXY_WASM_RESP_HEADER_STATIC_TABLE_ENTRIES;
689+
whs = &wasm_h2_resp_header_static_table[0];
690+
691+
} else {
692+
return NULL;
693+
}
694+
695+
696+
if (key_size <= 0 || key_data[0] != ':') {
697+
return NULL;
698+
}
699+
700+
for (i = 0; i < entries; i++) {
701+
wh = whs + i;
702+
703+
if ((size_t) key_size != wh->name.len) {
704+
continue;
705+
}
706+
707+
if (ngx_strncasecmp(key_data, wh->name.data, wh->name.len) == 0) {
708+
h = wh->getter(r);
709+
break;
710+
}
711+
}
712+
713+
return h;
714+
}
715+
716+
717+
static ngx_str_t *
718+
ngx_http_wasm_get_h2_req_header(ngx_http_request_t *r, u_char *key_data, size_t key_size) {
719+
return ngx_http_wasm_get_h2_header(r, key_data, key_size, PROXY_WASM_REQUEST_HEADER);
720+
}
721+
722+
723+
static ngx_str_t *
724+
ngx_http_wasm_get_h2_resp_header(ngx_http_request_t *r, u_char *key_data, size_t key_size) {
725+
return ngx_http_wasm_get_h2_header(r, key_data, key_size, PROXY_WASM_RESPONSE_HEADER);
726+
}
727+
728+
635729
static int32_t
636730
ngx_http_wasm_req_get_headers(ngx_http_request_t *r, int32_t addr, int32_t size_addr)
637731
{
@@ -644,6 +738,8 @@ ngx_http_wasm_req_get_headers(ngx_http_request_t *r, int32_t addr, int32_t size_
644738
proxy_wasm_map_iter it;
645739
char *key;
646740
char *val;
741+
ngx_str_t *s;
742+
ngx_http_wasm_h2_header_t *wh;
647743

648744
log = r->connection->log;
649745

@@ -674,23 +770,20 @@ ngx_http_wasm_req_get_headers(ngx_http_request_t *r, int32_t addr, int32_t size_
674770
}
675771

676772
/* count pseudo headers :path, :method, :scheme */
677-
for (i = 0; i < (ngx_int_t) PROXY_WASM_HEADER_STATIC_TABLE_ENTRIES; i++) {
678-
ngx_str_t *s;
679-
ngx_http_wasm_h2_header_t *wh;
680-
681-
wh = &wasm_h2_header_static_table[i];
773+
for (i = 0; i < (ngx_int_t) PROXY_WASM_REQ_HEADER_STATIC_TABLE_ENTRIES; i++) {
774+
wh = &wasm_h2_req_header_static_table[i];
682775
s = wh->getter(r);
683776
size += wh->name.len + 1 + s->len + 1;
684777
}
685778

686-
size += 4 + (count + PROXY_WASM_HEADER_STATIC_TABLE_ENTRIES) * 2 * 4;
779+
size += 4 + (count + PROXY_WASM_REQ_HEADER_STATIC_TABLE_ENTRIES) * 2 * 4;
687780
buf = ngx_http_wasm_get_buf_to_write(log, size, addr, size_addr);
688781
if (buf == NULL) {
689782
return PROXY_RESULT_INVALID_MEMORY_ACCESS;
690783
}
691784

692785
/* get the data */
693-
proxy_wasm_map_init_map(buf, count + PROXY_WASM_HEADER_STATIC_TABLE_ENTRIES);
786+
proxy_wasm_map_init_map(buf, count + PROXY_WASM_REQ_HEADER_STATIC_TABLE_ENTRIES);
694787
proxy_wasm_map_init_iter(&it, buf);
695788

696789
for (i = 0; i < count; i++) {
@@ -706,11 +799,8 @@ ngx_http_wasm_req_get_headers(ngx_http_request_t *r, int32_t addr, int32_t size_
706799
}
707800

708801
/* get pseudo headers :path, :method, :scheme */
709-
for (i = 0; i < (ngx_int_t) PROXY_WASM_HEADER_STATIC_TABLE_ENTRIES; i++) {
710-
ngx_str_t *s;
711-
ngx_http_wasm_h2_header_t *wh;
712-
713-
wh = &wasm_h2_header_static_table[i];
802+
for (i = 0; i < (ngx_int_t) PROXY_WASM_REQ_HEADER_STATIC_TABLE_ENTRIES; i++) {
803+
wh = &wasm_h2_req_header_static_table[i];
714804
s = wh->getter(r);
715805

716806
proxy_wasm_map_reserve(&it, &key, wh->name.len,
@@ -961,9 +1051,9 @@ ngx_http_wasm_req_get_header(ngx_http_request_t *r, char *key, int32_t key_size
9611051
{
9621052
ngx_log_t *log;
9631053
ngx_uint_t i;
1054+
ngx_str_t *h2h;
9641055
ngx_list_part_t *part;
9651056
ngx_table_elt_t *header;
966-
ngx_http_wasm_h2_header_t *wh;
9671057
unsigned char *key_buf = NULL;
9681058
const u_char *val = NULL;
9691059
int32_t val_len = 0;
@@ -973,46 +1063,11 @@ ngx_http_wasm_req_get_header(ngx_http_request_t *r, char *key, int32_t key_size
9731063
header = part->elts;
9741064
key_buf = (u_char *) key;
9751065

976-
if (key_size > 0 && key_buf[0] == ':') {
977-
for (i = 0; i < PROXY_WASM_HEADER_STATIC_TABLE_ENTRIES; i++) {
978-
wh = &wasm_h2_header_static_table[i];
979-
980-
if ((size_t) key_size != wh->name.len) {
981-
continue;
982-
}
983-
984-
if (ngx_strncasecmp(key_buf, wh->name.data, wh->name.len) == 0) {
985-
986-
switch (wh->ty) {
987-
case PROXY_WASM_HEADER_PATH:
988-
val = r->unparsed_uri.data;
989-
val_len = r->unparsed_uri.len;
990-
break;
991-
992-
case PROXY_WASM_HEADER_METHOD:
993-
val = r->method_name.data;
994-
val_len = r->method_name.len;
995-
break;
996-
997-
case PROXY_WASM_HEADER_SCHEME:
998-
if (r->connection->ssl) {
999-
val = scheme_https.data;
1000-
val_len = scheme_https.len;
1001-
} else {
1002-
val = scheme_http.data;
1003-
val_len = scheme_http.len;
1004-
}
1005-
break;
1006-
1007-
default:
1008-
break;
1009-
}
1010-
1011-
if (val != NULL) {
1012-
goto done;
1013-
}
1014-
}
1015-
}
1066+
h2h = ngx_http_wasm_get_h2_req_header(r, key_buf, key_size);
1067+
if (h2h) {
1068+
val = h2h->data;
1069+
val_len = h2h->len;
1070+
goto done;
10161071
}
10171072

10181073
for (i = 0; /* void */ ; i++) {
@@ -1060,7 +1115,7 @@ ngx_http_wasm_resp_get_header(ngx_http_request_t *r, char *key, int32_t key_siz
10601115
char *errmsg = NULL;
10611116
ngx_log_t *log;
10621117
unsigned char *key_buf;
1063-
ngx_str_t *values;
1118+
ngx_str_t *values, *h2h;
10641119

10651120

10661121
log = r->connection->log;
@@ -1071,6 +1126,13 @@ ngx_http_wasm_resp_get_header(ngx_http_request_t *r, char *key, int32_t key_siz
10711126
}
10721127

10731128
values = (ngx_str_t *) (key_buf + key_size);
1129+
1130+
h2h = ngx_http_wasm_get_h2_resp_header(r, (u_char *) key, key_size);
1131+
if (h2h) {
1132+
values = h2h;
1133+
goto done;
1134+
}
1135+
10741136
rc = get_resp_header(r, (unsigned char *) key, key_size, key_buf, values, 1, &errmsg);
10751137
if (rc < 0) {
10761138
if (rc == FFI_BAD_CONTEXT) {
@@ -1090,6 +1152,8 @@ ngx_http_wasm_resp_get_header(ngx_http_request_t *r, char *key, int32_t key_siz
10901152
return PROXY_RESULT_NOT_FOUND;
10911153
}
10921154

1155+
done:
1156+
10931157
return ngx_http_wasm_copy_to_wasm(log, values->data, values->len, addr, size);
10941158
}
10951159

src/http/ngx_http_wasm_call.c

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -20,10 +20,10 @@ typedef struct {
2020

2121

2222
static proxy_wasm_h2_header_t proxy_wasm_h2_headers[] = {
23-
{ngx_string(":path"), PROXY_WASM_HEADER_PATH},
24-
{ngx_string(":method"), PROXY_WASM_HEADER_METHOD},
25-
{ngx_string(":scheme"), PROXY_WASM_HEADER_SCHEME},
26-
{ngx_string(":authority"), PROXY_WASM_HEADER_AUTHORITY},
23+
{ngx_string(":path"), PROXY_WASM_REQUEST_HEADER_PATH},
24+
{ngx_string(":method"), PROXY_WASM_REQUEST_HEADER_METHOD},
25+
{ngx_string(":scheme"), PROXY_WASM_REQUEST_HEADER_SCHEME},
26+
{ngx_string(":authority"), PROXY_WASM_REQUEST_HEADER_AUTHORITY},
2727
{ngx_null_string, 0 }
2828
};
2929

@@ -132,22 +132,22 @@ ngx_http_wasm_call_get(ngx_http_request_t *r, ngx_str_t *method, ngx_str_t *sche
132132
if (ngx_strncasecmp((u_char *) key, wh->name.data, wh->name.len) == 0) {
133133

134134
switch (wh->ty) {
135-
case PROXY_WASM_HEADER_PATH:
135+
case PROXY_WASM_REQUEST_HEADER_PATH:
136136
path->data = (u_char *) val;
137137
path->len = val_len;
138138
goto next;
139139

140-
case PROXY_WASM_HEADER_METHOD:
140+
case PROXY_WASM_REQUEST_HEADER_METHOD:
141141
method->data = (u_char *) val;
142142
method->len = val_len;
143143
goto next;
144144

145-
case PROXY_WASM_HEADER_SCHEME:
145+
case PROXY_WASM_REQUEST_HEADER_SCHEME:
146146
scheme->data = (u_char *) val;
147147
scheme->len = val_len;
148148
goto next;
149149

150-
case PROXY_WASM_HEADER_AUTHORITY:
150+
case PROXY_WASM_REQUEST_HEADER_AUTHORITY:
151151
headers->key.data = (u_char *) "host";
152152
headers->key.len = 4;
153153
headers->value.data = (u_char *) val;

src/proxy_wasm/proxy_wasm_types.h

Lines changed: 15 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -65,10 +65,21 @@ typedef enum {
6565

6666

6767
enum {
68-
PROXY_WASM_HEADER_PATH = 1,
69-
PROXY_WASM_HEADER_METHOD,
70-
PROXY_WASM_HEADER_SCHEME,
71-
PROXY_WASM_HEADER_AUTHORITY,
68+
PROXY_WASM_REQUEST_HEADER = 1,
69+
PROXY_WASM_RESPONSE_HEADER,
70+
};
71+
72+
73+
enum {
74+
PROXY_WASM_REQUEST_HEADER_PATH = 1,
75+
PROXY_WASM_REQUEST_HEADER_METHOD,
76+
PROXY_WASM_REQUEST_HEADER_SCHEME,
77+
PROXY_WASM_REQUEST_HEADER_AUTHORITY,
78+
};
79+
80+
81+
enum {
82+
PROXY_WASM_RESPONSE_HEADER_STATUS = 1,
7283
};
7384

7485

0 commit comments

Comments
 (0)