NJS: added http request prototype.
This commit is contained in:
273
src/nxt_http_js.c
Normal file
273
src/nxt_http_js.c
Normal file
@@ -0,0 +1,273 @@
|
||||
|
||||
/*
|
||||
* Copyright (C) NGINX, Inc.
|
||||
*/
|
||||
|
||||
#include <nxt_router.h>
|
||||
#include <nxt_http.h>
|
||||
#include <njs.h>
|
||||
|
||||
|
||||
static njs_int_t nxt_http_js_ext_uri(njs_vm_t *vm, njs_object_prop_t *prop,
|
||||
njs_value_t *value, njs_value_t *setval, njs_value_t *retval);
|
||||
static njs_int_t nxt_http_js_ext_host(njs_vm_t *vm, njs_object_prop_t *prop,
|
||||
njs_value_t *value, njs_value_t *setval, njs_value_t *retval);
|
||||
static njs_int_t nxt_http_js_ext_remote_addr(njs_vm_t *vm,
|
||||
njs_object_prop_t *prop, njs_value_t *value, njs_value_t *setval,
|
||||
njs_value_t *retval);
|
||||
static njs_int_t nxt_http_js_ext_get_arg(njs_vm_t *vm,
|
||||
njs_object_prop_t *prop, njs_value_t *value, njs_value_t *setval,
|
||||
njs_value_t *retval);
|
||||
static njs_int_t nxt_http_js_ext_get_header(njs_vm_t *vm,
|
||||
njs_object_prop_t *prop, njs_value_t *value, njs_value_t *setval,
|
||||
njs_value_t *retval);
|
||||
static njs_int_t nxt_http_js_ext_get_cookie(njs_vm_t *vm,
|
||||
njs_object_prop_t *prop, njs_value_t *value, njs_value_t *setval,
|
||||
njs_value_t *retval);
|
||||
|
||||
|
||||
static njs_external_t nxt_http_js_proto[] = {
|
||||
{
|
||||
.flags = NJS_EXTERN_PROPERTY,
|
||||
.name.string = njs_str("uri"),
|
||||
.enumerable = 1,
|
||||
.u.property = {
|
||||
.handler = nxt_http_js_ext_uri,
|
||||
}
|
||||
},
|
||||
|
||||
{
|
||||
.flags = NJS_EXTERN_PROPERTY,
|
||||
.name.string = njs_str("host"),
|
||||
.enumerable = 1,
|
||||
.u.property = {
|
||||
.handler = nxt_http_js_ext_host,
|
||||
}
|
||||
},
|
||||
|
||||
{
|
||||
.flags = NJS_EXTERN_PROPERTY,
|
||||
.name.string = njs_str("remoteAddr"),
|
||||
.enumerable = 1,
|
||||
.u.property = {
|
||||
.handler = nxt_http_js_ext_remote_addr,
|
||||
}
|
||||
},
|
||||
|
||||
{
|
||||
.flags = NJS_EXTERN_OBJECT,
|
||||
.name.string = njs_str("args"),
|
||||
.enumerable = 1,
|
||||
.u.object = {
|
||||
.enumerable = 1,
|
||||
.prop_handler = nxt_http_js_ext_get_arg,
|
||||
}
|
||||
},
|
||||
|
||||
{
|
||||
.flags = NJS_EXTERN_OBJECT,
|
||||
.name.string = njs_str("headers"),
|
||||
.enumerable = 1,
|
||||
.u.object = {
|
||||
.enumerable = 1,
|
||||
.prop_handler = nxt_http_js_ext_get_header,
|
||||
}
|
||||
},
|
||||
|
||||
{
|
||||
.flags = NJS_EXTERN_OBJECT,
|
||||
.name.string = njs_str("cookies"),
|
||||
.enumerable = 1,
|
||||
.u.object = {
|
||||
.enumerable = 1,
|
||||
.prop_handler = nxt_http_js_ext_get_cookie,
|
||||
}
|
||||
},
|
||||
};
|
||||
|
||||
|
||||
void
|
||||
nxt_http_register_js_proto(nxt_js_conf_t *jcf)
|
||||
{
|
||||
nxt_js_set_proto(jcf, nxt_http_js_proto, njs_nitems(nxt_http_js_proto));
|
||||
}
|
||||
|
||||
|
||||
static njs_int_t
|
||||
nxt_http_js_ext_uri(njs_vm_t *vm, njs_object_prop_t *prop,
|
||||
njs_value_t *value, njs_value_t *setval, njs_value_t *retval)
|
||||
{
|
||||
nxt_http_request_t *r;
|
||||
|
||||
r = njs_vm_external(vm, nxt_js_proto_id, value);
|
||||
if (r == NULL) {
|
||||
njs_value_undefined_set(retval);
|
||||
return NJS_DECLINED;
|
||||
}
|
||||
|
||||
return njs_vm_value_string_set(vm, retval, r->path->start, r->path->length);
|
||||
}
|
||||
|
||||
|
||||
static njs_int_t
|
||||
nxt_http_js_ext_host(njs_vm_t *vm, njs_object_prop_t *prop,
|
||||
njs_value_t *value, njs_value_t *setval, njs_value_t *retval)
|
||||
{
|
||||
nxt_http_request_t *r;
|
||||
|
||||
r = njs_vm_external(vm, nxt_js_proto_id, value);
|
||||
if (r == NULL) {
|
||||
njs_value_undefined_set(retval);
|
||||
return NJS_DECLINED;
|
||||
}
|
||||
|
||||
return njs_vm_value_string_set(vm, retval, r->host.start, r->host.length);
|
||||
}
|
||||
|
||||
|
||||
static njs_int_t
|
||||
nxt_http_js_ext_remote_addr(njs_vm_t *vm, njs_object_prop_t *prop,
|
||||
njs_value_t *value, njs_value_t *setval, njs_value_t *retval)
|
||||
{
|
||||
nxt_http_request_t *r;
|
||||
|
||||
r = njs_vm_external(vm, nxt_js_proto_id, value);
|
||||
if (r == NULL) {
|
||||
njs_value_undefined_set(retval);
|
||||
return NJS_DECLINED;
|
||||
}
|
||||
|
||||
return njs_vm_value_string_set(vm, retval,
|
||||
nxt_sockaddr_address(r->remote),
|
||||
r->remote->address_length);
|
||||
}
|
||||
|
||||
|
||||
static njs_int_t
|
||||
nxt_http_js_ext_get_arg(njs_vm_t *vm, njs_object_prop_t *prop,
|
||||
njs_value_t *value, njs_value_t *setval, njs_value_t *retval)
|
||||
{
|
||||
njs_int_t rc;
|
||||
njs_str_t key;
|
||||
nxt_array_t *args;
|
||||
nxt_http_request_t *r;
|
||||
nxt_http_name_value_t *nv, *start, *end;
|
||||
|
||||
r = njs_vm_external(vm, nxt_js_proto_id, value);
|
||||
if (r == NULL) {
|
||||
njs_value_undefined_set(retval);
|
||||
return NJS_DECLINED;
|
||||
}
|
||||
|
||||
rc = njs_vm_prop_name(vm, prop, &key);
|
||||
if (rc != NJS_OK) {
|
||||
njs_value_undefined_set(retval);
|
||||
return NJS_DECLINED;
|
||||
}
|
||||
|
||||
args = nxt_http_arguments_parse(r);
|
||||
if (nxt_slow_path(args == NULL)) {
|
||||
return NJS_ERROR;
|
||||
}
|
||||
|
||||
start = args->elts;
|
||||
end = start + args->nelts;
|
||||
|
||||
for (nv = start; nv < end; nv++) {
|
||||
|
||||
if (key.length == nv->name_length
|
||||
&& memcmp(key.start, nv->name, nv->name_length) == 0)
|
||||
{
|
||||
return njs_vm_value_string_set(vm, retval, nv->value,
|
||||
nv->value_length);
|
||||
}
|
||||
}
|
||||
|
||||
njs_value_undefined_set(retval);
|
||||
|
||||
return NJS_DECLINED;
|
||||
}
|
||||
|
||||
|
||||
static njs_int_t
|
||||
nxt_http_js_ext_get_header(njs_vm_t *vm, njs_object_prop_t *prop,
|
||||
njs_value_t *value, njs_value_t *setval, njs_value_t *retval)
|
||||
{
|
||||
njs_int_t rc;
|
||||
njs_str_t key;
|
||||
nxt_http_field_t *f;
|
||||
nxt_http_request_t *r;
|
||||
|
||||
r = njs_vm_external(vm, nxt_js_proto_id, value);
|
||||
if (r == NULL) {
|
||||
njs_value_undefined_set(retval);
|
||||
return NJS_DECLINED;
|
||||
}
|
||||
|
||||
rc = njs_vm_prop_name(vm, prop, &key);
|
||||
if (rc != NJS_OK) {
|
||||
njs_value_undefined_set(retval);
|
||||
return NJS_DECLINED;
|
||||
}
|
||||
|
||||
nxt_list_each(f, r->fields) {
|
||||
|
||||
if (key.length == f->name_length
|
||||
&& memcmp(key.start, f->name, f->name_length) == 0)
|
||||
{
|
||||
return njs_vm_value_string_set(vm, retval, f->value,
|
||||
f->value_length);
|
||||
}
|
||||
|
||||
} nxt_list_loop;
|
||||
|
||||
njs_value_undefined_set(retval);
|
||||
|
||||
return NJS_DECLINED;
|
||||
}
|
||||
|
||||
|
||||
static njs_int_t
|
||||
nxt_http_js_ext_get_cookie(njs_vm_t *vm, njs_object_prop_t *prop,
|
||||
njs_value_t *value, njs_value_t *setval, njs_value_t *retval)
|
||||
{
|
||||
njs_int_t rc;
|
||||
njs_str_t key;
|
||||
nxt_array_t *cookies;
|
||||
nxt_http_request_t *r;
|
||||
nxt_http_name_value_t *nv, *start, *end;
|
||||
|
||||
r = njs_vm_external(vm, nxt_js_proto_id, value);
|
||||
if (r == NULL) {
|
||||
njs_value_undefined_set(retval);
|
||||
return NJS_DECLINED;
|
||||
}
|
||||
|
||||
rc = njs_vm_prop_name(vm, prop, &key);
|
||||
if (rc != NJS_OK) {
|
||||
njs_value_undefined_set(retval);
|
||||
return NJS_DECLINED;
|
||||
}
|
||||
|
||||
cookies = nxt_http_cookies_parse(r);
|
||||
if (nxt_slow_path(cookies == NULL)) {
|
||||
return NJS_ERROR;
|
||||
}
|
||||
|
||||
start = cookies->elts;
|
||||
end = start + cookies->nelts;
|
||||
|
||||
for (nv = start; nv < end; nv++) {
|
||||
|
||||
if (key.length == nv->name_length
|
||||
&& memcmp(key.start, nv->name, nv->name_length) == 0)
|
||||
{
|
||||
return njs_vm_value_string_set(vm, retval, nv->value,
|
||||
nv->value_length);
|
||||
}
|
||||
}
|
||||
|
||||
njs_value_undefined_set(retval);
|
||||
|
||||
return NJS_DECLINED;
|
||||
}
|
||||
75
src/nxt_js.c
75
src/nxt_js.c
@@ -15,10 +15,15 @@ struct nxt_js_s {
|
||||
struct nxt_js_conf_s {
|
||||
nxt_mp_t *pool;
|
||||
njs_vm_t *vm;
|
||||
njs_uint_t protos;
|
||||
njs_external_t *proto;
|
||||
nxt_array_t *funcs;
|
||||
};
|
||||
|
||||
|
||||
njs_int_t nxt_js_proto_id;
|
||||
|
||||
|
||||
nxt_js_conf_t *
|
||||
nxt_js_conf_new(nxt_mp_t *mp)
|
||||
{
|
||||
@@ -48,6 +53,14 @@ nxt_js_conf_new(nxt_mp_t *mp)
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
nxt_js_set_proto(nxt_js_conf_t *jcf, njs_external_t *proto, njs_uint_t n)
|
||||
{
|
||||
jcf->protos = n;
|
||||
jcf->proto = proto;
|
||||
}
|
||||
|
||||
|
||||
nxt_js_t *
|
||||
nxt_js_add_tpl(nxt_js_conf_t *jcf, nxt_str_t *str, nxt_bool_t strz)
|
||||
{
|
||||
@@ -56,7 +69,8 @@ nxt_js_add_tpl(nxt_js_conf_t *jcf, nxt_str_t *str, nxt_bool_t strz)
|
||||
nxt_js_t *js;
|
||||
nxt_str_t *func;
|
||||
|
||||
static nxt_str_t func_str = nxt_string("function() {"
|
||||
static nxt_str_t func_str = nxt_string("function(uri, host, remoteAddr, "
|
||||
"args, headers, cookies) {"
|
||||
" return ");
|
||||
|
||||
/*
|
||||
@@ -140,6 +154,12 @@ nxt_js_compile(nxt_js_conf_t *jcf)
|
||||
|
||||
*p++ = ']';
|
||||
|
||||
nxt_js_proto_id = njs_vm_external_prototype(jcf->vm, jcf->proto,
|
||||
jcf->protos);
|
||||
if (nxt_slow_path(nxt_js_proto_id < 0)) {
|
||||
return NXT_ERROR;
|
||||
}
|
||||
|
||||
ret = njs_vm_compile(jcf->vm, &start, p);
|
||||
|
||||
return (ret == NJS_OK) ? NXT_OK : NXT_ERROR;
|
||||
@@ -187,7 +207,14 @@ nxt_js_call(nxt_task_t *task, nxt_js_cache_t *cache, nxt_js_t *js,
|
||||
njs_str_t res;
|
||||
njs_value_t *array, *value;
|
||||
njs_function_t *func;
|
||||
njs_opaque_value_t opaque_value;
|
||||
njs_opaque_value_t opaque_value, arguments[6];
|
||||
|
||||
static const njs_str_t uri_str = njs_str("uri");
|
||||
static const njs_str_t host_str = njs_str("host");
|
||||
static const njs_str_t remote_addr_str = njs_str("remoteAddr");
|
||||
static const njs_str_t args_str = njs_str("args");
|
||||
static const njs_str_t headers_str = njs_str("headers");
|
||||
static const njs_str_t cookies_str = njs_str("cookies");
|
||||
|
||||
vm = cache->vm;
|
||||
|
||||
@@ -211,7 +238,49 @@ nxt_js_call(nxt_task_t *task, nxt_js_cache_t *cache, nxt_js_t *js,
|
||||
value = njs_vm_array_prop(vm, &cache->array, js->index, &opaque_value);
|
||||
func = njs_value_function(value);
|
||||
|
||||
ret = njs_vm_call(vm, func, NULL, 0);
|
||||
ret = njs_vm_external_create(vm, njs_value_arg(&opaque_value),
|
||||
nxt_js_proto_id, ctx, 0);
|
||||
if (nxt_slow_path(ret != NJS_OK)) {
|
||||
return NXT_ERROR;
|
||||
}
|
||||
|
||||
value = njs_vm_object_prop(vm, njs_value_arg(&opaque_value), &uri_str,
|
||||
&arguments[0]);
|
||||
if (nxt_slow_path(value == NULL)) {
|
||||
return NXT_ERROR;
|
||||
}
|
||||
|
||||
value = njs_vm_object_prop(vm, njs_value_arg(&opaque_value), &host_str,
|
||||
&arguments[1]);
|
||||
if (nxt_slow_path(value == NULL)) {
|
||||
return NXT_ERROR;
|
||||
}
|
||||
|
||||
value = njs_vm_object_prop(vm, njs_value_arg(&opaque_value),
|
||||
&remote_addr_str, &arguments[2]);
|
||||
if (nxt_slow_path(value == NULL)) {
|
||||
return NXT_ERROR;
|
||||
}
|
||||
|
||||
value = njs_vm_object_prop(vm, njs_value_arg(&opaque_value), &args_str,
|
||||
&arguments[3]);
|
||||
if (nxt_slow_path(value == NULL)) {
|
||||
return NXT_ERROR;
|
||||
}
|
||||
|
||||
value = njs_vm_object_prop(vm, njs_value_arg(&opaque_value), &headers_str,
|
||||
&arguments[4]);
|
||||
if (nxt_slow_path(value == NULL)) {
|
||||
return NXT_ERROR;
|
||||
}
|
||||
|
||||
value = njs_vm_object_prop(vm, njs_value_arg(&opaque_value), &cookies_str,
|
||||
&arguments[5]);
|
||||
if (nxt_slow_path(value == NULL)) {
|
||||
return NXT_ERROR;
|
||||
}
|
||||
|
||||
ret = njs_vm_call(vm, func, njs_value_arg(&arguments), 6);
|
||||
|
||||
rc = njs_vm_retval_string(vm, &res);
|
||||
if (rc != NJS_OK) {
|
||||
|
||||
@@ -22,6 +22,7 @@ typedef struct {
|
||||
|
||||
|
||||
nxt_js_conf_t *nxt_js_conf_new(nxt_mp_t *mp);
|
||||
void nxt_js_set_proto(nxt_js_conf_t *jcf, njs_external_t *proto, nxt_uint_t n);
|
||||
nxt_js_t *nxt_js_add_tpl(nxt_js_conf_t *jcf, nxt_str_t *str, nxt_bool_t strz);
|
||||
nxt_int_t nxt_js_compile(nxt_js_conf_t *jcf);
|
||||
nxt_int_t nxt_js_test(nxt_js_conf_t *jcf, nxt_str_t *str, u_char *error);
|
||||
@@ -29,6 +30,9 @@ nxt_int_t nxt_js_call(nxt_task_t *task, nxt_js_cache_t *cache, nxt_js_t *js,
|
||||
nxt_str_t *str, void *ctx);
|
||||
|
||||
|
||||
extern njs_int_t nxt_js_proto_id;
|
||||
|
||||
|
||||
#endif /* NXT_HAVE_NJS */
|
||||
|
||||
#endif /* _NXT_JS_H_INCLUDED_ */
|
||||
|
||||
@@ -1065,6 +1065,10 @@ nxt_router_temp_conf(nxt_task_t *task)
|
||||
goto fail;
|
||||
}
|
||||
|
||||
#if (NXT_HAVE_NJS)
|
||||
nxt_http_register_js_proto(rtcf->tstr_state->jcf);
|
||||
#endif
|
||||
|
||||
tmp = nxt_mp_create(1024, 128, 256, 32);
|
||||
if (nxt_slow_path(tmp == NULL)) {
|
||||
goto fail;
|
||||
|
||||
@@ -138,6 +138,9 @@ void nxt_cdecl nxt_log_time_handler(nxt_uint_t level, nxt_log_t *log,
|
||||
void nxt_stream_connection_init(nxt_task_t *task, void *obj, void *data);
|
||||
|
||||
nxt_int_t nxt_http_register_variables(void);
|
||||
#if (NXT_HAVE_NJS)
|
||||
void nxt_http_register_js_proto(nxt_js_conf_t *jcf);
|
||||
#endif
|
||||
|
||||
|
||||
#define nxt_runtime_process_each(rt, process) \
|
||||
|
||||
@@ -49,6 +49,8 @@ nxt_int_t nxt_var_test(nxt_str_t *str, nxt_array_t *fields, u_char *error);
|
||||
|
||||
nxt_int_t nxt_var_interpreter(nxt_task_t *task, nxt_var_cache_t *cache,
|
||||
nxt_var_t *var, nxt_str_t *str, void *ctx, nxt_bool_t logging);
|
||||
nxt_str_t *nxt_var_get(nxt_task_t *task, nxt_var_cache_t *cache,
|
||||
nxt_str_t *name, void *ctx);
|
||||
|
||||
|
||||
#endif /* _NXT_VAR_H_INCLUDED_ */
|
||||
|
||||
Reference in New Issue
Block a user