Skip to content

feature: Re-implement ngx_lua's ngx.decode_args API function with FFI #1108

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
wants to merge 1 commit into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
154 changes: 46 additions & 108 deletions src/ngx_http_lua_args.c
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@


#include "ngx_http_lua_args.h"
#include "ngx_http_lua_string.h"
#include "ngx_http_lua_util.h"


Expand Down Expand Up @@ -387,23 +388,16 @@ ngx_http_lua_ffi_req_get_querystring_len(ngx_http_request_t *r)


int
ngx_http_lua_ffi_req_get_uri_args_count(ngx_http_request_t *r, int max)
ngx_http_lua_ffi_get_args_count_helper(u_char *args,
size_t len, int max, int *hit)
{
int count;
u_char *p, *last;

if (r->connection->fd == (ngx_socket_t) -1) {
return NGX_HTTP_LUA_FFI_BAD_CONTEXT;
}
int count;
u_char *p, *last;

if (max < 0) {
max = NGX_HTTP_LUA_MAX_ARGS;
}

last = r->args.data + r->args.len;
last = args + len;
count = 0;

for (p = r->args.data; p != last; p++) {
for (p = args; p != last; p++) {
if (*p == '&') {
if (count == 0) {
count += 2;
Expand All @@ -417,14 +411,13 @@ ngx_http_lua_ffi_req_get_uri_args_count(ngx_http_request_t *r, int max)
if (count) {
if (max > 0 && count > max) {
count = max;
ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
"lua hit query args limit %d", max);
*hit = 1;
}

return count;
}

if (r->args.len) {
if (len) {
return 1;
}

Expand All @@ -433,117 +426,62 @@ ngx_http_lua_ffi_req_get_uri_args_count(ngx_http_request_t *r, int max)


int
ngx_http_lua_ffi_req_get_uri_args(ngx_http_request_t *r, u_char *buf,
ngx_http_lua_ffi_table_elt_t *out, int count)
ngx_http_lua_ffi_req_get_uri_args_count(ngx_http_request_t *r, int max)
{
int i, parsing_value = 0;
u_char *last, *p, *q;
u_char *src, *dst;
int rc, hit = 0;

if (count <= 0) {
return NGX_OK;
if (r->connection->fd == (ngx_socket_t) -1) {
return NGX_HTTP_LUA_FFI_BAD_CONTEXT;
}

ngx_memcpy(buf, r->args.data, r->args.len);

i = 0;
last = buf + r->args.len;
p = buf;
q = p;

while (p != last) {
if (*p == '=' && !parsing_value) {
/* key data is between p and q */

src = q; dst = q;

ngx_http_lua_unescape_uri(&dst, &src, p - q,
NGX_UNESCAPE_URI_COMPONENT);

dd("saving key %.*s", (int) (dst - q), q);

out[i].key.data = q;
out[i].key.len = (int) (dst - q);

/* skip the current '=' char */
p++;

q = p;
parsing_value = 1;

} else if (*p == '&') {
/* reached the end of a key or a value, just save it */
src = q; dst = q;

ngx_http_lua_unescape_uri(&dst, &src, p - q,
NGX_UNESCAPE_URI_COMPONENT);
if (max < 0) {
max = NGX_HTTP_LUA_MAX_ARGS;
}

dd("pushing key or value %.*s", (int) (dst - q), q);
rc = ngx_http_lua_ffi_get_args_count_helper(r->args.data,
r->args.len,
max, &hit);

if (parsing_value) {
/* end of the current pair's value */
parsing_value = 0;
if (hit) {
ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
"lua hit query args limit %d", max);
}

if (out[i].key.len) {
out[i].value.data = q;
out[i].value.len = (int) (dst - q);
i++;
}
return rc;
}

} else {
/* the current parsing pair takes no value,
* just push the value "true" */
dd("pushing boolean true");

if (dst - q) {
out[i].key.data = q;
out[i].key.len = (int) (dst - q);
out[i].value.len = -1;
i++;
}
}
int
ngx_http_lua_ffi_req_get_uri_args(ngx_http_request_t *r, u_char *buf,
ngx_http_lua_ffi_table_elt_t *out, int count)
{
ngx_memcpy(buf, r->args.data, r->args.len);

if (i == count) {
return i;
}
return ngx_http_lua_ffi_decode_args_helper(buf, r->args.len, out, count);
}

/* skip the current '&' char */
p++;

q = p;
int
ngx_http_lua_ffi_get_args_count(const u_char *args, size_t len, int max)
{
int rc, hit = 0;

} else {
p++;
}
if (max < 0) {
max = NGX_HTTP_LUA_MAX_ARGS;
}

if (p != q || parsing_value) {
src = q; dst = q;

ngx_http_lua_unescape_uri(&dst, &src, p - q,
NGX_UNESCAPE_URI_COMPONENT);

dd("pushing key or value %.*s", (int) (dst - q), q);

if (parsing_value) {
if (out[i].key.len) {
out[i].value.data = q;
out[i].value.len = (int) (dst - q);
i++;
}
rc = ngx_http_lua_ffi_get_args_count_helper((u_char *) args,
len, max, &hit);

} else {
if (dst - q) {
out[i].key.data = q;
out[i].key.len = (int) (dst - q);
out[i].value.len = (int) -1;
i++;
}
}
if (hit) {
ngx_log_debug1(NGX_LOG_DEBUG_HTTP, ngx_cycle->log, 0,
"lua hit query args limit %d", max);
}

return i;
return rc;
}


#endif /* NGX_LUA_NO_FFI_API */


Expand Down
126 changes: 125 additions & 1 deletion src/ngx_http_lua_string.c
Original file line number Diff line number Diff line change
Expand Up @@ -762,6 +762,130 @@ ngx_http_lua_ffi_escape_uri(const u_char *src, size_t len, u_char *dst)
ngx_http_lua_escape_uri(dst, (u_char *) src, len, NGX_ESCAPE_URI_COMPONENT);
}

#endif

int
ngx_http_lua_ffi_decode_args_helper(u_char *args, size_t len,
ngx_http_lua_ffi_table_elt_t *out, int count)
{
int i, parsing_value = 0;
u_char *last, *p, *q;
u_char *src, *dst;

if (count <= 0) {
return NGX_OK;
}

i = 0;
p = args;
q = p;
last = args + len;

while (p != last) {
if (*p == '=' && !parsing_value) {
/* key data is between p and q */

src = q; dst = q;

ngx_http_lua_unescape_uri(&dst, &src, p - q,
NGX_UNESCAPE_URI_COMPONENT);

dd("saving key %.*s", (int) (dst - q), q);

out[i].key.data = q;
out[i].key.len = (int) (dst - q);

/* skip the current '=' char */
p++;

q = p;
parsing_value = 1;

} else if (*p == '&') {
/* reached the end of a key or a value, just save it */
src = q; dst = q;

ngx_http_lua_unescape_uri(&dst, &src, p - q,
NGX_UNESCAPE_URI_COMPONENT);

dd("pushing key or value %.*s", (int) (dst - q), q);

if (parsing_value) {
/* end of the current pair's value */
parsing_value = 0;

if (out[i].key.len) {
out[i].value.data = q;
out[i].value.len = (int) (dst - q);
i++;
}

} else {
/* the current parsing pair takes no value,
* just push the value "true" */
dd("pushing boolean true");

if (dst - q) {
out[i].key.data = q;
out[i].key.len = (int) (dst - q);
out[i].value.len = -1;
i++;
}
}

if (i == count) {
return i;
}

/* skip the current '&' char */
p++;

q = p;

} else {
p++;
}
}

if (p != q || parsing_value) {
src = q; dst = q;

ngx_http_lua_unescape_uri(&dst, &src, p - q,
NGX_UNESCAPE_URI_COMPONENT);

dd("pushing key or value %.*s", (int) (dst - q), q);

if (parsing_value) {
if (out[i].key.len) {
out[i].value.data = q;
out[i].value.len = (int) (dst - q);
i++;
}

} else {
if (dst - q) {
out[i].key.data = q;
out[i].key.len = (int) (dst - q);
out[i].value.len = (int) -1;
i++;
}
}
}

return i;
}


int
ngx_http_lua_ffi_decode_args(u_char *buf, const u_char *args, size_t len,
ngx_http_lua_ffi_table_elt_t *out, int count)
{
ngx_memcpy(buf, args, len);

return ngx_http_lua_ffi_decode_args_helper(buf, len, out, count);
}


#endif /* NGX_LUA_NO_FFI_API */


/* vi:set ft=c ts=4 sw=4 et fdm=marker: */
9 changes: 9 additions & 0 deletions src/ngx_http_lua_string.h
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,15 @@
void ngx_http_lua_inject_string_api(lua_State *L);


#ifndef NGX_LUA_NO_FFI_API
#include "ngx_http_lua_util.h"

int ngx_http_lua_ffi_decode_args_helper(u_char *args, size_t len,
ngx_http_lua_ffi_table_elt_t *out, int count);
#endif


#endif /* _NGX_HTTP_LUA_STRING_H_INCLUDED_ */


/* vi:set ft=c ts=4 sw=4 et fdm=marker: */