static ngx_int_t ngx_http_js_variable(ngx_http_request_t *r, ngx_http_variable_value_t *v, uintptr_t data) { ngx_str_t *fname = (ngx_str_t *) data; ngx_int_t rc; nxt_str_t name, value, exception; njs_function_t *func; ngx_http_js_ctx_t *ctx; rc = ngx_http_js_init_vm(r); if (rc == NGX_ERROR) { return NGX_ERROR; } if (rc == NGX_DECLINED) { v->not_found = 1; return NGX_OK; } ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, "http js variable call \"%V\"", fname); ctx = ngx_http_get_module_ctx(r, ngx_http_js_module); name.start = fname->data; name.length = fname->len; func = njs_vm_function(ctx->vm, &name); if (func == NULL) { ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, "js function \"%V\" not found", fname); v->not_found = 1; return NGX_OK; } if (njs_vm_call(ctx->vm, func, ctx->args, 2) != NJS_OK) { njs_vm_exception(ctx->vm, &exception); ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, "js exception: %*s", exception.length, exception.start); v->not_found = 1; return NGX_OK; } if (njs_vm_retval(ctx->vm, &value) != NJS_OK) { return NGX_ERROR; } v->len = value.length; v->valid = 1; v->no_cacheable = 0; v->not_found = 0; v->data = value.start; return NGX_OK; }
static ngx_int_t ngx_http_js_variable(ngx_http_request_t *r, ngx_http_variable_value_t *v, uintptr_t data) { njs_vm_t *vm = (njs_vm_t *) data; nxt_str_t value; njs_vm_t *nvm; ngx_pool_cleanup_t *cln; nxt_mem_cache_pool_t *mcp; ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, "http js variable handler"); mcp = ngx_http_js_create_mem_cache_pool(); if (mcp == NULL) { return NGX_ERROR; } cln = ngx_pool_cleanup_add(r->pool, 0); if (cln == NULL) { return NGX_ERROR; } cln->handler = ngx_http_js_cleanup_mem_cache_pool; cln->data = mcp; nvm = njs_vm_clone(vm, mcp, (void **) &r); if (nvm == NULL) { return NGX_ERROR; } if (njs_vm_run(nvm) == NJS_OK) { if (njs_vm_retval(nvm, &value) != NJS_OK) { return NGX_ERROR; } v->len = value.len; v->valid = 1; v->no_cacheable = 0; v->not_found = 0; v->data = value.data; } else { njs_vm_exception(nvm, &value); ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, "js exception: %*s", value.len, value.data); v->not_found = 1; } ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, "http js variable done"); return NGX_OK; }
static njs_vm_t * ngx_http_js_compile(ngx_conf_t *cf, ngx_str_t *script) { u_char *start, *end; nxt_int_t rc; nxt_str_t s; njs_vm_t *vm; nxt_lvlhsh_t externals; njs_vm_shared_t *shared; nxt_mem_cache_pool_t *mcp; mcp = ngx_http_js_create_mem_cache_pool(); if (mcp == NULL) { return NULL; } shared = NULL; nxt_lvlhsh_init(&externals); if (njs_add_external(&externals, mcp, 0, ngx_http_js_externals, nxt_nitems(ngx_http_js_externals)) != NJS_OK) { ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, "could not add js externals"); return NULL; } vm = njs_vm_create(mcp, &shared, &externals); if (vm == NULL) { return NULL; } start = script->data; end = start + script->len; rc = njs_vm_compile(vm, &start, end); if (rc != NJS_OK) { njs_vm_exception(vm, &s); ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, "js compilation error: \"%*s\"", s.len, s.data); return NULL; } if (start != end) { ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, "extra characters in js script: \"%*s\"", end - start, start); return NULL; } return vm; }
static ngx_int_t ngx_http_js_handler(ngx_http_request_t *r) { ngx_int_t rc; nxt_str_t name, exception; njs_function_t *func; ngx_http_js_ctx_t *ctx; ngx_http_js_loc_conf_t *jlcf; rc = ngx_http_js_init_vm(r); if (rc == NGX_ERROR || rc == NGX_DECLINED) { return rc; } jlcf = ngx_http_get_module_loc_conf(r, ngx_http_js_module); ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, "http js content call \"%V\"" , &jlcf->content); ctx = ngx_http_get_module_ctx(r, ngx_http_js_module); name.start = jlcf->content.data; name.length = jlcf->content.len; func = njs_vm_function(ctx->vm, &name); if (func == NULL) { ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, "js function \"%V\" not found", &jlcf->content); return NGX_DECLINED; } if (njs_vm_call(ctx->vm, func, ctx->args, 2) != NJS_OK) { njs_vm_exception(ctx->vm, &exception); ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, "js exception: %*s", exception.length, exception.start); return NGX_ERROR; } return NGX_OK; }
static ngx_int_t ngx_http_js_handler(ngx_http_request_t *r) { nxt_str_t value; njs_vm_t *nvm; ngx_pool_cleanup_t *cln; nxt_mem_cache_pool_t *mcp; ngx_http_js_loc_conf_t *jlcf; ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, "http js handler"); mcp = ngx_http_js_create_mem_cache_pool(); if (mcp == NULL) { return NGX_ERROR; } cln = ngx_pool_cleanup_add(r->pool, 0); if (cln == NULL) { return NGX_ERROR; } cln->handler = ngx_http_js_cleanup_mem_cache_pool; cln->data = mcp; jlcf = ngx_http_get_module_loc_conf(r, ngx_http_js_module); nvm = njs_vm_clone(jlcf->vm, mcp, (void **) &r); if (nvm == NULL) { return NGX_ERROR; } if (njs_vm_run(nvm) != NJS_OK) { njs_vm_exception(nvm, &value); ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, "js exception: %*s", value.len, value.data); return NGX_ERROR; } return NGX_OK; }
static char * ngx_http_js_include(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) { ngx_http_js_loc_conf_t *jlcf = conf; size_t size; u_char *start, *end; ssize_t n; ngx_fd_t fd; ngx_str_t *value, file; nxt_int_t rc; nxt_str_t text, ext, *export; nxt_lvlhsh_t externals; ngx_file_info_t fi; njs_vm_shared_t *shared; ngx_pool_cleanup_t *cln; nxt_mem_cache_pool_t *mcp; if (jlcf->vm) { return "is duplicate"; } value = cf->args->elts; file = value[1]; if (ngx_conf_full_name(cf->cycle, &file, 1) != NGX_OK) { return NGX_CONF_ERROR; } fd = ngx_open_file(file.data, NGX_FILE_RDONLY, NGX_FILE_OPEN, 0); if (fd == NGX_INVALID_FILE) { ngx_conf_log_error(NGX_LOG_EMERG, cf, ngx_errno, ngx_open_file_n " \"%s\" failed", file.data); return NGX_CONF_ERROR; } if (ngx_fd_info(fd, &fi) == NGX_FILE_ERROR) { ngx_log_error(NGX_LOG_EMERG, cf->log, ngx_errno, ngx_fd_info_n " \"%s\" failed", file.data); (void) ngx_close_file(fd); return NGX_CONF_ERROR; } size = ngx_file_size(&fi); start = ngx_pnalloc(cf->pool, size); if (start == NULL) { (void) ngx_close_file(fd); return NGX_CONF_ERROR; } n = ngx_read_fd(fd, start, size); if (n == -1) { ngx_log_error(NGX_LOG_ALERT, cf->log, ngx_errno, ngx_read_fd_n " \"%s\" failed", file.data); (void) ngx_close_file(fd); return NGX_CONF_ERROR; } if ((size_t) n != size) { ngx_log_error(NGX_LOG_ALERT, cf->log, 0, ngx_read_fd_n " has read only %z of %O from \"%s\"", n, size, file.data); (void) ngx_close_file(fd); return NGX_CONF_ERROR; } if (ngx_close_file(fd) == NGX_FILE_ERROR) { ngx_log_error(NGX_LOG_ALERT, cf->log, ngx_errno, ngx_close_file_n " %s failed", file.data); } end = start + size; mcp = ngx_http_js_create_mem_cache_pool(); if (mcp == NULL) { return NGX_CONF_ERROR; } cln = ngx_pool_cleanup_add(cf->pool, 0); if (cln == NULL) { return NULL; } cln->handler = ngx_http_js_cleanup_mem_cache_pool; cln->data = mcp; shared = NULL; nxt_lvlhsh_init(&externals); if (njs_vm_external_add(&externals, mcp, 0, ngx_http_js_externals, nxt_nitems(ngx_http_js_externals)) != NJS_OK) { ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, "could not add js externals"); return NGX_CONF_ERROR; } jlcf->vm = njs_vm_create(mcp, &shared, &externals); if (jlcf->vm == NULL) { return NGX_CONF_ERROR; } rc = njs_vm_compile(jlcf->vm, &start, end, NULL, &export); if (rc != NJS_OK) { njs_vm_exception(jlcf->vm, &text); ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, "%*s, included", text.length, text.start); return NGX_CONF_ERROR; } if (start != end) { ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, "extra characters in js script: \"%*s\", included", end - start, start); return NGX_CONF_ERROR; } ext = nxt_string_value("$r"); if (njs_vm_external(jlcf->vm, NULL, &ext, &jlcf->args[0]) != NJS_OK) { ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, "js external \"%*s\" not found", ext.length, ext.start); return NGX_CONF_ERROR; } ext = nxt_string_value("response"); rc = njs_vm_external(jlcf->vm, &jlcf->args[0], &ext, &jlcf->args[1]); if (rc != NXT_OK) { ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, "js external \"$r.%*s\" not found", ext.length, ext.start); return NGX_CONF_ERROR; } return NGX_CONF_OK; }