From xeioex at nginx.com Fri Oct 2 12:20:30 2020 From: xeioex at nginx.com (Dmitry Volyntsev) Date: Fri, 02 Oct 2020 12:20:30 +0000 Subject: [njs] Version bump. Message-ID: details: https://hg.nginx.org/njs/rev/2065b127bd90 branches: changeset: 1533:2065b127bd90 user: Dmitry Volyntsev date: Fri Oct 02 12:18:41 2020 +0000 description: Version bump. diffstat: src/njs.h | 2 +- 1 files changed, 1 insertions(+), 1 deletions(-) diffs (12 lines): diff -r e0c26ff9bd97 -r 2065b127bd90 src/njs.h --- a/src/njs.h Tue Sep 29 13:32:37 2020 +0000 +++ b/src/njs.h Fri Oct 02 12:18:41 2020 +0000 @@ -11,7 +11,7 @@ #include -#define NJS_VERSION "0.4.4" +#define NJS_VERSION "0.5.0" #include /* STDOUT_FILENO, STDERR_FILENO */ From xeioex at nginx.com Fri Oct 2 12:20:32 2020 From: xeioex at nginx.com (Dmitry Volyntsev) Date: Fri, 02 Oct 2020 12:20:32 +0000 Subject: [njs] Improved working with the path argument in "fs" module. Message-ID: details: https://hg.nginx.org/njs/rev/f6bf6357ab6b branches: changeset: 1534:f6bf6357ab6b user: Dmitry Volyntsev date: Fri Oct 02 12:18:44 2020 +0000 description: Improved working with the path argument in "fs" module. diffstat: src/njs_fs.c | 318 +++++++++++++++++++++------------------------- src/njs_string.c | 13 + src/njs_string.h | 2 + src/njs_unix.h | 6 + test/njs_expect_test.exp | 6 + 5 files changed, 170 insertions(+), 175 deletions(-) diffs (720 lines): diff -r 2065b127bd90 -r f6bf6357ab6b src/njs_fs.c --- a/src/njs_fs.c Fri Oct 02 12:18:41 2020 +0000 +++ b/src/njs_fs.c Fri Oct 02 12:18:44 2020 +0000 @@ -81,20 +81,20 @@ typedef njs_int_t (*njs_file_tree_walk_c static njs_int_t njs_fs_fd_read(njs_vm_t *vm, int fd, njs_str_t *data); static njs_int_t njs_fs_error(njs_vm_t *vm, const char *syscall, - const char *desc, njs_value_t *path, int errn, njs_value_t *retval); + const char *desc, const char *path, int errn, njs_value_t *retval); static njs_int_t njs_fs_result(njs_vm_t *vm, njs_value_t *result, njs_index_t calltype, const njs_value_t* callback, njs_uint_t nargs); static njs_int_t njs_file_tree_walk(const char *path, njs_file_tree_walk_cb_t cb, int fd_limit, njs_ftw_flags_t flags); -static njs_int_t njs_fs_make_path(njs_vm_t *vm, const char *path, mode_t md, +static njs_int_t njs_fs_make_path(njs_vm_t *vm, char *path, mode_t md, njs_bool_t recursive, njs_value_t *retval); static njs_int_t njs_fs_rmtree(njs_vm_t *vm, const char *path, njs_bool_t recursive, njs_value_t *retval); -static njs_int_t njs_fs_path(njs_vm_t *vm, const char **dst, - const njs_value_t* src, const njs_str_t *prop_name); +static const char *njs_fs_path(njs_vm_t *vm, char storage[NJS_MAX_PATH + 1], + const njs_value_t *src, const char *prop_name); static int njs_fs_flags(njs_vm_t *vm, njs_value_t *value, int default_flags); static mode_t njs_fs_mode(njs_vm_t *vm, njs_value_t *value, mode_t default_mode); @@ -142,16 +142,15 @@ njs_fs_read_file(njs_vm_t *vm, njs_value int fd, flags; njs_str_t data; njs_int_t ret; - const char *file_path; - njs_value_t flag, encode, retval, *callback, *options, - *path; + const char *path; + njs_value_t flag, encode, retval, *callback, *options; struct stat sb; const njs_buffer_encoding_t *encoding; - - path = njs_arg(args, nargs, 1); - ret = njs_fs_path(vm, &file_path, path, &njs_str_value("path")); - if (njs_slow_path(ret != NJS_OK)) { - return ret; + char path_buf[NJS_MAX_PATH + 1]; + + path = njs_fs_path(vm, path_buf, njs_arg(args, nargs, 1), "path"); + if (njs_slow_path(path == NULL)) { + return NJS_ERROR; } callback = NULL; @@ -215,7 +214,7 @@ njs_fs_read_file(njs_vm_t *vm, njs_value } } - fd = open(file_path, flags); + fd = open(path, flags); if (njs_slow_path(fd < 0)) { ret = njs_fs_error(vm, "open", strerror(errno), path, errno, &retval); goto done; @@ -277,18 +276,18 @@ njs_fs_write_file(njs_vm_t *vm, njs_valu ssize_t n; njs_str_t content; njs_int_t ret; - const char *file_path; - njs_value_t flag, mode, encode, retval, *path, *data, - *callback, *options; + const char *path; + njs_value_t flag, mode, encode, retval, *data, *callback, + *options; njs_typed_array_t *array; njs_fs_calltype_t calltype; njs_array_buffer_t *buffer; const njs_buffer_encoding_t *encoding; - - path = njs_arg(args, nargs, 1); - ret = njs_fs_path(vm, &file_path, path, &njs_str_value("path")); - if (njs_slow_path(ret != NJS_OK)) { - return ret; + char path_buf[NJS_MAX_PATH + 1]; + + path = njs_fs_path(vm, path_buf, njs_arg(args, nargs, 1), "path"); + if (njs_slow_path(path == NULL)) { + return NJS_ERROR; } callback = NULL; @@ -395,7 +394,7 @@ njs_fs_write_file(njs_vm_t *vm, njs_valu return NJS_ERROR; } - fd = open(file_path, flags, md); + fd = open(path, flags, md); if (njs_slow_path(fd < 0)) { ret = njs_fs_error(vm, "open", strerror(errno), path, errno, &retval); goto done; @@ -441,8 +440,9 @@ njs_fs_rename(njs_vm_t *vm, njs_value_t njs_index_t calltype) { njs_int_t ret; - const char *old_path, *new_path; + const char *path, *newpath; njs_value_t retval, *callback; + char path_buf[NJS_MAX_PATH + 1], newpath_buf[NJS_MAX_PATH + 1]; callback = NULL; @@ -454,21 +454,19 @@ njs_fs_rename(njs_vm_t *vm, njs_value_t } } - ret = njs_fs_path(vm, &old_path, njs_arg(args, nargs, 1), - &njs_str_value("oldPath")); - if (njs_slow_path(ret != NJS_OK)) { - return ret; + path = njs_fs_path(vm, path_buf, njs_arg(args, nargs, 1), "oldPath"); + if (njs_slow_path(path == NULL)) { + return NJS_ERROR; } - ret = njs_fs_path(vm, &new_path, njs_arg(args, nargs, 2), - &njs_str_value("newPath")); - if (njs_slow_path(ret != NJS_OK)) { - return ret; + newpath = njs_fs_path(vm, newpath_buf, njs_arg(args, nargs, 2), "newPath"); + if (njs_slow_path(newpath == NULL)) { + return NJS_ERROR; } njs_set_undefined(&retval); - ret = rename(old_path, new_path); + ret = rename(path, newpath); if (njs_slow_path(ret != 0)) { ret = njs_fs_error(vm, "rename", strerror(errno), NULL, errno, &retval); } @@ -487,13 +485,13 @@ njs_fs_access(njs_vm_t *vm, njs_value_t { int md; njs_int_t ret; - const char *file_path; - njs_value_t retval, *path, *callback, *mode; - - path = njs_arg(args, nargs, 1); - ret = njs_fs_path(vm, &file_path, path, &njs_str_value("path")); - if (njs_slow_path(ret != NJS_OK)) { - return ret; + const char *path; + njs_value_t retval, *callback, *mode; + char path_buf[NJS_MAX_PATH + 1]; + + path = njs_fs_path(vm, path_buf, njs_arg(args, nargs, 1), "path"); + if (njs_slow_path(path == NULL)) { + return NJS_ERROR; } callback = NULL; @@ -527,7 +525,7 @@ njs_fs_access(njs_vm_t *vm, njs_value_t njs_set_undefined(&retval); - ret = access(file_path, md); + ret = access(path, md); if (njs_slow_path(ret != 0)) { ret = njs_fs_error(vm, "access", strerror(errno), path, errno, &retval); } @@ -545,19 +543,18 @@ njs_fs_symlink(njs_vm_t *vm, njs_value_t njs_index_t calltype) { njs_int_t ret; - const char *target_path, *file_path; - njs_value_t retval, *target, *path, *callback, *type; - - target = njs_arg(args, nargs, 1); - ret = njs_fs_path(vm, &target_path, target, &njs_str_value("target")); - if (njs_slow_path(ret != NJS_OK)) { - return ret; + const char *target, *path; + njs_value_t retval, *callback, *type; + char target_buf[NJS_MAX_PATH + 1], path_buf[NJS_MAX_PATH + 1]; + + target = njs_fs_path(vm, target_buf, njs_arg(args, nargs, 1), "target"); + if (njs_slow_path(target == NULL)) { + return NJS_ERROR; } - path = njs_arg(args, nargs, 2); - ret = njs_fs_path(vm, &file_path, path, &njs_str_value("path")); - if (njs_slow_path(ret != NJS_OK)) { - return ret; + path = njs_fs_path(vm, path_buf, njs_arg(args, nargs, 2), "path"); + if (njs_slow_path(path == NULL)) { + return NJS_ERROR; } callback = NULL; @@ -582,7 +579,7 @@ njs_fs_symlink(njs_vm_t *vm, njs_value_t njs_set_undefined(&retval); - ret = symlink(target_path, file_path); + ret = symlink(target, path); if (njs_slow_path(ret != 0)) { ret = njs_fs_error(vm, "symlink", strerror(errno), path, errno, &retval); @@ -601,13 +598,13 @@ njs_fs_unlink(njs_vm_t *vm, njs_value_t njs_index_t calltype) { njs_int_t ret; - const char *file_path; - njs_value_t retval, *path, *callback; - - path = njs_arg(args, nargs, 1); - ret = njs_fs_path(vm, &file_path, path, &njs_str_value("path")); - if (njs_slow_path(ret != NJS_OK)) { - return ret; + const char *path; + njs_value_t retval, *callback; + char path_buf[NJS_MAX_PATH + 1]; + + path = njs_fs_path(vm, path_buf, njs_arg(args, nargs, 1), "path"); + if (njs_slow_path(path == NULL)) { + return NJS_ERROR; } callback = NULL; @@ -622,7 +619,7 @@ njs_fs_unlink(njs_vm_t *vm, njs_value_t njs_set_undefined(&retval); - ret = unlink(file_path); + ret = unlink(path); if (njs_slow_path(ret != 0)) { ret = njs_fs_error(vm, "unlink", strerror(errno), path, errno, &retval); } @@ -641,15 +638,15 @@ njs_fs_realpath(njs_vm_t *vm, njs_value_ { njs_int_t ret; njs_str_t s; - const char *file_path; - njs_value_t encode, retval, *path, *callback, *options; + const char *path; + njs_value_t encode, retval, *callback, *options; const njs_buffer_encoding_t *encoding; - char path_buf[MAXPATHLEN]; - - path = njs_arg(args, nargs, 1); - ret = njs_fs_path(vm, &file_path, path, &njs_str_value("path")); - if (njs_slow_path(ret != NJS_OK)) { - return ret; + char path_buf[NJS_MAX_PATH + 1], + dst_buf[NJS_MAX_PATH + 1]; + + path = njs_fs_path(vm, path_buf, njs_arg(args, nargs, 1), "path"); + if (njs_slow_path(path == NULL)) { + return NJS_ERROR; } callback = NULL; @@ -700,7 +697,7 @@ njs_fs_realpath(njs_vm_t *vm, njs_value_ } } - s.start = (u_char *) realpath(file_path, path_buf); + s.start = (u_char *) realpath(path, dst_buf); if (njs_slow_path(s.start == NULL)) { ret = njs_fs_error(vm, "realpath", strerror(errno), path, errno, &retval); @@ -730,15 +727,15 @@ static njs_int_t njs_fs_mkdir(njs_vm_t *vm, njs_value_t *args, njs_uint_t nargs, njs_index_t calltype) { + char *path; mode_t md; njs_int_t ret; - const char *file_path; - njs_value_t mode, recursive, retval, *path, *callback, *options; - - path = njs_arg(args, nargs, 1); - ret = njs_fs_path(vm, &file_path, path, &njs_str_value("path")); - if (njs_slow_path(ret != NJS_OK)) { - return ret; + njs_value_t mode, recursive, retval, *callback, *options; + char path_buf[NJS_MAX_PATH + 1]; + + path = (char *) njs_fs_path(vm, path_buf, njs_arg(args, nargs, 1), "path"); + if (njs_slow_path(path == NULL)) { + return NJS_ERROR; } callback = NULL; @@ -792,8 +789,7 @@ njs_fs_mkdir(njs_vm_t *vm, njs_value_t * return NJS_ERROR; } - ret = njs_fs_make_path(vm, file_path, md, njs_is_true(&recursive), - &retval); + ret = njs_fs_make_path(vm, path, md, njs_is_true(&recursive), &retval); if (ret == NJS_OK) { return njs_fs_result(vm, &retval, calltype, callback, 1); @@ -808,13 +804,13 @@ njs_fs_rmdir(njs_vm_t *vm, njs_value_t * njs_index_t calltype) { njs_int_t ret; - const char *file_path; - njs_value_t recursive, retval, *path, *callback, *options; - - path = njs_arg(args, nargs, 1); - ret = njs_fs_path(vm, &file_path, path, &njs_str_value("path")); - if (njs_slow_path(ret != NJS_OK)) { - return ret; + const char *path; + njs_value_t recursive, retval, *callback, *options; + char path_buf[NJS_MAX_PATH + 1]; + + path = njs_fs_path(vm, path_buf, njs_arg(args, nargs, 1), "path"); + if (njs_slow_path(path == NULL)) { + return NJS_ERROR; } callback = NULL; @@ -852,7 +848,7 @@ njs_fs_rmdir(njs_vm_t *vm, njs_value_t * } } - ret = njs_fs_rmtree(vm, file_path, njs_is_true(&recursive), &retval); + ret = njs_fs_rmtree(vm, path, njs_is_true(&recursive), &retval); if (ret == NJS_OK) { return njs_fs_result(vm, &retval, calltype, callback, 1); @@ -869,19 +865,19 @@ njs_fs_readdir(njs_vm_t *vm, njs_value_t DIR *dir; njs_str_t s; njs_int_t ret; - const char *dir_path; - njs_value_t encode, types, ename, etype, retval, *path, + const char *path; + njs_value_t encode, types, ename, etype, retval, *callback, *options, *value; njs_array_t *results; struct dirent *entry; const njs_buffer_encoding_t *encoding; + char path_buf[NJS_MAX_PATH + 1]; static const njs_value_t string_types = njs_string("withFileTypes"); - path = njs_arg(args, nargs, 1); - ret = njs_fs_path(vm, &dir_path, path, &njs_str_value("path")); - if (njs_slow_path(ret != NJS_OK)) { - return ret; + path = njs_fs_path(vm, path_buf, njs_arg(args, nargs, 1), "path"); + if (njs_slow_path(path == NULL)) { + return NJS_ERROR; } callback = NULL; @@ -945,13 +941,15 @@ njs_fs_readdir(njs_vm_t *vm, njs_value_t njs_set_array(&retval, results); - dir = opendir(dir_path); + dir = opendir(path); if (njs_slow_path(dir == NULL)) { ret = njs_fs_error(vm, "opendir", strerror(errno), path, errno, &retval); goto done; } + ret = NJS_OK; + for ( ;; ) { errno = 0; entry = readdir(dir); @@ -1077,16 +1075,13 @@ njs_fs_fd_read(njs_vm_t *vm, int fd, njs static njs_int_t -njs_fs_make_path(njs_vm_t *vm, const char *path, mode_t md, - njs_bool_t recursive, njs_value_t *retval) +njs_fs_make_path(njs_vm_t *vm, char *path, mode_t md, njs_bool_t recursive, + njs_value_t *retval) { int err; - ssize_t length; njs_int_t ret; const char *p, *prev, *end; - njs_value_t value; struct stat sb; - char path_buf[MAXPATHLEN]; njs_set_undefined(retval); @@ -1111,15 +1106,14 @@ njs_fs_make_path(njs_vm_t *vm, const cha p = end; } - if (njs_slow_path((p - path) > MAXPATHLEN)) { + if (njs_slow_path((p - path) > NJS_MAX_PATH)) { njs_internal_error(vm, "too large path"); return NJS_ERROR; } - memcpy(&path_buf[prev - path], &path[prev - path], p - prev); - path_buf[p - path] = '\0'; - - ret = mkdir(path_buf, md); + path[p - path] = '\0'; + + ret = mkdir(path, md); err = errno; switch (ret) { @@ -1133,7 +1127,7 @@ njs_fs_make_path(njs_vm_t *vm, const cha case EEXIST: default: - ret = stat(path_buf, &sb); + ret = stat(path, &sb); if (ret == 0) { if (!S_ISDIR(sb.st_mode)) { err = ENOTDIR; @@ -1150,7 +1144,7 @@ njs_fs_make_path(njs_vm_t *vm, const cha break; } - path_buf[p - path] = '/'; + path[p - path] = '/'; prev = p; } @@ -1158,17 +1152,7 @@ njs_fs_make_path(njs_vm_t *vm, const cha failed: - length = njs_utf8_length((u_char *) path, end - path); - if (njs_slow_path(length < 0)) { - length = 0; - } - - ret = njs_string_new(vm, &value, (u_char *) path, end - path, length); - if (ret != NJS_OK) { - return NJS_ERROR; - } - - return njs_fs_error(vm, "mkdir", strerror(err), &value, err, retval); + return njs_fs_error(vm, "mkdir", strerror(err), path, err, retval); } @@ -1277,7 +1261,7 @@ njs_ftw(char *path, njs_file_tree_walk_c continue; } - if (njs_slow_path(length >= (PATH_MAX - len))) { + if (njs_slow_path(length >= (NJS_MAX_PATH - len))) { errno = ENAMETOOLONG; ret = NJS_ERROR; goto done; @@ -1329,10 +1313,10 @@ njs_file_tree_walk(const char *path, njs njs_ftw_flags_t flags) { size_t len; - char pathbuf[PATH_MAX + 1]; + char pathbuf[NJS_MAX_PATH + 1]; len = njs_strlen(path); - if (njs_slow_path(len > PATH_MAX)) { + if (njs_slow_path(len > NJS_MAX_PATH)) { errno = ENAMETOOLONG; return -1; } @@ -1361,11 +1345,8 @@ static njs_int_t njs_fs_rmtree(njs_vm_t *vm, const char *path, njs_bool_t recursive, njs_value_t *retval) { - size_t size; - ssize_t length; - njs_int_t ret; - const char *description; - njs_value_t value; + njs_int_t ret; + const char *description; njs_set_undefined(retval); @@ -1387,36 +1368,22 @@ njs_fs_rmtree(njs_vm_t *vm, const char * description = strerror(errno); } - size = njs_strlen(path); - length = njs_utf8_length((u_char *) path, size); - if (njs_slow_path(length < 0)) { - length = 0; - } - - ret = njs_string_new(vm, &value, (u_char *) path, size, length); - if (njs_slow_path(ret != NJS_OK)) { - return NJS_ERROR; - } - - return njs_fs_error(vm, "rmdir", description, &value, errno, retval); + return njs_fs_error(vm, "rmdir", description, path, errno, retval); } -static njs_int_t -njs_fs_path(njs_vm_t *vm, const char **dst, const njs_value_t* src, - const njs_str_t *prop_name) +static const char * +njs_fs_path(njs_vm_t *vm, char *storage, const njs_value_t *src, + const char *prop_name) { - u_char *data, *p, *start; + u_char *p; + njs_str_t str; njs_typed_array_t *array; njs_array_buffer_t *buffer; switch (src->type) { case NJS_STRING: - *dst = njs_string_to_c_string(vm, njs_value_arg(src)); - if (njs_slow_path(*dst == NULL)) { - return NJS_ERROR; - } - + njs_string_get(src, &str); break; case NJS_TYPED_ARRAY: @@ -1425,35 +1392,33 @@ njs_fs_path(njs_vm_t *vm, const char **d buffer = array->buffer; if (njs_slow_path(njs_is_detached_buffer(buffer))) { njs_type_error(vm, "detached buffer"); - return NJS_ERROR; - } - - start = &buffer->u.u8[array->offset]; - - if (njs_slow_path(memchr(start, '\0', array->byte_length) != 0)) { - njs_type_error(vm, "\"%V\" must be a Buffer without null bytes", - prop_name); - return NJS_ERROR; + return NULL; } - data = njs_mp_alloc(vm->mem_pool, array->byte_length + 1); - if (njs_slow_path(data == NULL)) { - njs_memory_error(vm); - return NJS_ERROR; - } - - p = njs_cpymem(data, start, array->byte_length); - *p++ = '\0'; - - *dst = (char *) data; + str.start = &buffer->u.u8[array->offset]; + str.length = array->byte_length; break; default: - njs_type_error(vm, "\"%V\" must be a string or Buffer", prop_name); - return NJS_ERROR; + njs_type_error(vm, "\"%s\" must be a string or Buffer", prop_name); + return NULL; + } + + if (njs_slow_path(str.length > NJS_MAX_PATH - 1)) { + njs_type_error(vm, "\"%s\" is too long >= %d", prop_name, NJS_MAX_PATH); + return NULL; } - return NJS_OK; + if (njs_slow_path(memchr(str.start, '\0', str.length) != 0)) { + njs_type_error(vm, "\"%s\" must be a Buffer without null bytes", + prop_name); + return NULL; + } + + p = njs_cpymem(storage, str.start, str.length); + *p++ = '\0'; + + return storage; } @@ -1511,7 +1476,7 @@ njs_fs_mode(njs_vm_t *vm, njs_value_t *v static njs_int_t njs_fs_error(njs_vm_t *vm, const char *syscall, const char *description, - njs_value_t *path, int errn, njs_value_t *retval) + const char *path, int errn, njs_value_t *retval) { size_t size; njs_int_t ret; @@ -1526,7 +1491,7 @@ njs_fs_error(njs_vm_t *vm, const char *s size = description != NULL ? njs_strlen(description) : 0; - ret = njs_string_new(vm, &value, (u_char *) description, size, size); + ret = njs_string_create(vm, &value, description, size); if (njs_slow_path(ret != NJS_OK)) { return NJS_ERROR; } @@ -1547,9 +1512,8 @@ njs_fs_error(njs_vm_t *vm, const char *s } code = njs_errno_string(errn); - size = njs_strlen(code); - - ret = njs_string_new(vm, &value, (u_char *) code, size, size); + + ret = njs_string_create(vm, &value, code, njs_strlen(code)); if (njs_slow_path(ret != NJS_OK)) { return NJS_ERROR; } @@ -1562,16 +1526,20 @@ njs_fs_error(njs_vm_t *vm, const char *s } if (path != NULL) { + ret = njs_string_create(vm, &value, path, njs_strlen(path)); + if (njs_slow_path(ret != NJS_OK)) { + return NJS_ERROR; + } + ret = njs_value_property_set(vm, retval, njs_value_arg(&string_path), - path); + &value); if (njs_slow_path(ret != NJS_OK)) { return NJS_ERROR; } } if (syscall != NULL) { - size = njs_strlen(syscall); - ret = njs_string_new(vm, &value, (u_char *) syscall, size, size); + ret = njs_string_create(vm, &value, syscall, njs_strlen(syscall)); if (njs_slow_path(ret != NJS_OK)) { return NJS_ERROR; } diff -r 2065b127bd90 -r f6bf6357ab6b src/njs_string.c --- a/src/njs_string.c Fri Oct 02 12:18:41 2020 +0000 +++ b/src/njs_string.c Fri Oct 02 12:18:44 2020 +0000 @@ -134,6 +134,19 @@ njs_string_set(njs_vm_t *vm, njs_value_t njs_int_t +njs_string_create(njs_vm_t *vm, njs_value_t *value, const char *src, + size_t size) +{ + njs_str_t str; + + str.start = (u_char *) src; + str.length = size; + + return njs_string_decode_utf8(vm, value, &str); +} + + +njs_int_t njs_string_new(njs_vm_t *vm, njs_value_t *value, const u_char *start, uint32_t size, uint32_t length) { diff -r 2065b127bd90 -r f6bf6357ab6b src/njs_string.h --- a/src/njs_string.h Fri Oct 02 12:18:41 2020 +0000 +++ b/src/njs_string.h Fri Oct 02 12:18:44 2020 +0000 @@ -185,6 +185,8 @@ u_char *njs_string_alloc(njs_vm_t *vm, n uint64_t length); njs_int_t njs_string_new(njs_vm_t *vm, njs_value_t *value, const u_char *start, uint32_t size, uint32_t length); +njs_int_t njs_string_create(njs_vm_t *vm, njs_value_t *value, const char *src, + size_t size); void njs_encode_hex(njs_str_t *dst, const njs_str_t *src); size_t njs_encode_hex_length(const njs_str_t *src, size_t *out_size); diff -r 2065b127bd90 -r f6bf6357ab6b src/njs_unix.h --- a/src/njs_unix.h Fri Oct 02 12:18:41 2020 +0000 +++ b/src/njs_unix.h Fri Oct 02 12:18:44 2020 +0000 @@ -47,4 +47,10 @@ #include +#if defined(PATH_MAX) +#define NJS_MAX_PATH PATH_MAX +#else +#define NJS_MAX_PATH 4096 +#endif + #endif /* _NJS_UNIX_H_INCLUDED_ */ diff -r 2065b127bd90 -r f6bf6357ab6b test/njs_expect_test.exp --- a/test/njs_expect_test.exp Fri Oct 02 12:18:41 2020 +0000 +++ b/test/njs_expect_test.exp Fri Oct 02 12:18:44 2020 +0000 @@ -477,6 +477,8 @@ njs_test { "undefined\r\nx undefined\r\n>> "} {"fs.readFile('test/fs/ascii', {encoding:'utf8',flag:'r+'}, function (e, data) {console.log(data[599], data[600])})\r\n" "undefined\r\nx undefined\r\n>> "} + {"fs.readFile(Buffer.from([0x80,0x80]), function(e) {console.log(e.path.codePointAt())})\r\n" + "undefined\r\n65533"} } njs_test { @@ -504,6 +506,8 @@ njs_test { "undefined\r\n>> "} {"fs.readFileSync('test/fs/non_utf8', 'utf8').charCodeAt(1)\r\n" "65533"} + {"fs.readFile('x'.repeat(8192))\r\n" + "TypeError: \"path\" is too long >= 4096"} } njs_test { @@ -540,6 +544,8 @@ njs_test { "undefined\r\n>> "} {"fs.writeFile('/invalid_path', 'ABC', function (e) { console.log(JSON.stringify(e))})\r\n" "undefined\r\n{\"errno\":13,\"code\":\"EACCES\",\"path\":\"/invalid_path\",\"syscall\":\"open\"}\r\n>> "} + {"fs.writeFile(Buffer.from('/invalid_path'), 'ABC', function (e) { console.log(typeof e.path)})\r\n" + "undefined\r\nstring\r\n>> "} } # require('fs').writeFileSync() From anton at sijanec.eu Sat Oct 3 14:15:13 2020 From: anton at sijanec.eu (=?UTF-8?Q?Anton_Luka_=C5=A0ijanec?=) Date: Sat, 03 Oct 2020 16:15:13 +0200 Subject: bug: subrequest, addition_filter and not_modified Message-ID: <5a83225ccbb6611055f86eb6f8eb6d98@sijanec.eu> Hello! I have just stumbled upon a nginx bug. When using add_before_body and/or add_after_body commands from ngx_http_addition_filter_module, the server will respond with "304 Not Modified" even if the added file has changed. After investigation I figured out that this error could be applied to everything that uses ngx_http_subrequest to gather data. The request structure will remain with the same last_modified_time even if the subrequest contains data that was modified after this time. The solution to this problem would be to overwrite the request structure headers_out.last_modified_time with the last_modified_time in the structure, generated by ngx_http_subrequest, if it's in the future, but that would not be enough. The problem is that ngx_http_subrequest does not populate the request struct, specified as it's fourth argument, with headers_out.last_modified_time, it stays at -1, but that wouldn't help very much in this particular case. Even setting the headers_out.last_modified_time to -1 in addition_filter_module would not work and would not fix the issue, because the filter modules do not execute before not_modified module (nginx/auto/modules:142). Well, at last resort, the not_modified module could load configuration of addition_filter module and, if addition is to be done, return to the next module. But that would not work either; the not_modified module source is included before the addition_filter so it's module struct and relying configurations are not available at the time of compilation. Proof of bug: Run nginx with attached nginx.conf and create files /tmp/add.html and /tmp/index.html with some content. Load http://localhost:8080/ in a modern Firefox browser. Then change the file /tmp/add.html and nginx will proceed to report "304 Not Modified" and your browser's copy will after page refresh remain with the old /tmp/add.html file added at the beginning of the response. Regards! I submitted the same text as a ticket: https://trac.nginx.org/nginx/ticket/2055 -- Anton Luka ?ijanec https://?ijanec.eu/ +38 6 64/176-345 anton at sijanec.eu (mail, xmpp & sip) https://?ijanec.eu/pgp-key.txt?F4C3E3A4DFB7254397A9F993E76135F49802CD14 -------------- next part -------------- An embedded and charset-unspecified text was scrubbed... Name: nginx.conf URL: From mdounin at mdounin.ru Sat Oct 3 17:39:17 2020 From: mdounin at mdounin.ru (Maxim Dounin) Date: Sat, 3 Oct 2020 20:39:17 +0300 Subject: bug: subrequest, addition_filter and not_modified In-Reply-To: <5a83225ccbb6611055f86eb6f8eb6d98@sijanec.eu> References: <5a83225ccbb6611055f86eb6f8eb6d98@sijanec.eu> Message-ID: <20201003173917.GO1136@mdounin.ru> Hello! On Sat, Oct 03, 2020 at 04:15:13PM +0200, Anton Luka ?ijanec wrote: > I have just stumbled upon a nginx bug. When using add_before_body and/or > add_after_body commands from ngx_http_addition_filter_module, the server > will respond with "304 Not Modified" even if the added file has changed. > > After investigation I figured out that this error could be applied to > everything that uses ngx_http_subrequest to gather data. The request > structure will remain with the same last_modified_time even if the > subrequest contains data that was modified after this time. The solution > to this problem would be to overwrite the request structure > headers_out.last_modified_time with the last_modified_time in the > structure, generated by ngx_http_subrequest, if it's in the future, but > that would not be enough. The usual approach is to clear the last modified time of the main request in the filter which is expected to significantly modify the response. For example, this is what SSI module does: if (!slcf->last_modified) { ngx_http_clear_last_modified(r); ngx_http_clear_etag(r); } else { ngx_http_weak_etag(r); } This is not the case for addition filter though, as it is expected to be used for non-essential additions, and hence only makes the response ETag weak, much like what SSI does with "ssi_last_modified on;". -- Maxim Dounin http://mdounin.ru/ From mdounin at mdounin.ru Sat Oct 3 18:05:45 2020 From: mdounin at mdounin.ru (Maxim Dounin) Date: Sat, 03 Oct 2020 18:05:45 +0000 Subject: [nginx] Version bump. Message-ID: details: https://hg.nginx.org/nginx/rev/64b97c8166b8 branches: changeset: 7724:64b97c8166b8 user: Maxim Dounin date: Sat Oct 03 21:01:12 2020 +0300 description: Version bump. diffstat: src/core/nginx.h | 4 ++-- 1 files changed, 2 insertions(+), 2 deletions(-) diffs (14 lines): diff -r 0896ed4ddee4 -r 64b97c8166b8 src/core/nginx.h --- a/src/core/nginx.h Tue Sep 29 17:32:10 2020 +0300 +++ b/src/core/nginx.h Sat Oct 03 21:01:12 2020 +0300 @@ -9,8 +9,8 @@ #define _NGINX_H_INCLUDED_ -#define nginx_version 1019003 -#define NGINX_VERSION "1.19.3" +#define nginx_version 1019004 +#define NGINX_VERSION "1.19.4" #define NGINX_VER "nginx/" NGINX_VERSION #ifdef NGX_BUILD From mdounin at mdounin.ru Sat Oct 3 18:05:48 2020 From: mdounin at mdounin.ru (Maxim Dounin) Date: Sat, 03 Oct 2020 18:05:48 +0000 Subject: [nginx] Mail: proxy_smtp_auth directive. Message-ID: details: https://hg.nginx.org/nginx/rev/d63c5373b5ba branches: changeset: 7725:d63c5373b5ba user: Maxim Dounin date: Sat Oct 03 21:04:57 2020 +0300 description: Mail: proxy_smtp_auth directive. The proxy_smtp_auth directive instructs nginx to authenticate users on backend via the AUTH command (using the PLAIN SASL mechanism), similar to what is normally done for IMAP and POP3. If xclient is enabled along with proxy_smtp_auth, the XCLIENT command won't try to send the LOGIN parameter. diffstat: src/mail/ngx_mail.h | 2 + src/mail/ngx_mail_proxy_module.c | 89 ++++++++++++++++++++++++++++++++++++++- 2 files changed, 87 insertions(+), 4 deletions(-) diffs (197 lines): diff -r 64b97c8166b8 -r d63c5373b5ba src/mail/ngx_mail.h --- a/src/mail/ngx_mail.h Sat Oct 03 21:01:12 2020 +0300 +++ b/src/mail/ngx_mail.h Sat Oct 03 21:04:57 2020 +0300 @@ -162,10 +162,12 @@ typedef enum { ngx_smtp_auth_external, ngx_smtp_helo, ngx_smtp_helo_xclient, + ngx_smtp_helo_auth, ngx_smtp_helo_from, ngx_smtp_xclient, ngx_smtp_xclient_from, ngx_smtp_xclient_helo, + ngx_smtp_xclient_auth, ngx_smtp_from, ngx_smtp_to } ngx_smtp_state_e; diff -r 64b97c8166b8 -r d63c5373b5ba src/mail/ngx_mail_proxy_module.c --- a/src/mail/ngx_mail_proxy_module.c Sat Oct 03 21:01:12 2020 +0300 +++ b/src/mail/ngx_mail_proxy_module.c Sat Oct 03 21:04:57 2020 +0300 @@ -16,6 +16,7 @@ typedef struct { ngx_flag_t enable; ngx_flag_t pass_error_message; ngx_flag_t xclient; + ngx_flag_t smtp_auth; size_t buffer_size; ngx_msec_t timeout; } ngx_mail_proxy_conf_t; @@ -74,6 +75,13 @@ static ngx_command_t ngx_mail_proxy_com offsetof(ngx_mail_proxy_conf_t, xclient), NULL }, + { ngx_string("proxy_smtp_auth"), + NGX_MAIL_MAIN_CONF|NGX_MAIL_SRV_CONF|NGX_CONF_FLAG, + ngx_conf_set_flag_slot, + NGX_MAIL_SRV_CONF_OFFSET, + offsetof(ngx_mail_proxy_conf_t, smtp_auth), + NULL }, + ngx_null_command }; @@ -450,7 +458,7 @@ ngx_mail_proxy_smtp_handler(ngx_event_t { u_char *p; ngx_int_t rc; - ngx_str_t line; + ngx_str_t line, auth, encoded; ngx_buf_t *b; ngx_connection_t *c; ngx_mail_session_t *s; @@ -513,6 +521,9 @@ ngx_mail_proxy_smtp_handler(ngx_event_t } else if (s->auth_method == NGX_MAIL_AUTH_NONE) { s->mail_state = ngx_smtp_helo_from; + } else if (pcf->smtp_auth) { + s->mail_state = ngx_smtp_helo_auth; + } else { s->mail_state = ngx_smtp_helo; } @@ -552,7 +563,9 @@ ngx_mail_proxy_smtp_handler(ngx_event_t p = ngx_copy(p, s->connection->addr_text.data, s->connection->addr_text.len); - if (s->login.len) { + pcf = ngx_mail_get_module_srv_conf(s, ngx_mail_proxy_module); + + if (s->login.len && !pcf->smtp_auth) { p = ngx_cpymem(p, " LOGIN=", sizeof(" LOGIN=") - 1); p = ngx_copy(p, s->login.data, s->login.len); } @@ -570,6 +583,9 @@ ngx_mail_proxy_smtp_handler(ngx_event_t } else if (s->auth_method == NGX_MAIL_AUTH_NONE) { s->mail_state = ngx_smtp_xclient_from; + } else if (pcf->smtp_auth) { + s->mail_state = ngx_smtp_xclient_auth; + } else { s->mail_state = ngx_smtp_xclient; } @@ -595,8 +611,62 @@ ngx_mail_proxy_smtp_handler(ngx_event_t &s->smtp_helo) - line.data; - s->mail_state = (s->auth_method == NGX_MAIL_AUTH_NONE) ? - ngx_smtp_helo_from : ngx_smtp_helo; + pcf = ngx_mail_get_module_srv_conf(s, ngx_mail_proxy_module); + + if (s->auth_method == NGX_MAIL_AUTH_NONE) { + s->mail_state = ngx_smtp_helo_from; + + } else if (pcf->smtp_auth) { + s->mail_state = ngx_smtp_helo_auth; + + } else { + s->mail_state = ngx_smtp_helo; + } + + break; + + case ngx_smtp_helo_auth: + case ngx_smtp_xclient_auth: + ngx_log_debug0(NGX_LOG_DEBUG_MAIL, rev->log, 0, + "mail proxy send auth"); + + s->connection->log->action = "sending AUTH to upstream"; + + if (s->passwd.data == NULL) { + ngx_log_error(NGX_LOG_ERR, s->connection->log, 0, + "no password available"); + ngx_mail_proxy_internal_server_error(s); + return; + } + + auth.len = 1 + s->login.len + 1 + s->passwd.len; + auth.data = ngx_pnalloc(c->pool, auth.len); + if (auth.data == NULL) { + ngx_mail_proxy_internal_server_error(s); + return; + } + + auth.len = ngx_sprintf(auth.data, "%Z%V%Z%V", &s->login, &s->passwd) + - auth.data; + + line.len = sizeof("AUTH PLAIN " CRLF) - 1 + + ngx_base64_encoded_length(auth.len); + + line.data = ngx_pnalloc(c->pool, line.len); + if (line.data == NULL) { + ngx_mail_proxy_internal_server_error(s); + return; + } + + encoded.data = ngx_cpymem(line.data, "AUTH PLAIN ", + sizeof("AUTH PLAIN ") - 1); + + ngx_encode_base64(&encoded, &auth); + + p = encoded.data + encoded.len; + *p++ = CR; *p = LF; + + s->mail_state = ngx_smtp_auth_plain; break; @@ -643,6 +713,7 @@ ngx_mail_proxy_smtp_handler(ngx_event_t case ngx_smtp_helo: case ngx_smtp_xclient: + case ngx_smtp_auth_plain: case ngx_smtp_to: b = s->proxy->buffer; @@ -824,6 +895,7 @@ ngx_mail_proxy_read_response(ngx_mail_se case ngx_smtp_helo: case ngx_smtp_helo_xclient: case ngx_smtp_helo_from: + case ngx_smtp_helo_auth: case ngx_smtp_from: if (p[0] == '2' && p[1] == '5' && p[2] == '0') { return NGX_OK; @@ -833,11 +905,18 @@ ngx_mail_proxy_read_response(ngx_mail_se case ngx_smtp_xclient: case ngx_smtp_xclient_from: case ngx_smtp_xclient_helo: + case ngx_smtp_xclient_auth: if (p[0] == '2' && (p[1] == '2' || p[1] == '5') && p[2] == '0') { return NGX_OK; } break; + case ngx_smtp_auth_plain: + if (p[0] == '2' && p[1] == '3' && p[2] == '5') { + return NGX_OK; + } + break; + case ngx_smtp_to: return NGX_OK; } @@ -1102,6 +1181,7 @@ ngx_mail_proxy_create_conf(ngx_conf_t *c pcf->enable = NGX_CONF_UNSET; pcf->pass_error_message = NGX_CONF_UNSET; pcf->xclient = NGX_CONF_UNSET; + pcf->smtp_auth = NGX_CONF_UNSET; pcf->buffer_size = NGX_CONF_UNSET_SIZE; pcf->timeout = NGX_CONF_UNSET_MSEC; @@ -1118,6 +1198,7 @@ ngx_mail_proxy_merge_conf(ngx_conf_t *cf ngx_conf_merge_value(conf->enable, prev->enable, 0); ngx_conf_merge_value(conf->pass_error_message, prev->pass_error_message, 0); ngx_conf_merge_value(conf->xclient, prev->xclient, 1); + ngx_conf_merge_value(conf->smtp_auth, prev->smtp_auth, 0); ngx_conf_merge_size_value(conf->buffer_size, prev->buffer_size, (size_t) ngx_pagesize); ngx_conf_merge_msec_value(conf->timeout, prev->timeout, 24 * 60 * 60000); From anton at sijanec.eu Sat Oct 3 18:10:35 2020 From: anton at sijanec.eu (=?UTF-8?Q?Anton_Luka_=C5=A0ijanec?=) Date: Sat, 03 Oct 2020 20:10:35 +0200 Subject: bug: subrequest, addition_filter and not_modified References: <5a83225ccbb6611055f86eb6f8eb6d98@sijanec.eu> <20201003173917.GO1136@mdounin.ru> Message-ID: <-rhyp9v2zq4go-6jzi72csg30bwktfo3xvie4l-64zdae-i614t0-d1znfcsj2hk4-3t7uxhok0z7u-9e79fa3b5cw7-ok3hzz-pdzv36-jsr0lw-2v3bxet68j5be6bcfgb7z8jftpnqrcbhb3lymqlzxv.1601748635354@email.android.com> An HTML attachment was scrubbed... URL: From alexander.borisov at nginx.com Tue Oct 6 16:54:19 2020 From: alexander.borisov at nginx.com (Alexander Borisov) Date: Tue, 06 Oct 2020 16:54:19 +0000 Subject: [njs] Fixed heap-use-after-free in JSON.parse(). Message-ID: details: https://hg.nginx.org/njs/rev/119064deed61 branches: changeset: 1535:119064deed61 user: Alexander Borisov date: Tue Oct 06 19:53:26 2020 +0300 description: Fixed heap-use-after-free in JSON.parse(). This correctly fixes the issues addressed in 1405:9beb9ea093b5. The initial fix wrongly assumed that the "value" pointer is still valid when njs_is_fast_array(&state->value) is true and the pointer can be used for the fast path.? This is not the case when the array object is resized. Moreover, the fast path branch may be completely eliminated because JSON.parse() with the replacer function is relatively slow by itself. This closes #323, #324, #325 issues on GitHub. diffstat: src/njs_json.c | 18 ------------------ src/test/njs_unit_test.c | 4 ++++ 2 files changed, 4 insertions(+), 18 deletions(-) diffs (42 lines): diff -r f6bf6357ab6b -r 119064deed61 src/njs_json.c --- a/src/njs_json.c Fri Oct 02 12:18:44 2020 +0000 +++ b/src/njs_json.c Tue Oct 06 19:53:26 2020 +0300 @@ -1018,24 +1018,6 @@ njs_json_parse_iterator_call(njs_vm_t *v return ret; } - /* - * The njs_function_apply() function can convert fast array to object. - * After this conversion, there will be garbage in the value. - */ - - if (njs_fast_path(njs_is_fast_array(&state->value) - && (state->index - 1) < njs_array(&state->value)->length)) - { - if (njs_is_undefined(&parse->retval)) { - njs_set_invalid(value); - - } else { - *value = parse->retval; - } - - break; - } - if (njs_is_undefined(&parse->retval)) { ret = njs_value_property_i64_delete(vm, &state->value, state->index - 1, NULL); diff -r f6bf6357ab6b -r 119064deed61 src/test/njs_unit_test.c --- a/src/test/njs_unit_test.c Fri Oct 02 12:18:44 2020 +0000 +++ b/src/test/njs_unit_test.c Tue Oct 06 19:53:26 2020 +0300 @@ -16437,6 +16437,10 @@ static njs_unit_test_t njs_test[] = " function(k, v) {return v.a.a;}); o"), njs_str("TypeError: cannot get property \"a\" of undefined") }, + { njs_str("function func() {this[8] = 1; return new Int8Array(func)}" + "JSON.parse('[1]', func);"), + njs_str("") }, + /* JSON.stringify() */ { njs_str("JSON.stringify()"), From alexander.borisov at nginx.com Tue Oct 6 17:52:30 2020 From: alexander.borisov at nginx.com (Alexander Borisov) Date: Tue, 06 Oct 2020 17:52:30 +0000 Subject: [njs] Fixed heap-use-after-free in JSON.stringify(). Message-ID: details: https://hg.nginx.org/njs/rev/da7b98611f57 branches: changeset: 1536:da7b98611f57 user: Alexander Borisov date: Tue Oct 06 20:24:21 2020 +0300 description: Fixed heap-use-after-free in JSON.stringify(). njs_json_stringify_iterator() assumed, while stringifying flat arrays, that a flat array will always remain flat. This is not the case for flat arrays with values with custom getters which may modify the enclosing array upon invocation. This closes #322 issue on GitHub. diffstat: src/njs_json.c | 13 ++++++++++++- src/test/njs_unit_test.c | 7 +++++++ 2 files changed, 19 insertions(+), 1 deletions(-) diffs (40 lines): diff -r 119064deed61 -r da7b98611f57 src/njs_json.c --- a/src/njs_json.c Tue Oct 06 19:53:26 2020 +0300 +++ b/src/njs_json.c Tue Oct 06 20:24:21 2020 +0300 @@ -1296,7 +1296,18 @@ njs_json_stringify_iterator(njs_vm_t *vm njs_json_stringify_indent(stringify, &chain, 0); } - stringify->retval = njs_array_start(&state->value)[state->index++]; + if (njs_is_fast_array(&state->value)) { + value = njs_array_start(&state->value); + stringify->retval = value[state->index++]; + + } else { + ret = njs_value_property_i64(vm, &state->value, state->index++, + &stringify->retval); + if (njs_slow_path(ret == NJS_ERROR)) { + return ret; + } + } + value = &stringify->retval; ret = njs_json_stringify_to_json(stringify, state, NULL, value); diff -r 119064deed61 -r da7b98611f57 src/test/njs_unit_test.c --- a/src/test/njs_unit_test.c Tue Oct 06 19:53:26 2020 +0300 +++ b/src/test/njs_unit_test.c Tue Oct 06 20:24:21 2020 +0300 @@ -16848,6 +16848,13 @@ static njs_unit_test_t njs_test[] = { njs_str("var a = {}; a.a = a; JSON.stringify(a)"), njs_str("TypeError: Nested too deep or a cyclic structure") }, + { njs_str("var array = [1,2,3];" + "array[1] = {get value() {" + " Object.defineProperty(array, '2', {get: () => 10}) }" + "};" + "JSON.stringify(array)"), + njs_str("[1,{},10]") }, + /* njs.dump(). */ { njs_str("njs.dump({a:1, b:[1,,2,{c:new Boolean(1)}]})"), From alexander.borisov at nginx.com Tue Oct 6 17:52:32 2020 From: alexander.borisov at nginx.com (Alexander Borisov) Date: Tue, 06 Oct 2020 17:52:32 +0000 Subject: [njs] Fixed JSON.stringify() for arrays resizable via getters. Message-ID: details: https://hg.nginx.org/njs/rev/036a4fbf9204 branches: changeset: 1537:036a4fbf9204 user: Alexander Borisov date: Tue Oct 06 20:51:56 2020 +0300 description: Fixed JSON.stringify() for arrays resizable via getters. diffstat: src/njs_json.c | 3 ++- src/test/njs_unit_test.c | 4 ++++ 2 files changed, 6 insertions(+), 1 deletions(-) diffs (34 lines): diff -r da7b98611f57 -r 036a4fbf9204 src/njs_json.c --- a/src/njs_json.c Tue Oct 06 20:24:21 2020 +0300 +++ b/src/njs_json.c Tue Oct 06 20:51:56 2020 +0300 @@ -1077,6 +1077,7 @@ njs_json_push_stringify_state(njs_vm_t * state->key = NULL; if (njs_is_fast_array(value)) { + state->length = njs_array_len(value); state->type = NJS_JSON_ARRAY; state->array = 1; @@ -1279,7 +1280,7 @@ njs_json_stringify_iterator(njs_vm_t *vm njs_json_stringify_indent(stringify, &chain, 0); } - if (state->index >= njs_array_len(&state->value)) { + if (state->index >= state->length) { njs_json_stringify_indent(stringify, &chain, -1); njs_chb_append_literal(&chain,"]"); diff -r da7b98611f57 -r 036a4fbf9204 src/test/njs_unit_test.c --- a/src/test/njs_unit_test.c Tue Oct 06 20:24:21 2020 +0300 +++ b/src/test/njs_unit_test.c Tue Oct 06 20:51:56 2020 +0300 @@ -16855,6 +16855,10 @@ static njs_unit_test_t njs_test[] = "JSON.stringify(array)"), njs_str("[1,{},10]") }, + { njs_str("var array = [1];" + "array[1] = {get value() {array[10] = 10}}; JSON.stringify(array)"), + njs_str("[1,{}]") }, + /* njs.dump(). */ { njs_str("njs.dump({a:1, b:[1,,2,{c:new Boolean(1)}]})"), From alexander.borisov at nginx.com Thu Oct 8 15:48:24 2020 From: alexander.borisov at nginx.com (Alexander Borisov) Date: Thu, 08 Oct 2020 15:48:24 +0000 Subject: [njs] HTTP: throwing an exception in internalRedirect() for a subrequest. Message-ID: details: https://hg.nginx.org/njs/rev/893fa730285c branches: changeset: 1538:893fa730285c user: Alexander Borisov date: Thu Oct 08 18:47:04 2020 +0300 description: HTTP: throwing an exception in internalRedirect() for a subrequest. This closes #214 issue on GitHub. diffstat: nginx/ngx_http_js_module.c | 5 +++++ 1 files changed, 5 insertions(+), 0 deletions(-) diffs (15 lines): diff -r 036a4fbf9204 -r 893fa730285c nginx/ngx_http_js_module.c --- a/nginx/ngx_http_js_module.c Tue Oct 06 20:51:56 2020 +0300 +++ b/nginx/ngx_http_js_module.c Thu Oct 08 18:47:04 2020 +0300 @@ -1831,6 +1831,11 @@ ngx_http_js_ext_internal_redirect(njs_vm return NJS_ERROR; } + if (r->parent != NULL) { + njs_vm_error(vm, "internalRedirect cannot be called from a subrequest"); + return NJS_ERROR; + } + ctx = ngx_http_get_module_ctx(r, ngx_http_js_module); if (ngx_http_js_string(vm, njs_arg(args, nargs, 1), &uri) != NJS_OK) { From mdounin at mdounin.ru Thu Oct 8 20:03:10 2020 From: mdounin at mdounin.ru (Maxim Dounin) Date: Thu, 08 Oct 2020 20:03:10 +0000 Subject: [nginx] Limit req: unlocking of nodes on complex value errors. Message-ID: details: https://hg.nginx.org/nginx/rev/559d19037984 branches: changeset: 7726:559d19037984 user: Maxim Dounin date: Thu Oct 08 17:44:34 2020 +0300 description: Limit req: unlocking of nodes on complex value errors. Previously, if there were multiple limits configured, errors in ngx_http_complex_value() during processing of a non-first limit resulted in reference count leak in shared memory nodes of already processed limits. Fix is to explicity unlock relevant nodes, much like we do when rejecting requests. diffstat: src/http/modules/ngx_http_limit_req_module.c | 42 ++++++++++++++++++---------- 1 files changed, 27 insertions(+), 15 deletions(-) diffs (73 lines): diff -r d63c5373b5ba -r 559d19037984 src/http/modules/ngx_http_limit_req_module.c --- a/src/http/modules/ngx_http_limit_req_module.c Sat Oct 03 21:04:57 2020 +0300 +++ b/src/http/modules/ngx_http_limit_req_module.c Thu Oct 08 17:44:34 2020 +0300 @@ -69,6 +69,8 @@ static ngx_int_t ngx_http_limit_req_look ngx_uint_t hash, ngx_str_t *key, ngx_uint_t *ep, ngx_uint_t account); static ngx_msec_t ngx_http_limit_req_account(ngx_http_limit_req_limit_t *limits, ngx_uint_t n, ngx_uint_t *ep, ngx_http_limit_req_limit_t **limit); +static void ngx_http_limit_req_unlock(ngx_http_limit_req_limit_t *limits, + ngx_uint_t n); static void ngx_http_limit_req_expire(ngx_http_limit_req_ctx_t *ctx, ngx_uint_t n); @@ -223,6 +225,7 @@ ngx_http_limit_req_handler(ngx_http_requ ctx = limit->shm_zone->data; if (ngx_http_complex_value(r, &ctx->key, &key) != NGX_OK) { + ngx_http_limit_req_unlock(limits, n); return NGX_HTTP_INTERNAL_SERVER_ERROR; } @@ -270,21 +273,7 @@ ngx_http_limit_req_handler(ngx_http_requ &limit->shm_zone->shm.name); } - while (n--) { - ctx = limits[n].shm_zone->data; - - if (ctx->node == NULL) { - continue; - } - - ngx_shmtx_lock(&ctx->shpool->mutex); - - ctx->node->count--; - - ngx_shmtx_unlock(&ctx->shpool->mutex); - - ctx->node = NULL; - } + ngx_http_limit_req_unlock(limits, n); if (lrcf->dry_run) { r->main->limit_req_status = NGX_HTTP_LIMIT_REQ_REJECTED_DRY_RUN; @@ -613,6 +602,29 @@ ngx_http_limit_req_account(ngx_http_limi static void +ngx_http_limit_req_unlock(ngx_http_limit_req_limit_t *limits, ngx_uint_t n) +{ + ngx_http_limit_req_ctx_t *ctx; + + while (n--) { + ctx = limits[n].shm_zone->data; + + if (ctx->node == NULL) { + continue; + } + + ngx_shmtx_lock(&ctx->shpool->mutex); + + ctx->node->count--; + + ngx_shmtx_unlock(&ctx->shpool->mutex); + + ctx->node = NULL; + } +} + + +static void ngx_http_limit_req_expire(ngx_http_limit_req_ctx_t *ctx, ngx_uint_t n) { ngx_int_t excess; From harishkumarivaturi at gmail.com Sat Oct 10 11:20:47 2020 From: harishkumarivaturi at gmail.com (HARISH KUMAR Ivaturi) Date: Sat, 10 Oct 2020 13:20:47 +0200 Subject: Nginx QUIC configuration file Message-ID: Hi This is my nginx configuration file. /etc/nginx/conf.d$ sudo nano default.conf server { listen 443 ssl; listen 443 http/3 reuseport; server_name localhost; ssl_certificate cert.crt; ssl_certificate_key cert.key; # Enable all TLS versions (TLSv1.3 is required for QUIC). ssl_protocols TLSv1.3; # Add Alt-Svc header to negotiate HTTP/3. add_header Alt-Svc 'quic=":443"'; add_header QUIC-Status $quic; #charset koi8-r; #access_log /var/log/nginx/host.access.log main; location / { root /usr/share/nginx/html; index index.html index.htm; } #error_page 404 /404.html; # redirect server error pages to the static page /50x.html # error_page 500 502 503 504 /50x.html; location = /50x.html { root /usr/share/nginx/html; } After this i run sudo service nginx restart and it says Job for nginx.service failed because the control process exited with error code. See "systemctl status nginx.service" and "journalctl -xe" for details. Okk then i check in systemctl status nginx.service and the error displayed is 2020/10/10 11:18:01 [emerg] 17014#17014: invalid parameter "http3" in /etc/nginx/conf.d/default.conf:3 Later i have replaced with quic in default.conf and again the same error 2020/10/10 11:15:47 [emerg] 16898#16898: invalid parameter "quic" in /etc/nginx/conf.d/default.conf:3 I request you to help me with the configuration file i.e. default.conf . I need web response of http/3 request by running curl commands curl -k --http3 -v "https://127.0.0.1:443" BR Harish Kumar -------------- next part -------------- An HTML attachment was scrubbed... URL: From manuel.baesler at gmail.com Sat Oct 10 13:27:38 2020 From: manuel.baesler at gmail.com (Manuel) Date: Sat, 10 Oct 2020 13:27:38 +0000 Subject: Nginx QUIC configuration file In-Reply-To: References: Message-ID: <506EB80F-1C8E-4DEE-A00E-49F6BE707846@gmail.com> Hi, the error message invalid parameter http3 doesn?t correspond with your config "listen 443 http/3" so ether nginx removes these / while printing the error message or it?s really wrong. But the official documentation says https://www.nginx.com/blog/introducing-technology-preview-nginx-support-for-quic-http-3/ server { listen 443 ssl; # TCP listener for HTTP/1.1 listen 443 http3 reuseport; # UDP listener for QUIC+HTTP/3 Then your config is wrong. Where did you got the http/3 parameter? Best, Manuel > Am 10.10.2020 um 11:20 schrieb HARISH KUMAR Ivaturi : > > Hi > This is my nginx configuration file. > /etc/nginx/conf.d$ sudo nano default.conf > server { > listen 443 ssl; > listen 443 http/3 reuseport; > server_name localhost; > > ssl_certificate cert.crt; > ssl_certificate_key cert.key; > # Enable all TLS versions (TLSv1.3 is required for QUIC). > ssl_protocols TLSv1.3; > > # Add Alt-Svc header to negotiate HTTP/3. > add_header Alt-Svc 'quic=":443"'; > add_header QUIC-Status $quic; > > > #charset koi8-r; > #access_log /var/log/nginx/host.access.log main; > > location / { > root /usr/share/nginx/html; > index index.html index.htm; > } > > #error_page 404 /404.html; > > # redirect server error pages to the static page /50x.html > # > error_page 500 502 503 504 /50x.html; > location = /50x.html { > root /usr/share/nginx/html; > } > > > After this i run > sudo service nginx restart > and it says Job for nginx.service failed because the control process exited with error code. > See "systemctl status nginx.service" and "journalctl -xe" for details. > Okk then i check in systemctl status nginx.service and the error displayed is > > 2020/10/10 11:18:01 [emerg] 17014#17014: invalid parameter "http3" in /etc/nginx/conf.d/default.conf:3 > > Later i have replaced with quic in default.conf and again the same error > 2020/10/10 11:15:47 [emerg] 16898#16898: invalid parameter "quic" in /etc/nginx/conf.d/default.conf:3 > > I request you to help me with the configuration file i.e. default.conf . > I need web response of http/3 request by running curl commands > curl -k --http3 -v "https://127.0.0.1:443" > > BR > Harish Kumar > _______________________________________________ > nginx-devel mailing list > nginx-devel at nginx.org > http://mailman.nginx.org/mailman/listinfo/nginx-devel -------------- next part -------------- An HTML attachment was scrubbed... URL: From harishkumarivaturi at gmail.com Sat Oct 10 14:48:04 2020 From: harishkumarivaturi at gmail.com (HARISH KUMAR Ivaturi) Date: Sat, 10 Oct 2020 16:48:04 +0200 Subject: Nginx QUIC configuration file In-Reply-To: <506EB80F-1C8E-4DEE-A00E-49F6BE707846@gmail.com> References: <506EB80F-1C8E-4DEE-A00E-49F6BE707846@gmail.com> Message-ID: Hi I have placed http3 now. server { listen 443 ssl; # TCP listener for HTTP/1.1 listen 443 http3 reuseport; # UDP listener for QUIC+HTTP/3 ssl_protocols TLSv1.3; # QUIC requires TLS 1.3 ssl_certificate ssl/www.example.com.crt; ssl_certificate_key ssl/www.example.com.key; add_header Alt-Svc 'quic=":443"'; # Advertise that QUIC is available add_header QUIC-Status $quic; # Sent when QUIC was used } And it has the same error. 2020/10/10 14:45:24 [emerg] 25485#25485: invalid parameter "http3" in /etc/nginx/conf.d/default.conf:3 On Sat, Oct 10, 2020 at 3:27 PM Manuel wrote: > Hi, > > the error message invalid parameter http3 doesn?t correspond with your > config "listen 443 http/3" so ether nginx removes these / while printing > the error message or it?s really wrong. But the official documentation says > > > https://www.nginx.com/blog/introducing-technology-preview-nginx-support-for-quic-http-3/ > > server { > listen 443 ssl; # TCP listener for HTTP/1.1 > > listen 443 http3 reuseport; # UDP listener for QUIC+HTTP/3 > > Then your config is wrong. > > Where did you got the http/3 parameter? > > Best, > > Manuel > > > > Am 10.10.2020 um 11:20 schrieb HARISH KUMAR Ivaturi < > harishkumarivaturi at gmail.com>: > > Hi > This is my nginx configuration file. > /etc/nginx/conf.d$ sudo nano default.conf > server { > listen 443 ssl; > listen 443 http/3 reuseport; > server_name localhost; > > ssl_certificate cert.crt; > ssl_certificate_key cert.key; > # Enable all TLS versions (TLSv1.3 is required for QUIC). > ssl_protocols TLSv1.3; > > # Add Alt-Svc header to negotiate HTTP/3. > add_header Alt-Svc 'quic=":443"'; > add_header QUIC-Status $quic; > > > #charset koi8-r; > #access_log /var/log/nginx/host.access.log main; > > location / { > root /usr/share/nginx/html; > index index.html index.htm; > } > > #error_page 404 /404.html; > > # redirect server error pages to the static page /50x.html > # > error_page 500 502 503 504 /50x.html; > location = /50x.html { > root /usr/share/nginx/html; > } > > > After this i run > sudo service nginx restart > and it says Job for nginx.service failed because the control process > exited with error code. > See "systemctl status nginx.service" and "journalctl -xe" for details. > Okk then i check in systemctl status nginx.service and the error displayed > is > > 2020/10/10 11:18:01 [emerg] 17014#17014: invalid parameter "http3" in > /etc/nginx/conf.d/default.conf:3 > > Later i have replaced with quic in default.conf and again the same error > 2020/10/10 11:15:47 [emerg] 16898#16898: invalid parameter "quic" in > /etc/nginx/conf.d/default.conf:3 > > I request you to help me with the configuration file i.e. default.conf . > I need web response of http/3 request by running curl commands > curl -k --http3 -v "https://127.0.0.1:443" > > BR > Harish Kumar > > _______________________________________________ > nginx-devel mailing list > nginx-devel at nginx.org > http://mailman.nginx.org/mailman/listinfo/nginx-devel > > _______________________________________________ > nginx-devel mailing list > nginx-devel at nginx.org > http://mailman.nginx.org/mailman/listinfo/nginx-devel -------------- next part -------------- An HTML attachment was scrubbed... URL: From harishkumarivaturi at gmail.com Sat Oct 10 14:56:50 2020 From: harishkumarivaturi at gmail.com (HARISH KUMAR Ivaturi) Date: Sat, 10 Oct 2020 16:56:50 +0200 Subject: Nginx QUIC configuration file In-Reply-To: References: <506EB80F-1C8E-4DEE-A00E-49F6BE707846@gmail.com> Message-ID: Hi Sorry, this is my final default.conf server { listen 443 ssl; # TCP listener for HTTP/1.1 listen 443 http3 reuseport; # UDP listener for QUIC+HTTP/3 server_name localhost; ssl_protocols TLSv1.3; # QUIC requires TLS 1.3 ssl_certificate cert.crt; ssl_certificate_key cert.key; add_header Alt-Svc 'quic=":443"'; # Advertise that QUIC is available add_header QUIC-Status $quic; # Sent when QUIC was used } after this i run curl -k --http3 -v "https://127.0.0.1:443" And in another terminal i have my sudo tail -f /var/log/nginx/error.log 2020/10/10 14:45:24 [emerg] 25485#25485: invalid parameter "http3" in /etc/nginx/conf.d/default.conf:3 Help me with this issue. BR Harish Kumar On Sat, Oct 10, 2020 at 4:48 PM HARISH KUMAR Ivaturi < harishkumarivaturi at gmail.com> wrote: > Hi > > I have placed http3 now. > > server { > listen 443 ssl; # TCP listener for HTTP/1.1 > listen 443 http3 reuseport; # UDP listener for QUIC+HTTP/3 > > ssl_protocols TLSv1.3; # QUIC requires TLS 1.3 > ssl_certificate ssl/www.example.com.crt; > ssl_certificate_key ssl/www.example.com.key; > > add_header Alt-Svc 'quic=":443"'; # Advertise that QUIC is available > add_header QUIC-Status $quic; # Sent when QUIC was used > > } > > And it has the same error. > 2020/10/10 14:45:24 [emerg] 25485#25485: invalid parameter "http3" in > /etc/nginx/conf.d/default.conf:3 > > > On Sat, Oct 10, 2020 at 3:27 PM Manuel wrote: > >> Hi, >> >> the error message invalid parameter http3 doesn?t correspond with your >> config "listen 443 http/3" so ether nginx removes these / while printing >> the error message or it?s really wrong. But the official documentation says >> >> >> https://www.nginx.com/blog/introducing-technology-preview-nginx-support-for-quic-http-3/ >> >> server { >> listen 443 ssl; # TCP listener for HTTP/1.1 >> >> listen 443 http3 reuseport; # UDP listener for QUIC+HTTP/3 >> >> Then your config is wrong. >> >> Where did you got the http/3 parameter? >> >> Best, >> >> Manuel >> >> >> >> Am 10.10.2020 um 11:20 schrieb HARISH KUMAR Ivaturi < >> harishkumarivaturi at gmail.com>: >> >> Hi >> This is my nginx configuration file. >> /etc/nginx/conf.d$ sudo nano default.conf >> server { >> listen 443 ssl; >> listen 443 http/3 reuseport; >> server_name localhost; >> >> ssl_certificate cert.crt; >> ssl_certificate_key cert.key; >> # Enable all TLS versions (TLSv1.3 is required for QUIC). >> ssl_protocols TLSv1.3; >> >> # Add Alt-Svc header to negotiate HTTP/3. >> add_header Alt-Svc 'quic=":443"'; >> add_header QUIC-Status $quic; >> >> >> #charset koi8-r; >> #access_log /var/log/nginx/host.access.log main; >> >> location / { >> root /usr/share/nginx/html; >> index index.html index.htm; >> } >> >> #error_page 404 /404.html; >> >> # redirect server error pages to the static page /50x.html >> # >> error_page 500 502 503 504 /50x.html; >> location = /50x.html { >> root /usr/share/nginx/html; >> } >> >> >> After this i run >> sudo service nginx restart >> and it says Job for nginx.service failed because the control process >> exited with error code. >> See "systemctl status nginx.service" and "journalctl -xe" for details. >> Okk then i check in systemctl status nginx.service and the error >> displayed is >> >> 2020/10/10 11:18:01 [emerg] 17014#17014: invalid parameter "http3" in >> /etc/nginx/conf.d/default.conf:3 >> >> Later i have replaced with quic in default.conf and again the same error >> 2020/10/10 11:15:47 [emerg] 16898#16898: invalid parameter "quic" in >> /etc/nginx/conf.d/default.conf:3 >> >> I request you to help me with the configuration file i.e. default.conf . >> I need web response of http/3 request by running curl commands >> curl -k --http3 -v "https://127.0.0.1:443" >> >> BR >> Harish Kumar >> >> _______________________________________________ >> nginx-devel mailing list >> nginx-devel at nginx.org >> http://mailman.nginx.org/mailman/listinfo/nginx-devel >> >> _______________________________________________ >> nginx-devel mailing list >> nginx-devel at nginx.org >> http://mailman.nginx.org/mailman/listinfo/nginx-devel > > -------------- next part -------------- An HTML attachment was scrubbed... URL: From maxim at nginx.com Sat Oct 10 15:00:49 2020 From: maxim at nginx.com (Maxim Konovalov) Date: Sat, 10 Oct 2020 18:00:49 +0300 Subject: Nginx QUIC configuration file In-Reply-To: References: <506EB80F-1C8E-4DEE-A00E-49F6BE707846@gmail.com> Message-ID: On 10.10.2020 17:56, HARISH KUMAR Ivaturi wrote: > Hi > > Sorry, this is my final default.conf > > server { > ? ? listen 443 ssl; ? ? ? ? ? ? ?# TCP listener for HTTP/1.1 > ? ? listen 443 http3 reuseport; ?# UDP listener for QUIC+HTTP/3 > ? ? server_name ?localhost; > ? ? ssl_protocols ? ? ? TLSv1.3; # QUIC requires TLS 1.3 > ? ? ssl_certificate ? ? cert.crt; > ? ? ssl_certificate_key cert.key; > > ? ? add_header Alt-Svc 'quic=":443"'; # Advertise that QUIC is available > ? ? add_header QUIC-Status $quic; ? ? # Sent when QUIC was used > } > > after this i run? > curl -k --http3 -v "https://127.0.0.1:443" > > And in another terminal i have my? > ?sudo tail -f /var/log/nginx/error.log > > 2020/10/10 14:45:24 [emerg] 25485#25485: invalid parameter "http3" in > /etc/nginx/conf.d/default.conf:3 > > Help me with this issue. > You probably complied nginx from the vanilla repo while you should take it from this one: https://hg.nginx.org/nginx-quic/file/quic See https://quic.nginx.org/ for more information. -- Maxim Konovalov From harishkumarivaturi at gmail.com Sat Oct 10 15:04:42 2020 From: harishkumarivaturi at gmail.com (HARISH KUMAR Ivaturi) Date: Sat, 10 Oct 2020 17:04:42 +0200 Subject: Nginx QUIC configuration file In-Reply-To: References: <506EB80F-1C8E-4DEE-A00E-49F6BE707846@gmail.com> Message-ID: Hi I have installed nginx with http/3 with mercurial. I just need a proper default.conf which is located in /etc/nginx/conf.d and in default.conf BR Harish Kumar On Sat, Oct 10, 2020 at 5:00 PM Maxim Konovalov wrote: > On 10.10.2020 17:56, HARISH KUMAR Ivaturi wrote: > > Hi > > > > Sorry, this is my final default.conf > > > > server { > > listen 443 ssl; # TCP listener for HTTP/1.1 > > listen 443 http3 reuseport; # UDP listener for QUIC+HTTP/3 > > server_name localhost; > > ssl_protocols TLSv1.3; # QUIC requires TLS 1.3 > > ssl_certificate cert.crt; > > ssl_certificate_key cert.key; > > > > add_header Alt-Svc 'quic=":443"'; # Advertise that QUIC is available > > add_header QUIC-Status $quic; # Sent when QUIC was used > > } > > > > after this i run > > curl -k --http3 -v "https://127.0.0.1:443" > > > > And in another terminal i have my > > sudo tail -f /var/log/nginx/error.log > > > > 2020/10/10 14:45:24 [emerg] 25485#25485: invalid parameter "http3" in > > /etc/nginx/conf.d/default.conf:3 > > > > Help me with this issue. > > > You probably complied nginx from the vanilla repo while you should take > it from this one: > > https://hg.nginx.org/nginx-quic/file/quic > > See https://quic.nginx.org/ for more information. > > -- > Maxim Konovalov > -------------- next part -------------- An HTML attachment was scrubbed... URL: From manuel.baesler at gmail.com Sat Oct 10 15:18:30 2020 From: manuel.baesler at gmail.com (Manuel) Date: Sat, 10 Oct 2020 15:18:30 +0000 Subject: Nginx QUIC configuration file In-Reply-To: References: <506EB80F-1C8E-4DEE-A00E-49F6BE707846@gmail.com> Message-ID: Hi, can you verify that the nginx binary that is using the http3 config is the nginx that can do http3? For this you have to locate the systemd file that starts the nginx server and then look into the file to which path the executable point. Then run minus minus version on the binary. > Am 10.10.2020 um 15:04 schrieb HARISH KUMAR Ivaturi : > > Hi > > I have installed nginx with http/3 with mercurial. > I just need a proper default.conf which is located in /etc/nginx/conf.d and in default.conf > > BR > Harish Kumar > >> On Sat, Oct 10, 2020 at 5:00 PM Maxim Konovalov wrote: >> On 10.10.2020 17:56, HARISH KUMAR Ivaturi wrote: >> > Hi >> > >> > Sorry, this is my final default.conf >> > >> > server { >> > listen 443 ssl; # TCP listener for HTTP/1.1 >> > listen 443 http3 reuseport; # UDP listener for QUIC+HTTP/3 >> > server_name localhost; >> > ssl_protocols TLSv1.3; # QUIC requires TLS 1.3 >> > ssl_certificate cert.crt; >> > ssl_certificate_key cert.key; >> > >> > add_header Alt-Svc 'quic=":443"'; # Advertise that QUIC is available >> > add_header QUIC-Status $quic; # Sent when QUIC was used >> > } >> > >> > after this i run >> > curl -k --http3 -v "https://127.0.0.1:443" >> > >> > And in another terminal i have my >> > sudo tail -f /var/log/nginx/error.log >> > >> > 2020/10/10 14:45:24 [emerg] 25485#25485: invalid parameter "http3" in >> > /etc/nginx/conf.d/default.conf:3 >> > >> > Help me with this issue. >> > >> You probably complied nginx from the vanilla repo while you should take >> it from this one: >> >> https://hg.nginx.org/nginx-quic/file/quic >> >> See https://quic.nginx.org/ for more information. >> >> -- >> Maxim Konovalov > _______________________________________________ > nginx-devel mailing list > nginx-devel at nginx.org > http://mailman.nginx.org/mailman/listinfo/nginx-devel -------------- next part -------------- An HTML attachment was scrubbed... URL: From manuel.baesler at gmail.com Sat Oct 10 15:20:41 2020 From: manuel.baesler at gmail.com (Manuel) Date: Sat, 10 Oct 2020 15:20:41 +0000 Subject: Nginx QUIC configuration file In-Reply-To: References: <506EB80F-1C8E-4DEE-A00E-49F6BE707846@gmail.com> Message-ID: <7D98691D-7C21-4396-BCFC-51E29593246D@gmail.com> Sorry, it?s binary -V (uppercase v) > Am 10.10.2020 um 15:04 schrieb HARISH KUMAR Ivaturi : > > Hi > > I have installed nginx with http/3 with mercurial. > I just need a proper default.conf which is located in /etc/nginx/conf.d and in default.conf > > BR > Harish Kumar > >> On Sat, Oct 10, 2020 at 5:00 PM Maxim Konovalov wrote: >> On 10.10.2020 17:56, HARISH KUMAR Ivaturi wrote: >> > Hi >> > >> > Sorry, this is my final default.conf >> > >> > server { >> > listen 443 ssl; # TCP listener for HTTP/1.1 >> > listen 443 http3 reuseport; # UDP listener for QUIC+HTTP/3 >> > server_name localhost; >> > ssl_protocols TLSv1.3; # QUIC requires TLS 1.3 >> > ssl_certificate cert.crt; >> > ssl_certificate_key cert.key; >> > >> > add_header Alt-Svc 'quic=":443"'; # Advertise that QUIC is available >> > add_header QUIC-Status $quic; # Sent when QUIC was used >> > } >> > >> > after this i run >> > curl -k --http3 -v "https://127.0.0.1:443" >> > >> > And in another terminal i have my >> > sudo tail -f /var/log/nginx/error.log >> > >> > 2020/10/10 14:45:24 [emerg] 25485#25485: invalid parameter "http3" in >> > /etc/nginx/conf.d/default.conf:3 >> > >> > Help me with this issue. >> > >> You probably complied nginx from the vanilla repo while you should take >> it from this one: >> >> https://hg.nginx.org/nginx-quic/file/quic >> >> See https://quic.nginx.org/ for more information. >> >> -- >> Maxim Konovalov > _______________________________________________ > nginx-devel mailing list > nginx-devel at nginx.org > http://mailman.nginx.org/mailman/listinfo/nginx-devel -------------- next part -------------- An HTML attachment was scrubbed... URL: From harishkumarivaturi at gmail.com Sat Oct 10 15:23:28 2020 From: harishkumarivaturi at gmail.com (HARISH KUMAR Ivaturi) Date: Sat, 10 Oct 2020 17:23:28 +0200 Subject: Nginx QUIC configuration file In-Reply-To: References: <506EB80F-1C8E-4DEE-A00E-49F6BE707846@gmail.com> Message-ID: Hi Manuel I am not sure if you remember but with your help i have installed Nginx with HTTP/3 by installing boringssl. After all the process done you have suggested me to do sudo cp objs/nginx /usr/local/bin/ So now. $ nginx -V nginx version: nginx/1.19.1 built by gcc 7.5.0 (Ubuntu 7.5.0-3ubuntu1~18.04) built with OpenSSL 1.1.0 (compatible; BoringSSL) (running with BoringSSL) TLS SNI support enabled configure arguments: --with-debug --with-http_v3_module --with-cc-opt=-I../boringssl/include --with-ld-opt='-L../boringssl/build/ssl -L../boringssl/build/crypto' On Sat, Oct 10, 2020 at 5:18 PM Manuel wrote: > Hi, > > can you verify that the nginx binary that is using the http3 config is the > nginx that can do http3? > For this you have to locate the systemd file that starts the nginx server > and then look into the file to which path the executable point. Then run > minus minus version on the binary. > > Am 10.10.2020 um 15:04 schrieb HARISH KUMAR Ivaturi < > harishkumarivaturi at gmail.com>: > > Hi > > I have installed nginx with http/3 with mercurial. > I just need a proper default.conf which is located in /etc/nginx/conf.d > and in default.conf > > BR > Harish Kumar > > On Sat, Oct 10, 2020 at 5:00 PM Maxim Konovalov wrote: > >> On 10.10.2020 17:56, HARISH KUMAR Ivaturi wrote: >> > Hi >> > >> > Sorry, this is my final default.conf >> > >> > server { >> > listen 443 ssl; # TCP listener for HTTP/1.1 >> > listen 443 http3 reuseport; # UDP listener for QUIC+HTTP/3 >> > server_name localhost; >> > ssl_protocols TLSv1.3; # QUIC requires TLS 1.3 >> > ssl_certificate cert.crt; >> > ssl_certificate_key cert.key; >> > >> > add_header Alt-Svc 'quic=":443"'; # Advertise that QUIC is available >> > add_header QUIC-Status $quic; # Sent when QUIC was used >> > } >> > >> > after this i run >> > curl -k --http3 -v "https://127.0.0.1:443" >> > >> > And in another terminal i have my >> > sudo tail -f /var/log/nginx/error.log >> > >> > 2020/10/10 14:45:24 [emerg] 25485#25485: invalid parameter "http3" in >> > /etc/nginx/conf.d/default.conf:3 >> > >> > Help me with this issue. >> > >> You probably complied nginx from the vanilla repo while you should take >> it from this one: >> >> https://hg.nginx.org/nginx-quic/file/quic >> >> See https://quic.nginx.org/ for more information. >> >> -- >> Maxim Konovalov >> > _______________________________________________ > nginx-devel mailing list > nginx-devel at nginx.org > http://mailman.nginx.org/mailman/listinfo/nginx-devel > > _______________________________________________ > nginx-devel mailing list > nginx-devel at nginx.org > http://mailman.nginx.org/mailman/listinfo/nginx-devel -------------- next part -------------- An HTML attachment was scrubbed... URL: From geert at hendrickx.be Sun Oct 11 08:04:06 2020 From: geert at hendrickx.be (Geert Hendrickx) Date: Sun, 11 Oct 2020 10:04:06 +0200 Subject: [PATCH] Portability: use `uname -n` instead of `hostname` Message-ID: <20201011080406.GA18953@vera.ghen.be> # HG changeset patch # User Geert Hendrickx # Date 1602402793 -7200 # Sun Oct 11 09:53:13 2020 +0200 # Node ID 53f3eae1dc9a4f901f3d4da67daa0181d13dc222 # Parent 4e06441193417456bf24b213d15da12a90322f4c Portability: use `uname -n` instead of `hostname`. As `hostname` is not defined by POSIX and not available by default on some modern Linux distro's (Arch, Fedora), making some tests fail. Using `uname -n` instead fixes this in a portable way. diff -r 4e0644119341 -r 53f3eae1dc9a mail_error_log.t --- a/mail_error_log.t Tue Oct 06 20:52:06 2020 +0100 +++ b/mail_error_log.t Sun Oct 11 09:53:13 2020 +0200 @@ -233,7 +233,7 @@ ok($sec < 60, "$desc valid seconds"); ok(defined($host), "$desc has host"); - chomp(my $hostname = lc `hostname`); + chomp(my $hostname = lc `uname -n`); is($host , $hostname, "$desc valid host"); ok(defined($tag), "$desc has tag"); diff -r 4e0644119341 -r 53f3eae1dc9a stream_access_log.t --- a/stream_access_log.t Tue Oct 06 20:52:06 2020 +0100 +++ b/stream_access_log.t Sun Oct 11 09:53:13 2020 +0200 @@ -158,7 +158,7 @@ ok($t->read_file('complex.log'), 'if with complex value'); ok($t->read_file('varlog_3.log'), 'variable in file'); -chomp(my $hostname = lc `hostname`); +chomp(my $hostname = lc `uname -n`); like($t->read_file('vars.log'), qr/^\d+:[\d.]+:$hostname:\d+$/, 'log vars'); is($t->read_file('addr.log'), "$escaped:$lhost:$lport:127.0.0.1:$dport:127.0.0.1:$uport\n", diff -r 4e0644119341 -r 53f3eae1dc9a stream_error_log.t --- a/stream_error_log.t Tue Oct 06 20:52:06 2020 +0100 +++ b/stream_error_log.t Sun Oct 11 09:53:13 2020 +0200 @@ -241,7 +241,7 @@ ok($sec < 60, "$desc valid seconds"); ok(defined($host), "$desc has host"); - chomp(my $hostname = lc `hostname`); + chomp(my $hostname = lc `uname -n`); is($host , $hostname, "$desc valid host"); ok(defined($tag), "$desc has tag"); diff -r 4e0644119341 -r 53f3eae1dc9a stream_variables.t --- a/stream_variables.t Tue Oct 06 20:52:06 2020 +0100 +++ b/stream_variables.t Sun Oct 11 09:53:13 2020 +0200 @@ -80,7 +80,7 @@ ############################################################################### -chomp(my $hostname = lc `hostname`); +chomp(my $hostname = lc `uname -n`); like(stream('127.0.0.1:' . port(8080))->read(), qr/^\d+:[\d.]+:$hostname:\d+:0$/, 'vars'); diff -r 4e0644119341 -r 53f3eae1dc9a syslog.t --- a/syslog.t Tue Oct 06 20:52:06 2020 +0100 +++ b/syslog.t Sun Oct 11 09:53:13 2020 +0200 @@ -321,7 +321,7 @@ ok($sec < 60, "$desc valid seconds"); ok(defined($host), "$desc has host"); - chomp(my $hostname = lc `hostname`); + chomp(my $hostname = lc `uname -n`); is($host , $hostname, "$desc valid host"); ok(defined($tag), "$desc has tag"); From geert at hendrickx.be Sun Oct 11 08:07:31 2020 From: geert at hendrickx.be (Geert Hendrickx) Date: Sun, 11 Oct 2020 10:07:31 +0200 Subject: [PATCH] Portability: use `uname -n` instead of `hostname` In-Reply-To: <20201011080406.GA18953@vera.ghen.be> References: <20201011080406.GA18953@vera.ghen.be> Message-ID: <20201011080731.GA18971@vera.ghen.be> PS: This patch is for the nginx-test repo. Geert On Sun, Oct 11, 2020 at 10:04:06 +0200, Geert Hendrickx wrote: > # HG changeset patch > # User Geert Hendrickx > # Date 1602402793 -7200 > # Sun Oct 11 09:53:13 2020 +0200 > # Node ID 53f3eae1dc9a4f901f3d4da67daa0181d13dc222 > # Parent 4e06441193417456bf24b213d15da12a90322f4c > Portability: use `uname -n` instead of `hostname`. > > As `hostname` is not defined by POSIX and not available > by default on some modern Linux distro's (Arch, Fedora), > making some tests fail. Using `uname -n` instead fixes > this in a portable way. -- geert.hendrickx.be :: geert at hendrickx.be :: PGP: 0xC4BB9E9F This e-mail was composed using 100% recycled spam messages! From manuel.baesler at gmail.com Sun Oct 11 23:07:19 2020 From: manuel.baesler at gmail.com (Manuel) Date: Sun, 11 Oct 2020 23:07:19 +0000 Subject: Nginx QUIC configuration file In-Reply-To: References: <506EB80F-1C8E-4DEE-A00E-49F6BE707846@gmail.com> Message-ID: <93469815-9DD9-48BC-93FC-757E9265CC3F@gmail.com> Hi, please recompile nginx with the latest version of boring and nginx. Probably also with minus minus prefix set to /etc/nginx 2nd step would be to find out which exact nginx binary the cmd 'service nginx restart' is executing. Alternative would be to execute the compiled binary directly. I tried it out today and so far nginx and Google Chrome Canary with enabled quic h3-29 draft are talking http3 via quic. This is the config: events {} http { log_format quic '$remote_addr - $remote_user [$time_local] ' '"$request" $status $body_bytes_sent ' '"$http_referer" "$http_user_agent" "$quic" "$http3"'; access_log logs/access.log quic; error_log logs/error.log debug; server { root /var/www/html; server_name xyz ; # for better compatibility it's recommended # to use the same port for quic and https listen 443 http3 reuseport; listen 443 ssl; ssl_protocols TLSv1.3; ssl_certificate ... ssl_certificate_key ... include /etc/letsencrypt/options-ssl-nginx.conf; # managed by Certbot ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem; # managed by Certbot location / { # required for browsers to direct them into quic port add_header X-http3-status "http3 is $http3"; add_header X-quic-status "quic is $quic"; add_header Alt-Svc '$http3=":443"; ma=86400'; # add_header Alt-Svc 'quic=":443"'; } } } > Am 10.10.2020 um 15:23 schrieb HARISH KUMAR Ivaturi : > > Hi Manuel > > I am not sure if you remember but with your help i have installed Nginx with HTTP/3 by installing boringssl. > After all the process done you have suggested me to do > sudo cp objs/nginx /usr/local/bin/ > > So now. > > > $ nginx -V > nginx version: nginx/1.19.1 > built by gcc 7.5.0 (Ubuntu 7.5.0-3ubuntu1~18.04) > built with OpenSSL 1.1.0 (compatible; BoringSSL) (running with BoringSSL) > TLS SNI support enabled > configure arguments: --with-debug --with-http_v3_module --with-cc-opt=-I../boringssl/include --with-ld-opt='-L../boringssl/build/ssl -L../boringssl/build/crypto' > >> On Sat, Oct 10, 2020 at 5:18 PM Manuel wrote: >> Hi, >> >> can you verify that the nginx binary that is using the http3 config is the nginx that can do http3? >> For this you have to locate the systemd file that starts the nginx server and then look into the file to which path the executable point. Then run minus minus version on the binary. >> >>> Am 10.10.2020 um 15:04 schrieb HARISH KUMAR Ivaturi : >>> >>> Hi >>> >>> I have installed nginx with http/3 with mercurial. >>> I just need a proper default.conf which is located in /etc/nginx/conf.d and in default.conf >>> >>> BR >>> Harish Kumar >>> >>>> On Sat, Oct 10, 2020 at 5:00 PM Maxim Konovalov wrote: >>>> On 10.10.2020 17:56, HARISH KUMAR Ivaturi wrote: >>>> > Hi >>>> > >>>> > Sorry, this is my final default.conf >>>> > >>>> > server { >>>> > listen 443 ssl; # TCP listener for HTTP/1.1 >>>> > listen 443 http3 reuseport; # UDP listener for QUIC+HTTP/3 >>>> > server_name localhost; >>>> > ssl_protocols TLSv1.3; # QUIC requires TLS 1.3 >>>> > ssl_certificate cert.crt; >>>> > ssl_certificate_key cert.key; >>>> > >>>> > add_header Alt-Svc 'quic=":443"'; # Advertise that QUIC is available >>>> > add_header QUIC-Status $quic; # Sent when QUIC was used >>>> > } >>>> > >>>> > after this i run >>>> > curl -k --http3 -v "https://127.0.0.1:443" >>>> > >>>> > And in another terminal i have my >>>> > sudo tail -f /var/log/nginx/error.log >>>> > >>>> > 2020/10/10 14:45:24 [emerg] 25485#25485: invalid parameter "http3" in >>>> > /etc/nginx/conf.d/default.conf:3 >>>> > >>>> > Help me with this issue. >>>> > >>>> You probably complied nginx from the vanilla repo while you should take >>>> it from this one: >>>> >>>> https://hg.nginx.org/nginx-quic/file/quic >>>> >>>> See https://quic.nginx.org/ for more information. >>>> >>>> -- >>>> Maxim Konovalov >>> _______________________________________________ >>> nginx-devel mailing list >>> nginx-devel at nginx.org >>> http://mailman.nginx.org/mailman/listinfo/nginx-devel >> _______________________________________________ >> nginx-devel mailing list >> nginx-devel at nginx.org >> http://mailman.nginx.org/mailman/listinfo/nginx-devel > _______________________________________________ > nginx-devel mailing list > nginx-devel at nginx.org > http://mailman.nginx.org/mailman/listinfo/nginx-devel -------------- next part -------------- An HTML attachment was scrubbed... URL: From harishkumarivaturi at gmail.com Sun Oct 11 23:15:54 2020 From: harishkumarivaturi at gmail.com (HARISH KUMAR Ivaturi) Date: Mon, 12 Oct 2020 01:15:54 +0200 Subject: Nginx QUIC configuration file In-Reply-To: <93469815-9DD9-48BC-93FC-757E9265CC3F@gmail.com> References: <506EB80F-1C8E-4DEE-A00E-49F6BE707846@gmail.com> <93469815-9DD9-48BC-93FC-757E9265CC3F@gmail.com> Message-ID: Hi Manuel Thank you for the solution. I think it is a configuration file related with Google Chrome Canary browser. Does the same config file work if I want to get a response in the terminal using curl command. command used: curl -k -v --http3 "https://127.0.0.1:443" And the reason why i need a proper config file is , later i want to make OpenStack rely with nginx (with HTTP/3) web server so there could be an interaction between them. I hope you understand. I sincerely thank you for your reply, but if it works for this Cloud then it would be helpful. BR Harish Kumar On Mon, Oct 12, 2020 at 1:07 AM Manuel wrote: > Hi, > > please recompile nginx with the latest version of boring and nginx. > Probably also with minus minus prefix set to /etc/nginx > 2nd step would be to find out which exact nginx binary the cmd 'service > nginx restart' is executing. Alternative would be to execute the compiled > binary directly. > > I tried it out today and so far nginx and Google Chrome Canary with > enabled quic h3-29 draft are talking http3 via quic. > > This is the config: > > events {} > > http { > > log_format quic '$remote_addr - $remote_user [$time_local] ' > > > > '"$request" $status $body_bytes_sent ' > > > > '"$http_referer" "$http_user_agent" "$quic" > "$http3"'; > > > > access_log logs/access.log quic; > > error_log logs/error.log debug; > > > > server { > > root /var/www/html; > > > > server_name xyz ; > > > > # for better compatibility it's recommended > > > > # to use the same port for quic and https > > listen 443 http3 reuseport; > > listen 443 ssl; > > ssl_protocols TLSv1.3; > > > > ssl_certificate ... > > ssl_certificate_key ... > > include /etc/letsencrypt/options-ssl-nginx.conf; # managed by Certbot > > ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem; # managed by Certbot > > > > location / { > > # required for browsers to direct them into quic port > > > > add_header X-http3-status "http3 is $http3"; > > add_header X-quic-status "quic is $quic"; > > add_header Alt-Svc '$http3=":443"; ma=86400'; > > # add_header Alt-Svc 'quic=":443"'; > > } > > } > > } > > > > Am 10.10.2020 um 15:23 schrieb HARISH KUMAR Ivaturi < > harishkumarivaturi at gmail.com>: > > Hi Manuel > > I am not sure if you remember but with your help i have installed Nginx > with HTTP/3 by installing boringssl. > After all the process done you have suggested me to do > sudo cp objs/nginx /usr/local/bin/ > > So now. > > > $ nginx -V > nginx version: nginx/1.19.1 > built by gcc 7.5.0 (Ubuntu 7.5.0-3ubuntu1~18.04) > built with OpenSSL 1.1.0 (compatible; BoringSSL) (running with BoringSSL) > TLS SNI support enabled > configure arguments: --with-debug --with-http_v3_module > --with-cc-opt=-I../boringssl/include > --with-ld-opt='-L../boringssl/build/ssl -L../boringssl/build/crypto' > > On Sat, Oct 10, 2020 at 5:18 PM Manuel wrote: > >> Hi, >> >> can you verify that the nginx binary that is using the http3 config is >> the nginx that can do http3? >> For this you have to locate the systemd file that starts the nginx server >> and then look into the file to which path the executable point. Then run >> minus minus version on the binary. >> >> Am 10.10.2020 um 15:04 schrieb HARISH KUMAR Ivaturi < >> harishkumarivaturi at gmail.com>: >> >> Hi >> >> I have installed nginx with http/3 with mercurial. >> I just need a proper default.conf which is located in /etc/nginx/conf.d >> and in default.conf >> >> BR >> Harish Kumar >> >> On Sat, Oct 10, 2020 at 5:00 PM Maxim Konovalov wrote: >> >>> On 10.10.2020 17:56, HARISH KUMAR Ivaturi wrote: >>> > Hi >>> > >>> > Sorry, this is my final default.conf >>> > >>> > server { >>> > listen 443 ssl; # TCP listener for HTTP/1.1 >>> > listen 443 http3 reuseport; # UDP listener for QUIC+HTTP/3 >>> > server_name localhost; >>> > ssl_protocols TLSv1.3; # QUIC requires TLS 1.3 >>> > ssl_certificate cert.crt; >>> > ssl_certificate_key cert.key; >>> > >>> > add_header Alt-Svc 'quic=":443"'; # Advertise that QUIC is >>> available >>> > add_header QUIC-Status $quic; # Sent when QUIC was used >>> > } >>> > >>> > after this i run >>> > curl -k --http3 -v "https://127.0.0.1:443" >>> > >>> > And in another terminal i have my >>> > sudo tail -f /var/log/nginx/error.log >>> > >>> > 2020/10/10 14:45:24 [emerg] 25485#25485: invalid parameter "http3" in >>> > /etc/nginx/conf.d/default.conf:3 >>> > >>> > Help me with this issue. >>> > >>> You probably complied nginx from the vanilla repo while you should take >>> it from this one: >>> >>> https://hg.nginx.org/nginx-quic/file/quic >>> >>> See https://quic.nginx.org/ for more information. >>> >>> -- >>> Maxim Konovalov >>> >> _______________________________________________ >> nginx-devel mailing list >> nginx-devel at nginx.org >> http://mailman.nginx.org/mailman/listinfo/nginx-devel >> >> _______________________________________________ >> nginx-devel mailing list >> nginx-devel at nginx.org >> http://mailman.nginx.org/mailman/listinfo/nginx-devel > > _______________________________________________ > nginx-devel mailing list > nginx-devel at nginx.org > http://mailman.nginx.org/mailman/listinfo/nginx-devel > > _______________________________________________ > nginx-devel mailing list > nginx-devel at nginx.org > http://mailman.nginx.org/mailman/listinfo/nginx-devel -------------- next part -------------- An HTML attachment was scrubbed... URL: From turchanov at farpost.com Mon Oct 12 04:10:26 2020 From: turchanov at farpost.com (turchanov at farpost.com) Date: Mon, 12 Oct 2020 14:10:26 +1000 Subject: [PATCH] Conditional application of limit_conn directive In-Reply-To: <54c602bf82cd03c12ca51bd30924578d@vl.ru> References: <37619b9652dccd8e09a2affe139d063c@vl.ru> <20200922131923.GE1136@mdounin.ru> <54c602bf82cd03c12ca51bd30924578d@vl.ru> Message-ID: Hello! Since you didn't reply to my reasoning for this patch, I have to ask more directly. I didn't convince you of the usefulness of this conditional mode and you are not going to apply the patch, are you? And if so, I could try to implement placement of the "limit_conn" into "if" context (not sure that I will be able to do that but at least I can try to). Will you agree to that feature? _Any_ feedback is welcomed. With best regards, Sergei Turchanov. turchanov at farpost.com ????? 2020-09-23 00:39: > Hello! > > ... > Maxim Dounin ????? 2020-09-22 23:19: >> Quoting the documentation (http://nginx.org/r/limit_conn_zone): >> >> : Requests with an empty key value are not accounted. >> >> That is, limit_conn can be used conditionally without any >> code changes. The same applies to limit_req. > > Yes, I know about that feature. The problem with that approach is a > complication of the > process to compute the value of a "key". We tried that before (with a > cascade of "map" directives) > and configuration became unreadable and very hard to understand when > you add another indirection > level to force a "key" to be an empty value depending on another > condition. That was an incentive > for this patch. > This is especially true when there are several "limit_conn" directives > in one location > to limit user sessions by different identification attributes (and all > of those attirbutes > need to be "emptied" on a condition). > > With best regards, > Sergei Turchanov. > _______________________________________________ > nginx-devel mailing list > nginx-devel at nginx.org > http://mailman.nginx.org/mailman/listinfo/nginx-devel From manuel.baesler at gmail.com Mon Oct 12 06:03:32 2020 From: manuel.baesler at gmail.com (Manuel) Date: Mon, 12 Oct 2020 06:03:32 +0000 Subject: Nginx QUIC configuration file In-Reply-To: References: <506EB80F-1C8E-4DEE-A00E-49F6BE707846@gmail.com> <93469815-9DD9-48BC-93FC-757E9265CC3F@gmail.com> Message-ID: <364990EC-ED1D-442E-85D5-B197DC27CC8A@gmail.com> Hi, the config file is from the nginx quic repository and from the blog post. It should work for every client that implements at least the 29 draft. Best, Manuel > Am 11.10.2020 um 23:15 schrieb HARISH KUMAR Ivaturi : > > Hi Manuel > > Thank you for the solution. I think it is a configuration file related with Google Chrome Canary browser. > Does the same config file work if I want to get a response in the terminal using curl command. > command used: > > curl -k -v --http3 "https://127.0.0.1:443" > > And the reason why i need a proper config file is , later i want to make OpenStack rely with nginx (with HTTP/3) web server so there could be an interaction between them. I hope you understand. > > I sincerely thank you for your reply, but if it works for this Cloud then it would be helpful. > > BR > Harish Kumar > >> On Mon, Oct 12, 2020 at 1:07 AM Manuel wrote: >> Hi, >> >> please recompile nginx with the latest version of boring and nginx. Probably also with minus minus prefix set to /etc/nginx >> 2nd step would be to find out which exact nginx binary the cmd 'service nginx restart' is executing. Alternative would be to execute the compiled binary directly. >> >> I tried it out today and so far nginx and Google Chrome Canary with enabled quic h3-29 draft are talking http3 via quic. >> >> This is the config: >> >> events {} >> http { >> log_format quic '$remote_addr - $remote_user [$time_local] ' >> >> '"$request" $status $body_bytes_sent ' >> >> '"$http_referer" "$http_user_agent" "$quic" "$http3"'; >> >> access_log logs/access.log quic; >> error_log logs/error.log debug; >> >> server { >> root /var/www/html; >> >> server_name xyz ; >> >> # for better compatibility it's recommended >> >> # to use the same port for quic and https >> listen 443 http3 reuseport; >> listen 443 ssl; >> ssl_protocols TLSv1.3; >> >> ssl_certificate ... >> ssl_certificate_key ... >> include /etc/letsencrypt/options-ssl-nginx.conf; # managed by Certbot >> ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem; # managed by Certbot >> >> location / { >> # required for browsers to direct them into quic port >> >> add_header X-http3-status "http3 is $http3"; >> add_header X-quic-status "quic is $quic"; >> add_header Alt-Svc '$http3=":443"; ma=86400'; >> # add_header Alt-Svc 'quic=":443"'; >> } >> } >> } >> >> >>> Am 10.10.2020 um 15:23 schrieb HARISH KUMAR Ivaturi : >>> >>> Hi Manuel >>> >>> I am not sure if you remember but with your help i have installed Nginx with HTTP/3 by installing boringssl. >>> After all the process done you have suggested me to do >>> sudo cp objs/nginx /usr/local/bin/ >>> >>> So now. >>> >>> >>> $ nginx -V >>> nginx version: nginx/1.19.1 >>> built by gcc 7.5.0 (Ubuntu 7.5.0-3ubuntu1~18.04) >>> built with OpenSSL 1.1.0 (compatible; BoringSSL) (running with BoringSSL) >>> TLS SNI support enabled >>> configure arguments: --with-debug --with-http_v3_module --with-cc-opt=-I../boringssl/include --with-ld-opt='-L../boringssl/build/ssl -L../boringssl/build/crypto' >>> >>>> On Sat, Oct 10, 2020 at 5:18 PM Manuel wrote: >>>> Hi, >>>> >>>> can you verify that the nginx binary that is using the http3 config is the nginx that can do http3? >>>> For this you have to locate the systemd file that starts the nginx server and then look into the file to which path the executable point. Then run minus minus version on the binary. >>>> >>>>> Am 10.10.2020 um 15:04 schrieb HARISH KUMAR Ivaturi : >>>>> >>>>> Hi >>>>> >>>>> I have installed nginx with http/3 with mercurial. >>>>> I just need a proper default.conf which is located in /etc/nginx/conf.d and in default.conf >>>>> >>>>> BR >>>>> Harish Kumar >>>>> >>>>>> On Sat, Oct 10, 2020 at 5:00 PM Maxim Konovalov wrote: >>>>>> On 10.10.2020 17:56, HARISH KUMAR Ivaturi wrote: >>>>>> > Hi >>>>>> > >>>>>> > Sorry, this is my final default.conf >>>>>> > >>>>>> > server { >>>>>> > listen 443 ssl; # TCP listener for HTTP/1.1 >>>>>> > listen 443 http3 reuseport; # UDP listener for QUIC+HTTP/3 >>>>>> > server_name localhost; >>>>>> > ssl_protocols TLSv1.3; # QUIC requires TLS 1.3 >>>>>> > ssl_certificate cert.crt; >>>>>> > ssl_certificate_key cert.key; >>>>>> > >>>>>> > add_header Alt-Svc 'quic=":443"'; # Advertise that QUIC is available >>>>>> > add_header QUIC-Status $quic; # Sent when QUIC was used >>>>>> > } >>>>>> > >>>>>> > after this i run >>>>>> > curl -k --http3 -v "https://127.0.0.1:443" >>>>>> > >>>>>> > And in another terminal i have my >>>>>> > sudo tail -f /var/log/nginx/error.log >>>>>> > >>>>>> > 2020/10/10 14:45:24 [emerg] 25485#25485: invalid parameter "http3" in >>>>>> > /etc/nginx/conf.d/default.conf:3 >>>>>> > >>>>>> > Help me with this issue. >>>>>> > >>>>>> You probably complied nginx from the vanilla repo while you should take >>>>>> it from this one: >>>>>> >>>>>> https://hg.nginx.org/nginx-quic/file/quic >>>>>> >>>>>> See https://quic.nginx.org/ for more information. >>>>>> >>>>>> -- >>>>>> Maxim Konovalov >>>>> _______________________________________________ >>>>> nginx-devel mailing list >>>>> nginx-devel at nginx.org >>>>> http://mailman.nginx.org/mailman/listinfo/nginx-devel >>>> _______________________________________________ >>>> nginx-devel mailing list >>>> nginx-devel at nginx.org >>>> http://mailman.nginx.org/mailman/listinfo/nginx-devel >>> _______________________________________________ >>> nginx-devel mailing list >>> nginx-devel at nginx.org >>> http://mailman.nginx.org/mailman/listinfo/nginx-devel >> _______________________________________________ >> nginx-devel mailing list >> nginx-devel at nginx.org >> http://mailman.nginx.org/mailman/listinfo/nginx-devel > _______________________________________________ > nginx-devel mailing list > nginx-devel at nginx.org > http://mailman.nginx.org/mailman/listinfo/nginx-devel -------------- next part -------------- An HTML attachment was scrubbed... URL: From harishkumarivaturi at gmail.com Mon Oct 12 15:41:10 2020 From: harishkumarivaturi at gmail.com (HARISH KUMAR Ivaturi) Date: Mon, 12 Oct 2020 17:41:10 +0200 Subject: Nginx HTTP/3 as a web server for DevStack Message-ID: Hi Does anyone know how to make DevStack (OpenStack Cloud) rely with Nginx HTTP/3 as a web server? Relevant links: https://www.nginx.com/blog/introducing-technology-preview-nginx-support-for-quic-http-3/ https://quic.nginx.org/readme.html https://docs.openstack.org/devstack/latest/ BR Harish Kumar -------------- next part -------------- An HTML attachment was scrubbed... URL: From mdounin at mdounin.ru Mon Oct 12 16:48:55 2020 From: mdounin at mdounin.ru (Maxim Dounin) Date: Mon, 12 Oct 2020 19:48:55 +0300 Subject: [PATCH] Conditional application of limit_conn directive In-Reply-To: References: <37619b9652dccd8e09a2affe139d063c@vl.ru> <20200922131923.GE1136@mdounin.ru> <54c602bf82cd03c12ca51bd30924578d@vl.ru> Message-ID: <20201012164855.GX1136@mdounin.ru> Hello! On Mon, Oct 12, 2020 at 02:10:26PM +1000, turchanov at farpost.com wrote: > Since you didn't reply to my reasoning for this patch, > I have to ask more directly. > > I didn't convince you of the usefulness of this conditional mode and > you are not going to apply the patch, are you? As previously suggested, the limit_conn and limit_req can be used conditionally by providing an empty key value. This is believed to be reasonably easy to configure, and no further changes are needed. There are no plans to apply the patch. > And if so, I could try to implement placement of the "limit_conn" into > "if" > context (not sure that I will be able to do that but at least I can try > to). > Will you agree to that feature? No. No additional directives are expected to be allowed in the "if" context. See IfIsEvil wiki article for details if you want to better understand reasons. -- Maxim Dounin http://mdounin.ru/ From pluknet at nginx.com Mon Oct 12 17:15:42 2020 From: pluknet at nginx.com (Sergey Kandaurov) Date: Mon, 12 Oct 2020 18:15:42 +0100 Subject: [PATCH] Portability: use `uname -n` instead of `hostname` In-Reply-To: <20201011080406.GA18953@vera.ghen.be> References: <20201011080406.GA18953@vera.ghen.be> Message-ID: <996B469A-DF6C-45CA-A5B6-B79A994E8A20@nginx.com> > On 11 Oct 2020, at 09:04, Geert Hendrickx wrote: > > # HG changeset patch > # User Geert Hendrickx > # Date 1602402793 -7200 > # Sun Oct 11 09:53:13 2020 +0200 > # Node ID 53f3eae1dc9a4f901f3d4da67daa0181d13dc222 > # Parent 4e06441193417456bf24b213d15da12a90322f4c > Portability: use `uname -n` instead of `hostname`. > > As `hostname` is not defined by POSIX and not available > by default on some modern Linux distro's (Arch, Fedora), > making some tests fail. Using `uname -n` instead fixes > this in a portable way. Whilst `uname -n` is certainly more portable than 4.2BSD'ish hostname(1), the former will barely work on win32 which is also ought to be supported. How about this change instead? It should work across all supported hosts. # HG changeset patch # User Sergey Kandaurov # Date 1602522787 -3600 # Mon Oct 12 18:13:07 2020 +0100 # Node ID b61e820caa837c412bb6cfeb33a5dccb05115701 # Parent 4e06441193417456bf24b213d15da12a90322f4c Tests: using Sys::Hostname to get hostname in a portable way. The hostname utility is not defined by POSIX and not available by default on some modern Linux distro's (Arch, Fedora). Reported by Geert Hendrickx. diff --git a/mail_error_log.t b/mail_error_log.t --- a/mail_error_log.t +++ b/mail_error_log.t @@ -13,6 +13,7 @@ use strict; use Test::More; use IO::Select; +use Sys::Hostname; BEGIN { use FindBin; chdir($FindBin::Bin); } @@ -233,8 +234,7 @@ SKIP: { ok($sec < 60, "$desc valid seconds"); ok(defined($host), "$desc has host"); - chomp(my $hostname = lc `hostname`); - is($host , $hostname, "$desc valid host"); + is($host, lc(hostname()), "$desc valid host"); ok(defined($tag), "$desc has tag"); like($tag, qr'\w+', "$desc valid tag"); diff --git a/stream_access_log.t b/stream_access_log.t --- a/stream_access_log.t +++ b/stream_access_log.t @@ -12,6 +12,8 @@ use strict; use Test::More; +use Sys::Hostname; + BEGIN { use FindBin; chdir($FindBin::Bin); } use lib 'lib'; @@ -158,7 +160,7 @@ is($t->read_file('filtered.log'), "127.0 ok($t->read_file('complex.log'), 'if with complex value'); ok($t->read_file('varlog_3.log'), 'variable in file'); -chomp(my $hostname = lc `hostname`); +my $hostname = lc hostname(); like($t->read_file('vars.log'), qr/^\d+:[\d.]+:$hostname:\d+$/, 'log vars'); is($t->read_file('addr.log'), "$escaped:$lhost:$lport:127.0.0.1:$dport:127.0.0.1:$uport\n", diff --git a/stream_error_log.t b/stream_error_log.t --- a/stream_error_log.t +++ b/stream_error_log.t @@ -13,6 +13,7 @@ use strict; use Test::More; use IO::Select; +use Sys::Hostname; BEGIN { use FindBin; chdir($FindBin::Bin); } @@ -241,8 +242,7 @@ SKIP: { ok($sec < 60, "$desc valid seconds"); ok(defined($host), "$desc has host"); - chomp(my $hostname = lc `hostname`); - is($host , $hostname, "$desc valid host"); + is($host, lc(hostname()), "$desc valid host"); ok(defined($tag), "$desc has tag"); like($tag, qr'\w+', "$desc valid tag"); diff --git a/stream_variables.t b/stream_variables.t --- a/stream_variables.t +++ b/stream_variables.t @@ -12,6 +12,8 @@ use strict; use Test::More; +use Sys::Hostname; + BEGIN { use FindBin; chdir($FindBin::Bin); } use lib 'lib'; @@ -80,7 +82,7 @@ EOF ############################################################################### -chomp(my $hostname = lc `hostname`); +my $hostname = lc hostname(); like(stream('127.0.0.1:' . port(8080))->read(), qr/^\d+:[\d.]+:$hostname:\d+:0$/, 'vars'); diff --git a/syslog.t b/syslog.t --- a/syslog.t +++ b/syslog.t @@ -13,6 +13,7 @@ use strict; use Test::More; use IO::Select; +use Sys::Hostname; BEGIN { use FindBin; chdir($FindBin::Bin); } @@ -321,8 +322,7 @@ sub parse_syslog_message { ok($sec < 60, "$desc valid seconds"); ok(defined($host), "$desc has host"); - chomp(my $hostname = lc `hostname`); - is($host , $hostname, "$desc valid host"); + is($host, lc(hostname()), "$desc valid host"); ok(defined($tag), "$desc has tag"); like($tag, qr'\w+', "$desc valid tag"); -- Sergey Kandaurov From ru at nginx.com Tue Oct 13 04:45:34 2020 From: ru at nginx.com (Ruslan Ermilov) Date: Tue, 13 Oct 2020 04:45:34 +0000 Subject: [nginx] Cpp test: added stream. Message-ID: details: https://hg.nginx.org/nginx/rev/f1e6f65ddfeb branches: changeset: 7727:f1e6f65ddfeb user: Ruslan Ermilov date: Tue Oct 13 07:44:09 2020 +0300 description: Cpp test: added stream. diffstat: src/misc/ngx_cpp_test_module.cpp | 2 ++ 1 files changed, 2 insertions(+), 0 deletions(-) diffs (12 lines): diff -r 559d19037984 -r f1e6f65ddfeb src/misc/ngx_cpp_test_module.cpp --- a/src/misc/ngx_cpp_test_module.cpp Thu Oct 08 17:44:34 2020 +0300 +++ b/src/misc/ngx_cpp_test_module.cpp Tue Oct 13 07:44:09 2020 +0300 @@ -14,6 +14,8 @@ extern "C" { #include #include #include + + #include } // nginx header files should go before other, because they define 64-bit off_t From geert at hendrickx.be Tue Oct 13 07:21:34 2020 From: geert at hendrickx.be (Geert Hendrickx) Date: Tue, 13 Oct 2020 09:21:34 +0200 Subject: [PATCH] Portability: use `uname -n` instead of `hostname` In-Reply-To: <996B469A-DF6C-45CA-A5B6-B79A994E8A20@nginx.com> References: <20201011080406.GA18953@vera.ghen.be> <996B469A-DF6C-45CA-A5B6-B79A994E8A20@nginx.com> Message-ID: <20201013072134.GA35274@vera.ghen.be> On Mon, Oct 12, 2020 at 18:15:42 +0100, Sergey Kandaurov wrote: > Whilst `uname -n` is certainly more portable than 4.2BSD'ish hostname(1), > the former will barely work on win32 which is also ought to be supported. > How about this change instead? It should work across all supported hosts. Sure, if Sys::Hostname is bundled with standard perl, which appears to be the case. Looking at that module, on Unix it calls `uname -n` eventually. ;-) On Windows indeed it still uses `hostname`. Geert -- geert.hendrickx.be :: geert at hendrickx.be :: PGP: 0xC4BB9E9F This e-mail was composed using 100% recycled spam messages! From alexander.borisov at nginx.com Tue Oct 13 12:45:23 2020 From: alexander.borisov at nginx.com (Alexander Borisov) Date: Tue, 13 Oct 2020 12:45:23 +0000 Subject: [njs] Fixed heap-buffer-overflow for RegExp.prototype[Symbol.replace]. Message-ID: details: https://hg.nginx.org/njs/rev/a82f123409b7 branches: changeset: 1539:a82f123409b7 user: Alexander Borisov date: Tue Oct 13 15:44:33 2020 +0300 description: Fixed heap-buffer-overflow for RegExp.prototype[Symbol.replace]. Previously, RegExp.prototype[Symbol.replace] might overrun the boundaries of the result of the custom "exec" method for a RegExp argument. The issue occurred when the result object had zero length. The length is used to create an array and the zero index was always written without respect for the length resulting is heap-buffer-overflow. The issue was introduced in 1c729f765cfb. diffstat: src/njs_regexp.c | 14 ++++++++------ src/test/njs_unit_test.c | 12 ++++++++++++ 2 files changed, 20 insertions(+), 6 deletions(-) diffs (72 lines): diff -r 893fa730285c -r a82f123409b7 src/njs_regexp.c --- a/src/njs_regexp.c Thu Oct 08 18:47:04 2020 +0300 +++ b/src/njs_regexp.c Tue Oct 13 15:44:33 2020 +0300 @@ -1343,14 +1343,14 @@ njs_regexp_prototype_symbol_replace(njs_ pos = njs_max(njs_min(pos, (int64_t) s.size), 0); - if (njs_fast_path(njs_is_fast_array(r))) { + if (njs_fast_path(njs_is_fast_array(r) && njs_array_len(r) != 0)) { array = njs_array(r); arguments = array->start; arguments[0] = matched; - ncaptures = array->length; + ncaptures = njs_max((int64_t) array->length - 1, 0); - for (n = 1; n < ncaptures; n++) { + for (n = 1; n <= ncaptures; n++) { if (njs_is_undefined(&arguments[n])) { continue; } @@ -1367,7 +1367,9 @@ njs_regexp_prototype_symbol_replace(njs_ goto exception; } - array = njs_array_alloc(vm, 0, ncaptures, 0); + ncaptures = njs_max(ncaptures - 1, 0); + + array = njs_array_alloc(vm, 0, ncaptures + 1, 0); if (njs_slow_path(array == NULL)) { goto exception; } @@ -1375,7 +1377,7 @@ njs_regexp_prototype_symbol_replace(njs_ arguments = array->start; arguments[0] = matched; - for (n = 1; n < ncaptures; n++) { + for (n = 1; n <= ncaptures; n++) { ret = njs_value_property_i64(vm, r, n, &arguments[n]); if (njs_slow_path(ret == NJS_ERROR)) { goto exception; @@ -1406,7 +1408,7 @@ njs_regexp_prototype_symbol_replace(njs_ } ret = njs_string_get_substitution(vm, &matched, string, pos, - arguments, ncaptures - 1, &groups, + arguments, ncaptures, &groups, replace, &retval); } else { diff -r 893fa730285c -r a82f123409b7 src/test/njs_unit_test.c --- a/src/test/njs_unit_test.c Thu Oct 08 18:47:04 2020 +0300 +++ b/src/test/njs_unit_test.c Tue Oct 13 15:44:33 2020 +0300 @@ -8284,6 +8284,18 @@ static njs_unit_test_t njs_test[] = { njs_str("/b(c)(z)?(.)/[Symbol.replace]('abcde', '[$01$02$03$04$00]')"), njs_str("a[cd$04$00]e") }, + { njs_str("var r = /./; r.exec = () => {return {}};" + "r[Symbol.replace]('ABCD', 'b')"), + njs_str("b") }, + + { njs_str("var r = /./; r.exec = () => {return {}};" + "r[Symbol.replace]('ABCD', (m,p,o) => `${m}|${p}|${o}`)"), + njs_str("undefined|0|ABCD") }, + + { njs_str("var r = /./; r.exec = () => Buffer.from([]).toJSON().data;" + "r[Symbol.replace]('ABCD', 'b')"), + njs_str("b") }, + { njs_str("'?'.replace(/(h*)/g, '$1??')"), njs_str("?????") }, From alexander.borisov at nginx.com Mon Oct 19 13:12:07 2020 From: alexander.borisov at nginx.com (Alexander Borisov) Date: Mon, 19 Oct 2020 13:12:07 +0000 Subject: [njs] Fixed returned value for Buffer.prototype.write* functions. Message-ID: details: https://hg.nginx.org/njs/rev/4106bf95d343 branches: changeset: 1540:4106bf95d343 user: Alexander Borisov date: Mon Oct 19 15:51:37 2020 +0300 description: Fixed returned value for Buffer.prototype.write* functions. All Buffer.prototype.write* functions must return offset plus the number of bytes written. The issue was introduced in 27bb9caf186c. diffstat: src/njs_buffer.c | 2 +- src/test/njs_unit_test.c | 6 +++++- 2 files changed, 6 insertions(+), 2 deletions(-) diffs (28 lines): diff -r a82f123409b7 -r 4106bf95d343 src/njs_buffer.c --- a/src/njs_buffer.c Tue Oct 13 15:44:33 2020 +0300 +++ b/src/njs_buffer.c Mon Oct 19 15:51:37 2020 +0300 @@ -1331,7 +1331,7 @@ njs_buffer_prototype_write_int(njs_vm_t break; } - njs_set_undefined(&vm->retval); + njs_set_number(&vm->retval, index + size); return NJS_OK; } diff -r a82f123409b7 -r 4106bf95d343 src/test/njs_unit_test.c --- a/src/test/njs_unit_test.c Tue Oct 13 15:44:33 2020 +0300 +++ b/src/test/njs_unit_test.c Mon Oct 19 15:51:37 2020 +0300 @@ -19191,7 +19191,11 @@ static njs_unit_test_t njs_test[] = " if (size > 1) { rmethod += endianness; wmethod += endianness; };" " var v = 0x7abbccddeeff & (size * 8 - 1);" "" - " buf[wgmethod](v, offset, size);" + " var ret = buf[wgmethod](v, offset, size);" + " if(ret !== offset + size) {" + " throw Error(`${wgmethod} returned ${ret}, need ${offset + size}`);" + " }" + "" " var gv = buf[rgmethod](offset, size);" "" " buf.fill(0);" From alexander.borisov at nginx.com Tue Oct 20 11:01:15 2020 From: alexander.borisov at nginx.com (Alexander Borisov) Date: Tue, 20 Oct 2020 11:01:15 +0000 Subject: [njs] Added support for Object.prototype.valueOf() in Buffer.from(). Message-ID: details: https://hg.nginx.org/njs/rev/c262ed3c7df0 branches: changeset: 1541:c262ed3c7df0 user: Alexander Borisov date: Tue Oct 20 14:00:40 2020 +0300 description: Added support for Object.prototype.valueOf() in Buffer.from(). Missed in 27bb9caf186c. diffstat: src/njs_buffer.c | 17 ++++++++++++++++- src/njs_value.c | 27 +++++++++++++++++++++++++++ src/njs_value.h | 1 + src/test/njs_unit_test.c | 23 +++++++++++++++++++++++ 4 files changed, 67 insertions(+), 1 deletions(-) diffs (119 lines): diff -r 4106bf95d343 -r c262ed3c7df0 src/njs_buffer.c --- a/src/njs_buffer.c Mon Oct 19 15:51:37 2020 +0300 +++ b/src/njs_buffer.c Tue Oct 20 14:00:40 2020 +0300 @@ -228,11 +228,13 @@ njs_buffer_from(njs_vm_t *vm, njs_value_ njs_index_t unused) { njs_int_t ret; - njs_value_t *value; + njs_value_t *value, retval; const njs_buffer_encoding_t *encoding; value = njs_arg(args, nargs, 1); +next: + switch (value->type) { case NJS_TYPED_ARRAY: return njs_buffer_from_typed_array(vm, value); @@ -251,6 +253,19 @@ njs_buffer_from(njs_vm_t *vm, njs_value_ default: if (njs_is_object(value)) { + ret = njs_value_of(vm, value, &retval); + if (njs_slow_path(ret == NJS_ERROR)) { + return ret; + } + + if (ret == NJS_OK && !njs_is_null(&retval) + && !(njs_is_object(&retval) + && njs_object(&retval) == njs_object(value))) + { + *value = retval; + goto next; + } + ret = njs_buffer_from_object(vm, value); if (njs_slow_path(ret != NJS_DECLINED)) { return ret; diff -r 4106bf95d343 -r c262ed3c7df0 src/njs_value.c --- a/src/njs_value.c Mon Oct 19 15:51:37 2020 +0300 +++ b/src/njs_value.c Tue Oct 20 14:00:40 2020 +0300 @@ -262,6 +262,33 @@ njs_value_own_enumerate(njs_vm_t *vm, nj njs_int_t +njs_value_of(njs_vm_t *vm, njs_value_t *value, njs_value_t *retval) +{ + + njs_int_t ret; + + static const njs_value_t value_of = njs_string("valueOf"); + + if (njs_slow_path(!njs_is_object(value))) { + return NJS_DECLINED; + } + + ret = njs_value_property(vm, value, njs_value_arg(&value_of), + retval); + if (njs_slow_path(ret != NJS_OK)) { + return ret; + } + + if (!njs_is_function(retval)) { + njs_type_error(vm, "object.valueOf is not a function"); + return NJS_ERROR; + } + + return njs_function_apply(vm, njs_function(retval), value, 1, retval); +} + + +njs_int_t njs_value_length(njs_vm_t *vm, njs_value_t *value, int64_t *length) { njs_string_prop_t string_prop; diff -r 4106bf95d343 -r c262ed3c7df0 src/njs_value.h --- a/src/njs_value.h Mon Oct 19 15:51:37 2020 +0300 +++ b/src/njs_value.h Tue Oct 20 14:00:40 2020 +0300 @@ -1053,6 +1053,7 @@ njs_array_t *njs_value_enumerate(njs_vm_ njs_object_enum_t kind, njs_object_enum_type_t type, njs_bool_t all); njs_array_t *njs_value_own_enumerate(njs_vm_t *vm, njs_value_t *value, njs_object_enum_t kind, njs_object_enum_type_t type, njs_bool_t all); +njs_int_t njs_value_of(njs_vm_t *vm, njs_value_t *value, njs_value_t *retval); njs_int_t njs_value_length(njs_vm_t *vm, njs_value_t *value, int64_t *dst); const char *njs_type_string(njs_value_type_t type); diff -r 4106bf95d343 -r c262ed3c7df0 src/test/njs_unit_test.c --- a/src/test/njs_unit_test.c Mon Oct 19 15:51:37 2020 +0300 +++ b/src/test/njs_unit_test.c Tue Oct 20 14:00:40 2020 +0300 @@ -18580,6 +18580,29 @@ static njs_unit_test_t njs_test[] = { njs_str("var buf = Buffer.from('?'); njs.dump(buf)"), njs_str("Buffer [206,177]") }, + { njs_str("var arr = new Array(1,2,3); arr.valueOf = () => arr;" + "njs.dump(Buffer.from(arr))"), + njs_str("Buffer [1,2,3]") }, + + { njs_str("var obj = new Object(); obj.valueOf = () => obj;" + "Buffer.from(obj)"), + njs_str("TypeError: first argument object is not a string or Buffer-like object") }, + + { njs_str("var obj = new Object(); obj.valueOf = () => undefined;" + "njs.dump(Buffer.from(obj))"), + njs_str("TypeError: first argument undefined is not a string or Buffer-like object") }, + + { njs_str("var arr = new Array(1,2,3); arr.valueOf = () => null;" + "njs.dump(Buffer.from(arr))"), + njs_str("Buffer [1,2,3]") }, + + { njs_str("var obj = new Object(); obj.valueOf = () => new Array(1,2,3);" + "njs.dump(Buffer.from(obj))"), + njs_str("Buffer [1,2,3]") }, + + { njs_str("njs.dump(Buffer.from(new String('test')))"), + njs_str("Buffer [116,101,115,116]") }, + { njs_str("[" " ['6576696c', 'hex']," " ['ZXZpbA==', 'base64']," From xeioex at nginx.com Tue Oct 20 15:50:21 2020 From: xeioex at nginx.com (Dmitry Volyntsev) Date: Tue, 20 Oct 2020 15:50:21 +0000 Subject: [njs] Added TypeScript description for Buffer type. Message-ID: details: https://hg.nginx.org/njs/rev/5eab7463f984 branches: changeset: 1542:5eab7463f984 user: Jakub Jirutka date: Sat Oct 17 01:38:31 2020 +0200 description: Added TypeScript description for Buffer type. diffstat: src/ts/njs_core.d.ts | 545 ++++++++++++++++++++++++++++++++++++++++++++++++++- test/ts/test.ts | 14 +- 2 files changed, 555 insertions(+), 4 deletions(-) diffs (598 lines): diff -r c262ed3c7df0 -r 5eab7463f984 src/ts/njs_core.d.ts --- a/src/ts/njs_core.d.ts Tue Oct 20 14:00:40 2020 +0300 +++ b/src/ts/njs_core.d.ts Sat Oct 17 01:38:31 2020 +0200 @@ -1,8 +1,10 @@ +type BufferEncoding = "utf8" | "hex" | "base64" | "base64url"; + interface StringConstructor { /** * Creates a byte string from an encoded string. */ - bytesFrom(bytes: string, encoding: "hex" | "base64" | "base64url"): NjsByteString; + bytesFrom(bytes: string, encoding: Exclude): NjsByteString; /** * Creates a byte string from an array that contains octets. */ @@ -35,11 +37,550 @@ type NjsByteString = string & { /** * Encodes a byte string to hex, base64, or base64url. */ - toString(encoding: "hex" | "base64" | "base64url"): string; + toString(encoding: Exclude): string; }; type NjsStringLike = string | NjsByteString; +type TypedArray = + | Uint8Array + | Uint8ClampedArray + | Uint16Array + | Uint32Array + | Int8Array + | Int16Array + | Int32Array + | Float32Array + | Float64Array; + +/** + * Raw data is stored in instances of the `Buffer` class. + */ +declare class Buffer extends Uint8Array { + /** + * Allocates a new `Buffer` of a specified `size`. + * + * @param size The count of octets to allocate. + * @param fill If specified, the allocated `Buffer` will be initialized by calling `buf.fill(fill)`. + * Otherwise, the `Buffer` will be zero-filled. + * @param encoding The character encoding used for call to `buf.fill(fill, encoding)` while + * initalizing. Defaults to`'utf8'`. + */ + static alloc(size: number, fill?: NjsStringLike | Uint8Array | number, encoding?: BufferEncoding): Buffer; + /** + * The same as `Buffer.alloc()`, with the difference that the memory allocated for the buffer + * is not initialized, the contents of the new buffer is unknown and may contain sensitive data. + * + * @param size The count of octets to allocate. + */ + static allocUnsafe(size: number): Buffer; + + /** + * Returns the byte length of the specified `value`, when encoded using `encoding`. + * + * @param value The value to test. + * @param encoding The character encoding used to evaluate `value` if `value` is a `string`. + * Defaults to `'utf8'`. + */ + static byteLength(value: NjsStringLike | Buffer | TypedArray | DataView | ArrayBuffer, encoding?: BufferEncoding): number; + + /** + * Compares `buffer1` with `buffer2` when sorting arrays of buffer instances. + * + * @return + * - `0` if `buffer2` is the same as `buffer1`, + * - `1` if `buffer2` should come _before_ `buffer1` when sorted, + * - `-1` if `buffer2` should come _after_ `buffer1` when sorted. + */ + static compare(buf1: Uint8Array, buf2: Uint8Array): -1 | 0 | 1; + + /** + * Returns a new `Buffer` which is the result of concatenating all the `Buffer` instances in + * the `list`. If there are no items in the `list` or the total length is 0, a new zero-length + * `Buffer` is returned. + * + * @param list An array of `Buffer` or `Uint8Array` objects to concatenate. + * @param totalLength Total length of the buffers when concatenated, coerced to an unsigned + * integer. If not specified, it is calculated from the `Buffer` instances in `list` by adding + * their lengths. If the combined length of the Buffers in list exceeds `totalLength`, the + * result is truncated to `totalLength`. + */ + static concat(list: Uint8Array[], totalLength?: number): Buffer; + + /** + * @param arrayBuffer The `.buffer` property of any `TypedArray` or a `new ArrayBuffer()`. + * @param byteOffset An integer specifying the index of the first byte to expose. Defaults to `0`. + * @param length An integer specifying number of bytes to expose. + * Defaults to `arrayBuffer.byteLength - byteOffset`. + */ + static from(arrayBuffer: ArrayBuffer, byteOffset?: number, length?: number): Buffer; + /** + * Allocates a new `Buffer` using an array of bytes in the range `0 ? 255`. Array entries + * outside that range will be truncated. + * + * @param data The data to create a new `Buffer`. + */ + static from(data: number[]): Buffer; + /** + * Copies the passed buffer `data` onto a new `Buffer` instance. + * + * @param data The buffer to copy. + */ + static from(data: Uint8Array): Buffer; + /** + * For objects whose `valueOf()` function returns a value not strictly equal to object, returns + * `Buffer.from(object.valueOf(), offsetOrEncoding, length)`. + * + * @param obj An object supporting `valueOf()`. + */ + static from(obj: { valueOf(): NjsStringLike | object }, byteOffset?: number, length?: number): Buffer; + /** + * Creates a new `Buffer` with a string `str`. + * + * @param str The string to create a new `Buffer`. + * @param encoding The character encoding to be used when converting a string into bytes. + * Defaults to `'utf8'`. + */ + static from(str: NjsStringLike, encoding?: BufferEncoding): Buffer; + + /** + * Returns true if the `obj` is a `Buffer`. + * + * @param obj The object to test. + */ + static isBuffer(obj: any): obj is Buffer; + + /** + * Returns `true` if `encoding` is the name of a supported character encoding. + * + * @param encoding The string to test. + */ + static isEncoding(encoding: NjsStringLike): encoding is BufferEncoding; + + /** + * The underlying `ArrayBuffer` object based on which this `Buffer` object is created. + */ + readonly buffer: ArrayBuffer; + /** + * Specifies the `byteOffset` of the Buffer's underlying `ArrayBuffer` object. + */ + readonly byteOffset: number; + /** + * The number of bytes in this buffer. + */ + readonly length: number; + + /** + * Constructor cannot be called. + */ + private constructor(); + + /** + * The index operator can be used to get and set the octet at position index in buffer. + * The values refer to individual bytes, so the legal value range is between 0 and 255 (decimal). + */ + [index: number]: number; + + /** + * Compares this buffer (source) with the `target` and returns a number indicating whether this + * buffer comes before, after, or is the same as the `target` in sort order. Comparison is based + * on the actual sequence of bytes in each `Buffer`. + * + * @param target The target buffer for comparison. + * @param targetStart An integer specifying the offset within `target` at which to begin + * comparison. Defaults to `0`. + * @param targetEnd An integer specifying the offset within `target` at which to end comparison. + * Defaults to `target.length`. + * @param sourceStart An integer specifying the offset within this buffer at which to begin + * comparison. Defaults to `0`. + * @param sourceEnd An integer specifying the offset within this buffer at which to end comparison + * (not inclusive). Defaults to `buf.length`. + * @return + * - `0` if `target` is the same as this buffer, + * - `1` if `target` should come _before_ this buffer when sorted, + * - `-1` if `target` should come _after_ this buffer when sorted. + */ + compare(target: Uint8Array, targetStart?: number, targetEnd?: number, sourceStart?: number, sourceEnd?: number): -1 | 0 | 1; + + /** + * Copies data from a region of this buffer to a region in `target`, even if the `target` + * memory region overlaps with this buffer. + * + * @param target The target buffer. + * @param targetStart An integer specifying the offset within `target` at which to begin writing. + * Defaults to `0`. + * @param sourceStart An integer specifying the offset within this buffer from which to begin + * copying. Defaults to `0`. + * @param sourceEnd An integer specifying the offset within this buffer at which to stop copying + * (not inclusive). Defaults to `buf.length`. + * @return The number of bytes copied. + */ + copy(target: Uint8Array, targetStart?: number, sourceStart?: number, sourceEnd?: number): number; + + /** + * Returns `true` if both this buffer and `other` buffer have exactly the same bytes. + * + * @param other The other buffer to compare with. + */ + equals(other: Uint8Array): boolean; + + /** + * Fills this buffer with the specified `value`. If the `offset` and `end` are not specified, + * the entire buffer will be filled. The `value` is coerced to `uint32` if it is not a `string`, + * `Buffer`, or `integer`. If the resulting integer is greater than `255`, the buffer will be + * filled with `value` and `255`. + * + * @param value The value with which to fill this buffer. + * @param offset Number of bytes to skip before starting to fill this buffer. Defaults to `0`. + * @param end Where to stop filling this buffer (not inclusive). Defaults to `buf.length`. + * @param encoding The encoding for `value` if `value` is a `string`. Defaults to `'utf8'`. + */ + fill(value: NjsStringLike | Uint8Array | number, offset?: number, end?: number, encoding?: BufferEncoding): this; + + /** + * Equivalent to `buf.indexOf() !== -1`, returns `true` if the `value` was found in this buffer. + * + * @param value What to search for. If a `number`, it must be between `0` and `255`. + * @param byteOffset Where to begin search in this buffer. Defaults to `0`. + * @param encoding The encoding for `value` if `value` is a `string`. Defaults to `'utf8'`. + */ + includes(value: NjsStringLike | number | Uint8Array, byteOffset?: number, encoding?: BufferEncoding): boolean; + + /** + * Returns an integer which is the index of the first occurrence of `value` in this buffer, + * or `-1` if this buffer does not contain `value`. + * + * @param value What to search for. If a `number`, it must be between `0` and `255`. + * @param byteOffset Where to begin search in this buffer. Defaults to `0`. + * @param encoding The encoding for `value` if `value` is a `string`. Defaults to `'utf8'`. + */ + indexOf(value: NjsStringLike | number | Uint8Array, byteOffset?: number, encoding?: BufferEncoding): number; + /** + * The same as `buf.indexOf()`, except the last occurrence of the `value` is found instead of + * the first occurrence. If the `value` is an empty `string` or empty `Buffer`, `byteOffset` + * will be returned. + * + * @param value What to search for. If a `number`, it must be between `0` and `255`. + * @param byteOffset Where to begin search in this buffer. Defaults to `0`. + * @param encoding The encoding for `value` if `value` is a `string`. Defaults to `'utf8'`. + */ + lastIndexOf(value: NjsStringLike | number | Uint8Array, byteOffset?: number, encoding?: BufferEncoding): number; + + /** + * Reads the `byteLength` from this buffer at the specified `offset` and interprets the result + * as a big-endian, two's complement signed value supporting up to 48 bits of accuracy. + * + * @param offset An integer specifying the number of bytes to skip before starting to read. + * Must satisfy `0 <= offset <= buf.length - byteLength`. + * @param byteLength An integer between `1` and `6` specifying the number of bytes to read. + * Must satisfy `0 < byteLength <= 6`. + */ + readIntBE(offset: number, byteLength: number): number; + /** + * @see {Buffer.prototype.readIntBE}. + */ + readInt8(offset?: number): number; + /** + * @see {Buffer.prototype.readIntBE}. + */ + readInt16BE(offset?: number): number; + /** + * @see {Buffer.prototype.readIntBE}. + */ + readInt32BE(offset?: number): number; + /** + * Reads the `byteLength` from this buffer at the specified `offset` and interprets the result + * as a little-endian, two's complement signed value supporting up to 48 bits of accuracy. + * + * @param offset An integer specifying the number of bytes to skip before starting to read. + * Must satisfy `0 <= offset <= buf.length - byteLength`. + * @param byteLength An integer between `1` and `6` specifying the number of bytes to read. + * Must satisfy `0 < byteLength <= 6`. + */ + readIntLE(offset: number, byteLength: number): number; + /** + * @see {Buffer.prototype.readIntLE}. + */ + readInt16LE(offset?: number): number; + /** + * @see {Buffer.prototype.readIntLE}. + */ + readInt32LE(offset?: number): number; + + /** + * Reads the `byteLength` from this buffer at the specified `offset` and interprets the result + * as a big-endian integer supporting up to 48 bits of accuracy. + * + * @param offset An integer specifying the number of bytes to skip before starting to read. + * Must satisfy `0 <= offset <= buf.length - byteLength`. + * @param byteLength An integer between `1` and `6` specifying the number of bytes to read. + * Must satisfy `0 < byteLength <= 6`. + */ + readUIntBE(offset: number, byteLength: number): number; + /** + * @see {Buffer.prototype.readUIntBE}. + */ + readUInt8(offset?: number): number; + /** + * @see {Buffer.prototype.readUIntBE}. + */ + readUInt16BE(offset?: number): number; + /** + * @see {Buffer.prototype.readUIntBE}. + */ + readUInt32BE(offset?: number): number; + /** + * Reads the `byteLength` from this buffer at the specified `offset` and interprets the result + * as a little-endian integer supporting up to 48 bits of accuracy. + * + * @param offset An integer specifying the number of bytes to skip before starting to read. + * Must satisfy `0 <= offset <= buf.length - byteLength`. + * @param byteLength An integer between `1` and `6` specifying the number of bytes to read. + * Must satisfy `0 < byteLength <= 6`. + */ + readUIntLE(offset: number, byteLength: number): number; + /** + * @see {Buffer.prototype.readUIntLE}. + */ + readUInt16LE(offset?: number): number; + /** + * @see {Buffer.prototype.readUIntLE}. + */ + readUInt32LE(offset?: number): number; + + /** + * Reads a 64-bit, big-endian double from this buffer at the specified `offset`. + * + * @param offset An integer specifying the number of bytes to skip before starting to read. + * Must satisfy `0 <= offset <= buf.length - 8`. Defaults to `0`. + */ + readDoubleBE(offset?: number): number; + /** + * Reads a 64-bit, little-endian double from this buffer at the specified `offset`. + * + * @param offset An integer specifying the number of bytes to skip before starting to read. + * Must satisfy `0 <= offset <= buf.length - 8`. Defaults to `0`. + */ + readDoubleLE(offset?: number): number; + + /** + * Reads a 32-bit, big-endian float from this buffer at the specified `offset`. + * + * @param offset An integer specifying the number of bytes to skip before starting to read. + * Must satisfy `0 <= offset <= buf.length - 4`. Defaults to `0`. + */ + readFloatBE(offset?: number): number; + /** + * Reads a 32-bit, little-endian float from this buffer at the specified `offset`. + * + * @param offset An integer specifying the number of bytes to skip before starting to read. + * Must satisfy `0 <= offset <= buf.length - 4`. Defaults to `0`. + */ + readFloatLE(offset?: number): number; + + /** + * Returns a new `Buffer` that references **the same memory as the original**, but offset and + * cropped by `start` and `end`. + * + * @param start Where the new `Buffer` will start. Defaults to `0`. + * @param end Where the new `Buffer` will end (not inclusive). If `end` is greater than + * `buf.length`, the same result as that of end equal to `buf.length` is returned. + * Defaults to `buf.length`. + */ + subarray(start?: number, end?: number): Buffer; + + /** + * Returns a new `Buffer` that references **the same memory as the original**, but offset and + * cropped by the `start` and end `values`. + * + * @param start Where the new `Buffer` will start. Defaults to `0`. + * @param end Where the new `Buffer` will end (not inclusive). Defaults to `buf.length`. + */ + slice(begin?: number, end?: number): Buffer; + + /** + * Interprets this buffer as an array of unsigned 16-bit numbers and swaps the byte order + * in-place. + * + * @throws {RangeError} if `buf.length` is not a multiple of 2. + */ + swap16(): Buffer; + /** + * Interprets this buffer as an array of unsigned 32-bit numbers and swaps the byte order + * in-place. + * + * @throws {RangeError} if `buf.length` is not a multiple of 4. + */ + swap32(): Buffer; + /** + * Interprets this buffer as an array of 64-bit numbers and swaps byte order in-place. + * + * @throws {RangeError} if `buf.length` is not a multiple of 8. + */ + swap32(): Buffer; + + /** + * Returns a JSON representation of this buffer. `JSON.stringify()` implicitly calls this + * function when stringifying a `Buffer` instance. + */ + toJSON(): { type: "Buffer"; data: number[] }; + + /** + * Decodes this buffer to a string according to the specified character `encoding`. + * + * @param encoding The character encoding. Defaults to `'utf8'`. + * @param start The byte offset to start decoding at. Defaults to `0`. + * @param end The byte offset to stop decoding at (not inclusive). Defaults to `buf.length`. + */ + toString(encoding?: BufferEncoding, start?: number, end?: number): string; + + /** + * Writes a string `str` to this buffer at the `offset` according to the character `encoding`. + * If this buffer did not contain enough space to fit the entire string, only part of the + * string will be written, however, partially encoded characters will not be written. + * + * @param str The string to write into this buffer. + * @param offset An integer specifying the number of bytes to skip before starting to write `str`. + * Defaults to `0`. + * @param length An integer specifying the number of bytes to write. + * Defaults to `buf.length - offset`. + * @param encoding The character encoding of `str`. Defaults to `'utf8'`. + * @return Offset plus the number of bytes written. + */ + write(str: NjsStringLike, encoding?: BufferEncoding): number; + write(str: NjsStringLike, offset: number, encoding?: BufferEncoding): number; + write(str: NjsStringLike, offset: number, length: number, encoding?: BufferEncoding): number; + + /** + * Writes `byteLength` bytes of `value` to this buffer at the specified `offset` as big-endian. + * Supports up to 48 bits of accuracy. + * + * @param value The number to be written into this buffer. + * @param offset An integer specifying the number of bytes to skip before starting to write. + * Must satisfy `0 <= offset <= buf.length - byteLength`. + * @param byteLength An integer between `1` and `6` specifying the number of bytes to read. + * Must satisfy `0 < byteLength <= 6`. + * @return Offset plus the number of bytes written. + */ + writeIntBE(value: number, offset: number, byteLength: number): number; + /** + * @see {Buffer.prototype.writeIntBE}. + */ + writeInt8(value: number, offset?: number): number; + /** + * @see {Buffer.prototype.writeIntBE}. + */ + writeInt16BE(value: number, offset?: number): number; + /** + * @see {Buffer.prototype.writeIntBE}. + */ + writeInt32BE(value: number, offset?: number): number; + /** + * Writes `byteLength` bytes of `value` to this buffer at the specified `offset` as + * little-endian. Supports up to 48 bits of accuracy. + * + * @param value The number to be written into this buffer. + * @param offset An integer specifying the number of bytes to skip before starting to write. + * Must satisfy `0 <= offset <= buf.length - byteLength`. + * @param byteLength An integer between `1` and `6` specifying the number of bytes to read. + * Must satisfy `0 < byteLength <= 6`. + * @return Offset plus the number of bytes written. + */ + writeIntLE(value: number, offset: number, byteLength: number): number; + /** + * @see {Buffer.prototype.writeIntLE}. + */ + writeInt16LE(value: number, offset?: number): number; + /** + * @see {Buffer.prototype.writeIntLE}. + */ + writeInt32LE(value: number, offset?: number): number; + + /** + * Writes `byteLength` bytes of `value` to this buffer at the specified `offset` as big-endian. + * Supports up to 48 bits of accuracy. + * + * @param value The number to be written into this buffer. + * @param offset An integer specifying the number of bytes to skip before starting to write. + * Must satisfy `0 <= offset <= buf.length - byteLength`. + * @param byteLength An integer between `1` and `6` specifying the number of bytes to read. + * Must satisfy `0 < byteLength <= 6`. + * @return Offset plus the number of bytes written. + */ + writeUIntBE(value: number, offset: number, byteLength: number): number; + /** + * @see {Buffer.prototype.writeUIntBE}. + */ + writeUInt8(value: number, offset?: number): number; + /** + * @see {Buffer.prototype.writeUIntBE}. + */ + writeUInt16BE(value: number, offset?: number): number; + /** + * @see {Buffer.prototype.writeUIntBE}. + */ + writeUInt32BE(value: number, offset?: number): number; + /** + * Writes `byteLength` bytes of `value` to this buffer at the specified `offset` as + * little-endian. Supports up to 48 bits of accuracy. + * + * @param value The number to be written into this buffer. + * @param offset An integer specifying the number of bytes to skip before starting to write. + * Must satisfy `0 <= offset <= buf.length - byteLength`. + * @param byteLength An integer between `1` and `6` specifying the number of bytes to read. + * Must satisfy `0 < byteLength <= 6`. + * @return Offset plus the number of bytes written. + */ + writeUIntLE(value: number, offset: number, byteLength: number): number; + /** + * @see {Buffer.prototype.writeUIntLE}. + */ + writeUInt16LE(value: number, offset?: number): number; + /** + * @see {Buffer.prototype.writeUIntLE}. + */ + writeUInt32LE(value: number, offset?: number): number; + + /** + * Writes the `value` to this buffer at the specified `offset` as big-endian. + * + * @param value The number to be written into this buffer. + * @param offset An integer specifying the number of bytes to skip before starting to write. + * Must satisfy `0 <= offset <= buf.length - 8`. Defaults to `0`. + * @return Offset plus the number of bytes written. + */ + writeDoubleBE(value: number, offset?: number): number; + /** + * Writes the `value` to this buffer at the specified `offset` as little-endian. + * + * @param value The number to be written into this buffer. + * @param offset An integer specifying the number of bytes to skip before starting to write. + * Must satisfy `0 <= offset <= buf.length - 8`. Defaults to `0`. + * @return Offset plus the number of bytes written. + */ + writeDoubleLE(value: number, offset?: number): number; + + /** + * Writes the `value` to this buffer at the specified `offset` as big-endian. + * + * @param value The number to be written into this buffer. + * @param offset An integer specifying the number of bytes to skip before starting to write. + * Must satisfy `0 <= offset <= buf.length - 4`. Defaults to `0`. + * @return Offset plus the number of bytes written. + */ + writeFloatBE(value: number, offset?: number): number; + /** + * Writes the `value` to this buffer at the specified `offset` as little-endian. + * + * @param value The number to be written into this buffer. + * @param offset An integer specifying the number of bytes to skip before starting to write. + * Must satisfy `0 <= offset <= buf.length - 4`. Defaults to `0`. + * @return Offset plus the number of bytes written. + */ + writeFloatLE(value: number, offset?: number): number; +} + + // Global objects interface NjsGlobal { diff -r c262ed3c7df0 -r 5eab7463f984 test/ts/test.ts --- a/test/ts/test.ts Tue Oct 20 14:00:40 2020 +0300 +++ b/test/ts/test.ts Sat Oct 17 01:38:31 2020 +0200 @@ -1,6 +1,6 @@ /// -function handler(r: NginxHTTPRequest) { +function http_module(r: NginxHTTPRequest) { var bs: NjsByteString; var s: string; @@ -59,8 +59,18 @@ function handler(r: NginxHTTPRequest) { r.subrequest('/p/sub4', 'a=1&b=2').then(reply => r.return(reply.status, JSON.stringify(JSON.parse(reply.responseBody)))); - // builtin objects +} + +function buffer(b: Buffer) { + var s:string; + s = b.toString() + b.toString('utf8') + b.toString('hex'); + b = Buffer.concat([b, Buffer.from([0,1,2])]); + + b.equals(b); +} + +function builtins() { njs.dump('asdf'); njs.version != process.argv[1]; } From xeioex at nginx.com Tue Oct 20 15:50:23 2020 From: xeioex at nginx.com (Dmitry Volyntsev) Date: Tue, 20 Oct 2020 15:50:23 +0000 Subject: [njs] Added TypeScript description for fs module. Message-ID: details: https://hg.nginx.org/njs/rev/6b84320e31d4 branches: changeset: 1543:6b84320e31d4 user: Jakub Jirutka date: Fri Oct 09 02:33:31 2020 +0200 description: Added TypeScript description for fs module. diffstat: src/ts/fs.d.ts | 384 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++ test/ts/test.ts | 10 + 2 files changed, 394 insertions(+), 0 deletions(-) diffs (413 lines): diff -r 5eab7463f984 -r 6b84320e31d4 src/ts/fs.d.ts --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/ts/fs.d.ts Fri Oct 09 02:33:31 2020 +0200 @@ -0,0 +1,384 @@ +/// + +declare module "fs" { + + /** + * File system flag that controls opening of a file. + * + * - `'a'` - Open a file for appending. The file is created if it does not exist. + * - `'ax'` - The same as `'a'` but fails if the file already exists. + * - `'a+'` - Open a file for reading and appending. If the file does not exist, it will be created. + * - `'ax+'` - The same as `'a+'` but fails if the file already exists. + * - `'as'` - Open a file for appending in synchronous mode. If the file does not exist, it will be created. + * - `'as+'` - Open a file for reading and appending in synchronous mode. If the file does not exist, it will be created. + * - `'r'` - Open a file for reading. An exception occurs if the file does not exist. + * - `'r+'` - Open a file for reading and writing. An exception occurs if the file does not exist. + * - `'rs+'` - Open a file for reading and writing in synchronous mode. Instructs the operating system to bypass the local file system cache. + * - `'w'` - Open a file for writing. If the file does not exist, it will be created. If the file exists, it will be replaced. + * - `'wx'` - The same as `'w'` but fails if the file already exists. + * - `'w+'` - Open a file for reading and writing. If the file does not exist, it will be created. If the file exists, it will be replaced. + * - `'wx+'` - The same as `'w+'` but fails if the file already exists. + */ + export type OpenMode = "a" | "ax" | "a+" | "ax+" | "as" | "as+" | "r" | "r+" | "rs+" | "w" | "wx" | "w+" | "wx+"; + + export type FileEncoding = BufferEncoding; + + /** + * Valid types for path values in "fs". + */ + export type PathLike = string | Buffer; + + /** + * A representation of a directory entry - a file or a subdirectory. + * + * When `readdirSync()` is called with the `withFileTypes` option, the resulting array contains + * `fs.Dirent` objects. + */ + export interface Dirent { + /** + * @returns `true` if the object describes a block device. + */ + isBlockDevice(): boolean; + /** + * @returns `true` if the object describes a character device. + */ + isCharacterDevice(): boolean; + /** + * @returns `true` if the object describes a file system directory. + */ + isDirectory(): boolean; + /** + * @returns `true` if the object describes a first-in-first-out (FIFO) pipe. + */ + isFIFO(): boolean; + /** + * @returns `true` if the object describes a regular file. + */ + isFile(): boolean; + /** + * @returns `true` if the object describes a socket. + */ + isSocket(): boolean; + /** + * @returns `true` if the object describes a symbolic link. + */ + isSymbolicLink(): boolean; + + /** + * The name of the file this object refers to. + */ + name: string; + } + + type WriteFileOptions = { + mode?: number; + flag?: OpenMode; + }; + + type Constants = { + /** + * Indicates that the file is visible to the calling process, used by default if no mode + * is specified. + */ + F_OK: 0; + /** + * Indicates that the file can be read by the calling process. + */ + R_OK: 4; + /** + * Indicates that the file can be written by the calling process. + */ + W_OK: 2; + /** + * Indicates that the file can be executed by the calling process. + */ + X_OK: 1; + }; + + interface Promises { + /** + * Asynchronously tests permissions for a file or directory specified in the `path`. + * If the check fails, an error will be returned, otherwise, the method will return undefined. + * + * @example + * import fs from 'fs' + * fs.promises.access('/file/path', fs.constants.R_OK | fs.constants.W_OK) + * .then(() => console.log('has access')) + * .catch(() => console.log('no access')) + * + * @since 0.3.9 + * @param path A path to a file or directory. + * @param mode An optional integer that specifies the accessibility checks to be performed. + * Defaults to `fs.constants.F_OK`. + */ + access(path: PathLike, mode?: number): Promise; + + /** + * Asynchronously appends specified `data` to a file with provided `filename`. + * If the file does not exist, it will be created. + * + * @since 0.4.4 + * @param path A path to a file. + * @param data The data to write. + * @param options An object optionally specifying the file mode and flag. + * If `mode` is not supplied, the default of `0o666` is used. + * If `flag` is not supplied, the default of `'a'` is used. + */ + appendFile(path: PathLike, data: NjsStringLike | Buffer, options?: WriteFileOptions): Promise; + + /** + * Asynchronously creates a directory at the specified `path`. + * + * @since 0.4.2 + * @param path A path to a file. + * @param options The file mode (or an object specifying the file mode). Defaults to `0o777`. + */ + mkdir(path: PathLike, options?: { mode?: number } | number): Promise; + + /** + * Asynchronously reads the contents of a directory at the specified `path`. + * + * @since 0.4.2 + * @param path A path to a file. + * @param options A string that specifies encoding or an object optionally specifying + * the following keys: + * - `encoding` - `'utf8'` (default) or `'buffer'` (since 0.4.4) + * - `withFileTypes` - if set to `true`, the files array will contain `fs.Dirent` objects; defaults to `false`. + */ + readdir(path: PathLike, options?: { encoding?: "utf8"; withFileTypes?: false; } | "utf8"): Promise; + readdir(path: PathLike, options: { encoding: "buffer"; withFileTypes?: false; } | "buffer"): Promise; + readdir(path: PathLike, options: { encoding?: "utf8" | "buffer"; withFileTypes: true; }): Promise; + + /** + * Asynchronously returns the contents of the file with provided `filename`. + * If an encoding is specified, a `string` is returned, otherwise, a `Buffer`. + * + * @param path A path to a file. + * @param options A string that specifies encoding or an object with the following optional keys: + * - `encoding` - `'utf8'`, `'hex'`, `'base64'`, or `'base64url'` (the last three since 0.4.4). + * - `flag` - file system flag, defaults to `r`. + */ + readFile(path: PathLike): Promise; + readFile(path: PathLike, options?: { flag?: OpenMode; }): Promise; + readFile(path: PathLike, options: { encoding?: FileEncoding; flag?: OpenMode; } | FileEncoding): Promise; + + /** + * Asynchronously computes the canonical pathname by resolving `.`, `..` and symbolic links using + * `realpath(3)`. + * + * @since 0.3.9 + * @param path A path to a file. + * @param options The encoding (or an object specifying the encoding), used as the encoding of the result. + */ + realpath(path: PathLike, options?: { encoding?: "utf8" } | "utf8"): Promise; + realpath(path: PathLike, options: { encoding: "buffer" } | "buffer"): Promise; + + /** + * Asynchronously changes the name or location of a file from `oldPath` to `newPath`. + * + * @since 0.3.4 + * @param oldPath A path to a file. + * @param newPath A path to a file. + */ + rename(oldPath: PathLike, newPath: PathLike): Promise; + + /** + * Asynchronously removes a directory at the specified `path`. + * + * @since 0.4.2 + * @param path A path to a file. + */ + rmdir(path: PathLike): Promise; + + /** + * Asynchronously creates the link called `path` pointing to `target` using `symlink(2)`. + * Relative targets are relative to the link?s parent directory. + * + * @since 0.3.9 + * @param target A path to an existing file. + * @param path A path to the new symlink. + */ + symlink(target: PathLike, path: PathLike): Promise; + + /** + * Asynchronously unlinks a file by `path`. + * + * @since 0.3.9 + * @param path A path to a file. + */ + unlink(path: PathLike): Promise; + + /** + * Asynchronously writes `data` to a file with provided `filename`. If the file does not + * exist, it will be created, if the file exists, it will be replaced. + * + * @since 0.4.4 + * @param path A path to a file. + * @param data The data to write. + * @param options An object optionally specifying the file mode and flag. + * If `mode` is not supplied, the default of `0o666` is used. + * If `flag` is not supplied, the default of `'w'` is used. + */ + writeFile(path: PathLike, data: NjsStringLike | Buffer, options?: WriteFileOptions): Promise; + } + + interface NjsFS { + /** + * Promissified versions of file system methods. + * + * @since 0.3.9 + */ + promises: Promises + /** + * File Access Constants + */ + constants: Constants + + /** + * Synchronously tests permissions for a file or directory specified in the `path`. + * If the check fails, an error will be returned, otherwise, the method will return undefined. + * + * @example + * try { + * fs.accessSync('/file/path', fs.constants.R_OK | fs.constants.W_OK); + * console.log('has access'); + * } catch (e) { + * console.log('no access'); + * } + * + * @since 0.3.9 + * @param path A path to a file or directory. + * @param mode An optional integer that specifies the accessibility checks to be performed. + * Defaults to `fs.constants.F_OK`. + */ + accessSync(path: PathLike, mode?: number): void; + + /** + * Synchronously appends specified `data` to a file with provided `filename`. + * If the file does not exist, it will be created. + * + * @since 0.4.4 + * @param path A path to a file. + * @param data The data to write. + * @param options An object optionally specifying the file mode and flag. + * If `mode` is not supplied, the default of `0o666` is used. + * If `flag` is not supplied, the default of `'a'` is used. + */ + appendFileSync(path: PathLike, data: NjsStringLike | Buffer, options?: WriteFileOptions): void; + + /** + * Synchronously creates a directory at the specified `path`. + * + * @since 0.4.2 + * @param path A path to a file. + * @param options The file mode (or an object specifying the file mode). Defaults to `0o777`. + */ + mkdirSync(path: PathLike, options?: { mode?: number } | number): void; + + /** + * Synchronously reads the contents of a directory at the specified `path`. + * + * @since 0.4.2 + * @param path A path to a file. + * @param options A string that specifies encoding or an object optionally specifying + * the following keys: + * - `encoding` - `'utf8'` (default) or `'buffer'` (since 0.4.4) + * - `withFileTypes` - if set to `true`, the files array will contain `fs.Dirent` objects; + * defaults to `false`. + */ + readdirSync(path: PathLike, options?: { encoding?: "utf8"; withFileTypes?: false; } | "utf8"): string[]; + readdirSync(path: PathLike, options: { encoding: "buffer"; withFileTypes?: false; } | "buffer"): Buffer[]; + readdirSync(path: PathLike, options: { encoding?: "utf8" | "buffer"; withFileTypes: true; }): Dirent[]; + + /** + * Synchronously returns the contents of the file with provided `filename`. + * If an encoding is specified, a `string` is returned, otherwise, a `Buffer`. + * + * @example + * import fs from 'fs' + * var file = fs.readFileSync('/file/path.tar.gz') + * var gzipped = file.slice(0,2).toString('hex') === '1f8b'; gzipped // => true + * + * @param path A path to a file. + * @param options A string that specifies encoding or an object with the following optional keys: + * - `encoding` - `'utf8'`, `'hex'`, `'base64'`, or `'base64url'` (the last three since 0.4.4). + * - `flag` - file system flag, defaults to `r`. + */ + readFileSync(path: PathLike): Buffer; + readFileSync(path: PathLike, options?: { flag?: OpenMode; }): Buffer; + readFileSync(path: PathLike, options: { encoding?: FileEncoding; flag?: OpenMode; } | FileEncoding): string; + + /** + * Synchronously computes the canonical pathname by resolving `.`, `..` and symbolic links using + * `realpath(3)`. + * + * @since 0.3.9 + * @param path A path to a file. + * @param options The encoding (or an object specifying the encoding), used as the encoding of the result. + */ + realpathSync(path: PathLike, options?: { encoding?: "utf8" } | "utf8"): string; + realpathSync(path: PathLike, options: { encoding: "buffer" } | "buffer"): Buffer; + + /** + * Synchronously changes the name or location of a file from `oldPath` to `newPath`. + * + * @example + * import fs from 'fs' + * var file = fs.renameSync('hello.txt', 'HelloWorld.txt') + * + * @since 0.3.4 + * @param oldPath A path to a file. + * @param newPath A path to a file. + */ + renameSync(oldPath: PathLike, newPath: PathLike): void; + + /** + * Synchronously removes a directory at the specified `path`. + * + * @since 0.4.2 + * @param path A path to a file. + */ + rmdirSync(path: PathLike): void; + + /** + * Synchronously creates the link called `path` pointing to `target` using `symlink(2)`. + * Relative targets are relative to the link?s parent directory. + * + * @since 0.3.9 + * @param target A path to an existing file. + * @param path A path to the new symlink. + */ + symlinkSync(target: PathLike, path: PathLike): void; + + /** + * Synchronously unlinks a file by `path`. + * + * @since 0.3.9 + * @param path A path to a file. + */ + unlinkSync(path: PathLike): void; + + /** + * Synchronously writes `data` to a file with provided `filename`. If the file does not exist, + * it will be created, if the file exists, it will be replaced. + * + * @example + * import fs from 'fs' + * fs.writeFileSync('hello.txt', 'Hello world') + * + * @since 0.4.4 + * @param path A path to a file. + * @param data The data to write. + * @param options An object optionally specifying the file mode and flag. + * If `mode` is not supplied, the default of `0o666` is used. + * If `flag` is not supplied, the default of `'w'` is used. + */ + writeFileSync(path: PathLike, data: NjsStringLike | Buffer, options?: WriteFileOptions): void; + } + + const fs: NjsFS; + + // It's exported like this because njs doesn't support named imports. + // TODO: Replace NjsFS with individual named exports as soon as njs supports named imports. + export default fs; +} diff -r 5eab7463f984 -r 6b84320e31d4 test/ts/test.ts --- a/test/ts/test.ts Sat Oct 17 01:38:31 2020 +0200 +++ b/test/ts/test.ts Fri Oct 09 02:33:31 2020 +0200 @@ -1,4 +1,7 @@ /// +/// + +import fs from 'fs'; function http_module(r: NginxHTTPRequest) { var bs: NjsByteString; @@ -61,6 +64,13 @@ function http_module(r: NginxHTTPRequest } +function fs_module() { + var s:string; + + s = fs.readFileSync('/path', 'utf8'); + s = fs.readFileSync(Buffer.from('/path'), {encoding:'hex'}); +} + function buffer(b: Buffer) { var s:string; From xeioex at nginx.com Tue Oct 20 15:50:25 2020 From: xeioex at nginx.com (Dmitry Volyntsev) Date: Tue, 20 Oct 2020 15:50:25 +0000 Subject: [njs] Added TypeScript description for querystring module. Message-ID: details: https://hg.nginx.org/njs/rev/e7fb6e22acb7 branches: changeset: 1544:e7fb6e22acb7 user: Jakub Jirutka date: Fri Oct 09 17:05:47 2020 +0200 description: Added TypeScript description for querystring module. diffstat: src/ts/querystring.d.ts | 101 ++++++++++++++++++++++++++++++++++++++++++++++++ test/ts/test.ts | 10 ++++ 2 files changed, 111 insertions(+), 0 deletions(-) diffs (133 lines): diff -r 6b84320e31d4 -r e7fb6e22acb7 src/ts/querystring.d.ts --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/ts/querystring.d.ts Fri Oct 09 17:05:47 2020 +0200 @@ -0,0 +1,101 @@ +/// + +declare module "querystring" { + + export interface ParsedUrlQuery { + [key: string]: string | string[] | undefined; + } + + export interface ParsedUrlQueryInput { + [key: string]: NjsStringLike | number | boolean | NjsStringLike[] | number[] | boolean[] | null | undefined; + } + + interface ParseOptions { + /** + * Function used to decode percent-encoded characters in the query string. + * Defaults to `querystring.unescape()`. + */ + decodeURIComponent?: (str: NjsStringLike) => string; + + /** + * The maximum number of keys to parse; defaults to `1000`. + * The `0` value removes limitations for counting keys. + */ + maxKeys?: number; + } + + interface StringifyOptions { + /** + * The function to use when converting URL-unsafe characters to percent-encoding in the + * query string; defaults to `querystring.escape()`. + */ + encodeURIComponent?: (str: NjsStringLike) => string; + } + + interface QueryString { + /** + * Performs URL encoding of the given string `str`, returns an escaped query string. + * The method is used by `querystring.stringify()` and should not be used directly. + * + * @param str The query string to escape. + * @return The escaped query string. + */ + escape(str: NjsStringLike): string; + + /** + * Parses the query string URL and returns an object. + * + * By default, percent-encoded characters within the query string are assumed to use the + * UTF-8 encoding, invalid UTF-8 sequences will be replaced with the `U+FFFD` replacement + * character. + * + * @param query The query string. + * @param separator The substring for delimiting key and value pairs in the query string; defaults to `'&'`. + * @param equal The substring for delimiting keys and values in the query string, defaults to `'='`. + * @param options An object optionally specifying `decodeURIComponent` function and `maxKeys` number. + * @return An object containing the components of the query string. + */ + parse(query: NjsStringLike, separator?: NjsStringLike, equal?: NjsStringLike, options?: ParseOptions): ParsedUrlQuery; + + /** + * An alias for `querystring.parse()`. + */ + decode(query: NjsStringLike, separator?: NjsStringLike, equal?: NjsStringLike, options?: ParseOptions): ParsedUrlQuery; + + /** + * Serializes an object and returns a URL query string. + * + * By default, characters that require percent-encoding within the query string are encoded + * as UTF-8. If other encoding is required, then `encodeURIComponent` option should be + * specified. + * + * @param obj The data to convert to a query string. + * @param separator The substring for delimiting key and value pairs in the query string; defaults to `'&'`. + * @param equal The substring for delimiting keys and values in the query string; defaults to `'='`. + * @param options An object optionally specifying `encodeURIComponent` function. + * @return A query string. + */ + stringify(obj: ParsedUrlQueryInput, separator?: NjsStringLike, equal?: NjsStringLike, options?: StringifyOptions): string; + + /** + * An alias for `querystring.stringify()`. + */ + encode(obj: ParsedUrlQueryInput, separator?: NjsStringLike, equal?: NjsStringLike, options?: StringifyOptions): string; + + /** + * Performs decoding of URL percent-encoded characters of the string `str`, returns an + * unescaped query string. The method is used by `querystring.parse()` and should not be + * used directly. + * + * @param str An escaped query string. + * @return An unescaped string. + */ + unescape(str: NjsStringLike): string; + } + + const querystring: QueryString; + + // It's exported like this because njs doesn't support named imports. + // TODO: Replace NjsFS with individual named exports as soon as njs supports named imports. + export default querystring; +} diff -r 6b84320e31d4 -r e7fb6e22acb7 test/ts/test.ts --- a/test/ts/test.ts Fri Oct 09 02:33:31 2020 +0200 +++ b/test/ts/test.ts Fri Oct 09 17:05:47 2020 +0200 @@ -1,7 +1,9 @@ /// /// +/// import fs from 'fs'; +import qs from 'querystring'; function http_module(r: NginxHTTPRequest) { var bs: NjsByteString; @@ -71,6 +73,14 @@ function fs_module() { s = fs.readFileSync(Buffer.from('/path'), {encoding:'hex'}); } +function qs_module(str: NjsByteString) { + var o; + var s:string; + + o = qs.parse(str); + s = qs.stringify(o); +} + function buffer(b: Buffer) { var s:string; From xeioex at nginx.com Tue Oct 20 15:50:27 2020 From: xeioex at nginx.com (Dmitry Volyntsev) Date: Tue, 20 Oct 2020 15:50:27 +0000 Subject: [njs] Added TypeScript description for crypto module. Message-ID: details: https://hg.nginx.org/njs/rev/11da5c960017 branches: changeset: 1545:11da5c960017 user: Jakub Jirutka date: Fri Oct 09 17:28:58 2020 +0200 description: Added TypeScript description for crypto module. diffstat: src/ts/crypto.d.ts | 76 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ test/ts/test.ts | 14 +++++++++ 2 files changed, 90 insertions(+), 0 deletions(-) diffs (114 lines): diff -r e7fb6e22acb7 -r 11da5c960017 src/ts/crypto.d.ts --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/ts/crypto.d.ts Fri Oct 09 17:28:58 2020 +0200 @@ -0,0 +1,76 @@ +/// + +declare module "crypto" { + + export type Algorithm = "md5" | "sha1" | "sha256"; + + export type DigestEncoding = Exclude; + + export interface Hash { + /** + * Updates the hash content with the given `data` and returns self. + */ + update(data: NjsStringLike | Buffer | DataView | TypedArray): Hash; + + /** + * Calculates the digest of all of the data passed using `hash.update()`. + * + * @example + * import cr from 'crypto' + * cr.createHash('sha1').update('A').update('B').digest('base64url') // => 'BtlFlCqiamG-GMPiK_GbvKjdK10' + * + * @param encoding The encoding of the return value. If not provided, a `Buffer` object + * (or a byte string before version 0.4.4) is returned. + * @return A calculated digest. + */ + digest(): Buffer; + digest(encoding: DigestEncoding): string; + } + + export interface Hmac { + /** + * Updates the HMAC content with the given `data` and returns self. + */ + update(data: NjsStringLike | Buffer | DataView | TypedArray): Hmac; + + /** + * Calculates the HMAC digest of all of the data passed using `hmac.update()`. + * + * @example + * import cr from 'crypto' + * cr.createHmac('sha1', 'secret.key').update('AB').digest('base64url') // => 'Oglm93xn23_MkiaEq_e9u8zk374' + * + * @param encoding The encoding of the return value. If not provided, a `Buffer` object + * (or a byte string before version 0.4.4) is returned. + * @return The calculated HMAC digest. + */ + digest(): Buffer; + digest(encoding: DigestEncoding): string; + } + + interface Crypto { + /** + * Creates and returns a `Hash` object that can be used to generate hash digests using + * the given `algorithm`. + * + * @param algorithm `'md5'`, `'sha1'`, or `'sha256'` + * @returns A `Hash` object. + */ + createHash(algorithm: Algorithm): Hash; + + /** + * Creates and returns an HMAC object that uses the given `algorithm` and secret `key`. + * + * @param algorithm `'md5'`, `'sha1'`, or `'sha256'` + * @param key The secret key. + * @returns An `HMAC` object. + */ + createHmac(algorithm: Algorithm, key: NjsStringLike): Hmac; + } + + const crypto: Crypto; + + // It's exported like this because njs doesn't support named imports. + // TODO: Replace NjsFS with individual named exports as soon as njs supports named imports. + export default crypto; +} diff -r e7fb6e22acb7 -r 11da5c960017 test/ts/test.ts --- a/test/ts/test.ts Fri Oct 09 17:05:47 2020 +0200 +++ b/test/ts/test.ts Fri Oct 09 17:28:58 2020 +0200 @@ -1,9 +1,11 @@ /// /// /// +/// import fs from 'fs'; import qs from 'querystring'; +import crypto from 'crypto'; function http_module(r: NginxHTTPRequest) { var bs: NjsByteString; @@ -81,6 +83,18 @@ function qs_module(str: NjsByteString) { s = qs.stringify(o); } +function crypto_module(str: NjsByteString) { + var h; + var b:Buffer; + var s:string; + + h = crypto.createHash("sha1"); + h = h.update(str).update(Buffer.from([0])); + b = h.digest(); + + s = crypto.createHash("sha256").digest("hex"); +} + function buffer(b: Buffer) { var s:string; From xeioex at nginx.com Tue Oct 20 15:50:29 2020 From: xeioex at nginx.com (Dmitry Volyntsev) Date: Tue, 20 Oct 2020 15:50:29 +0000 Subject: [njs] Types: mark String.bytesFrom() in as deprecated. Message-ID: details: https://hg.nginx.org/njs/rev/3d8f6b9548c0 branches: changeset: 1546:3d8f6b9548c0 user: Jakub Jirutka date: Mon Oct 19 21:42:01 2020 +0200 description: Types: mark String.bytesFrom() in as deprecated. diffstat: src/ts/njs_core.d.ts | 4 ++++ 1 files changed, 4 insertions(+), 0 deletions(-) diffs (18 lines): diff -r 11da5c960017 -r 3d8f6b9548c0 src/ts/njs_core.d.ts --- a/src/ts/njs_core.d.ts Fri Oct 09 17:28:58 2020 +0200 +++ b/src/ts/njs_core.d.ts Mon Oct 19 21:42:01 2020 +0200 @@ -3,10 +3,14 @@ type BufferEncoding = "utf8" | "hex" | " interface StringConstructor { /** * Creates a byte string from an encoded string. + * + * @deprecated will be removed in the future. */ bytesFrom(bytes: string, encoding: Exclude): NjsByteString; /** * Creates a byte string from an array that contains octets. + * + * @deprecated will be removed in the future. */ bytesFrom(bytes: Array): NjsByteString; } From mdounin at mdounin.ru Thu Oct 22 15:02:04 2020 From: mdounin at mdounin.ru (Maxim Dounin) Date: Thu, 22 Oct 2020 15:02:04 +0000 Subject: [nginx] Core: ngx_conf_set_keyval_slot() now accepts NGX_CONF_UNSET_PTR. Message-ID: details: https://hg.nginx.org/nginx/rev/485dba3e2a01 branches: changeset: 7728:485dba3e2a01 user: Maxim Dounin date: Thu Oct 22 18:00:20 2020 +0300 description: Core: ngx_conf_set_keyval_slot() now accepts NGX_CONF_UNSET_PTR. With this change, it is now possible to use ngx_conf_merge_ptr_value() to merge keyval arrays. This change actually follows much earlier changes in ngx_conf_merge_ptr_value() and ngx_conf_set_str_array_slot() in 1452:cd586e963db0 (0.6.10) and 1701:40d004d95d88 (0.6.22). To preserve compatibility with existing 3rd party modules, both NULL and NGX_CONF_UNSET_PTR are accepted for now. diffstat: src/core/ngx_conf_file.c | 2 +- src/http/modules/ngx_http_grpc_module.c | 8 +++++--- src/http/modules/ngx_http_proxy_module.c | 8 +++++--- 3 files changed, 11 insertions(+), 7 deletions(-) diffs (81 lines): diff -r f1e6f65ddfeb -r 485dba3e2a01 src/core/ngx_conf_file.c --- a/src/core/ngx_conf_file.c Tue Oct 13 07:44:09 2020 +0300 +++ b/src/core/ngx_conf_file.c Thu Oct 22 18:00:20 2020 +0300 @@ -1137,7 +1137,7 @@ ngx_conf_set_keyval_slot(ngx_conf_t *cf, a = (ngx_array_t **) (p + cmd->offset); - if (*a == NULL) { + if (*a == NGX_CONF_UNSET_PTR || *a == NULL) { *a = ngx_array_create(cf->pool, 4, sizeof(ngx_keyval_t)); if (*a == NULL) { return NGX_CONF_ERROR; diff -r f1e6f65ddfeb -r 485dba3e2a01 src/http/modules/ngx_http_grpc_module.c --- a/src/http/modules/ngx_http_grpc_module.c Tue Oct 13 07:44:09 2020 +0300 +++ b/src/http/modules/ngx_http_grpc_module.c Thu Oct 22 18:00:20 2020 +0300 @@ -4324,7 +4324,6 @@ ngx_http_grpc_create_loc_conf(ngx_conf_t * conf->upstream.hide_headers_hash = { NULL, 0 }; * conf->upstream.ssl_name = NULL; * - * conf->headers_source = NULL; * conf->headers.lengths = NULL; * conf->headers.values = NULL; * conf->headers.hash = { NULL, 0 }; @@ -4377,6 +4376,8 @@ ngx_http_grpc_create_loc_conf(ngx_conf_t conf->upstream.pass_trailers = 1; conf->upstream.preserve_output = 1; + conf->headers_source = NGX_CONF_UNSET_PTR; + ngx_str_set(&conf->upstream.module, "grpc"); return conf; @@ -4507,9 +4508,10 @@ ngx_http_grpc_merge_loc_conf(ngx_conf_t clcf->handler = ngx_http_grpc_handler; } - if (conf->headers_source == NULL) { + ngx_conf_merge_ptr_value(conf->headers_source, prev->headers_source, NULL); + + if (conf->headers_source == prev->headers_source) { conf->headers = prev->headers; - conf->headers_source = prev->headers_source; conf->host_set = prev->host_set; } diff -r f1e6f65ddfeb -r 485dba3e2a01 src/http/modules/ngx_http_proxy_module.c --- a/src/http/modules/ngx_http_proxy_module.c Tue Oct 13 07:44:09 2020 +0300 +++ b/src/http/modules/ngx_http_proxy_module.c Thu Oct 22 18:00:20 2020 +0300 @@ -3268,7 +3268,6 @@ ngx_http_proxy_create_loc_conf(ngx_conf_ * conf->method = NULL; * conf->location = NULL; * conf->url = { 0, NULL }; - * conf->headers_source = NULL; * conf->headers.lengths = NULL; * conf->headers.values = NULL; * conf->headers.hash = { NULL, 0 }; @@ -3346,6 +3345,8 @@ ngx_http_proxy_create_loc_conf(ngx_conf_ /* "proxy_cyclic_temp_file" is disabled */ conf->upstream.cyclic_temp_file = 0; + conf->headers_source = NGX_CONF_UNSET_PTR; + conf->redirect = NGX_CONF_UNSET; conf->upstream.change_buffering = 1; @@ -3819,12 +3820,13 @@ ngx_http_proxy_merge_loc_conf(ngx_conf_t } } - if (conf->headers_source == NULL) { + ngx_conf_merge_ptr_value(conf->headers_source, prev->headers_source, NULL); + + if (conf->headers_source == prev->headers_source) { conf->headers = prev->headers; #if (NGX_HTTP_CACHE) conf->headers_cache = prev->headers_cache; #endif - conf->headers_source = prev->headers_source; } rc = ngx_http_proxy_init_headers(cf, conf, &conf->headers, From mdounin at mdounin.ru Thu Oct 22 15:02:07 2020 From: mdounin at mdounin.ru (Maxim Dounin) Date: Thu, 22 Oct 2020 15:02:07 +0000 Subject: [nginx] SSL: ssl_conf_command directive. Message-ID: details: https://hg.nginx.org/nginx/rev/3bff3f397c05 branches: changeset: 7729:3bff3f397c05 user: Maxim Dounin date: Thu Oct 22 18:00:22 2020 +0300 description: SSL: ssl_conf_command directive. With the ssl_conf_command directive it is now possible to set arbitrary OpenSSL configuration parameters as long as nginx is compiled with OpenSSL 1.0.2 or later. Full list of available configuration commands can be found in the SSL_CONF_cmd manual page (https://www.openssl.org/docs/man1.1.1/man3/SSL_CONF_cmd.html). In particular, this allows configuring PrioritizeChaCha option (ticket #1445): ssl_conf_command Options PrioritizeChaCha; It can be also used to configure TLSv1.3 ciphers in OpenSSL, which fails to configure them via the SSL_CTX_set_cipher_list() interface (ticket #1529): ssl_conf_command Ciphersuites TLS_CHACHA20_POLY1305_SHA256; Configuration commands are applied after nginx own configuration for SSL, so they can be used to override anything set by nginx. Note though that configuring OpenSSL directly with ssl_conf_command might result in a behaviour nginx does not expect, and should be done with care. diffstat: src/event/ngx_event_openssl.c | 72 ++++++++++++++++++++++++++++++++++ src/event/ngx_event_openssl.h | 4 + src/http/modules/ngx_http_ssl_module.c | 32 +++++++++++++++ src/http/modules/ngx_http_ssl_module.h | 1 + src/mail/ngx_mail_ssl_module.c | 32 +++++++++++++++ src/mail/ngx_mail_ssl_module.h | 1 + src/stream/ngx_stream_ssl_module.c | 33 +++++++++++++++ src/stream/ngx_stream_ssl_module.h | 1 + 8 files changed, 176 insertions(+), 0 deletions(-) diffs (386 lines): diff -r 485dba3e2a01 -r 3bff3f397c05 src/event/ngx_event_openssl.c --- a/src/event/ngx_event_openssl.c Thu Oct 22 18:00:20 2020 +0300 +++ b/src/event/ngx_event_openssl.c Thu Oct 22 18:00:22 2020 +0300 @@ -1471,6 +1471,78 @@ ngx_ssl_early_data(ngx_conf_t *cf, ngx_s ngx_int_t +ngx_ssl_conf_commands(ngx_conf_t *cf, ngx_ssl_t *ssl, ngx_array_t *commands) +{ + if (commands == NULL) { + return NGX_OK; + } + +#ifdef SSL_CONF_FLAG_FILE + { + int type; + u_char *key, *value; + ngx_uint_t i; + ngx_keyval_t *cmd; + SSL_CONF_CTX *cctx; + + cctx = SSL_CONF_CTX_new(); + if (cctx == NULL) { + ngx_ssl_error(NGX_LOG_EMERG, ssl->log, 0, + "SSL_CONF_CTX_new() failed"); + return NGX_ERROR; + } + + SSL_CONF_CTX_set_flags(cctx, SSL_CONF_FLAG_FILE); + SSL_CONF_CTX_set_flags(cctx, SSL_CONF_FLAG_SERVER); + SSL_CONF_CTX_set_flags(cctx, SSL_CONF_FLAG_CLIENT); + SSL_CONF_CTX_set_flags(cctx, SSL_CONF_FLAG_CERTIFICATE); + SSL_CONF_CTX_set_flags(cctx, SSL_CONF_FLAG_SHOW_ERRORS); + + SSL_CONF_CTX_set_ssl_ctx(cctx, ssl->ctx); + + cmd = commands->elts; + for (i = 0; i < commands->nelts; i++) { + + key = cmd[i].key.data; + type = SSL_CONF_cmd_value_type(cctx, (char *) key); + + if (type == SSL_CONF_TYPE_FILE || type == SSL_CONF_TYPE_DIR) { + if (ngx_conf_full_name(cf->cycle, &cmd[i].value, 1) != NGX_OK) { + SSL_CONF_CTX_free(cctx); + return NGX_ERROR; + } + } + + value = cmd[i].value.data; + + if (SSL_CONF_cmd(cctx, (char *) key, (char *) value) <= 0) { + ngx_ssl_error(NGX_LOG_EMERG, ssl->log, 0, + "SSL_CONF_cmd(\"%s\", \"%s\") failed", key, value); + SSL_CONF_CTX_free(cctx); + return NGX_ERROR; + } + } + + if (SSL_CONF_CTX_finish(cctx) != 1) { + ngx_ssl_error(NGX_LOG_EMERG, ssl->log, 0, + "SSL_CONF_finish() failed"); + SSL_CONF_CTX_free(cctx); + return NGX_ERROR; + } + + SSL_CONF_CTX_free(cctx); + + return NGX_OK; + } +#else + ngx_log_error(NGX_LOG_EMERG, ssl->log, 0, + "SSL_CONF_cmd() is not available on this platform"); + return NGX_ERROR; +#endif +} + + +ngx_int_t ngx_ssl_client_session_cache(ngx_conf_t *cf, ngx_ssl_t *ssl, ngx_uint_t enable) { if (!enable) { diff -r 485dba3e2a01 -r 3bff3f397c05 src/event/ngx_event_openssl.h --- a/src/event/ngx_event_openssl.h Thu Oct 22 18:00:20 2020 +0300 +++ b/src/event/ngx_event_openssl.h Thu Oct 22 18:00:22 2020 +0300 @@ -203,6 +203,9 @@ ngx_int_t ngx_ssl_dhparam(ngx_conf_t *cf ngx_int_t ngx_ssl_ecdh_curve(ngx_conf_t *cf, ngx_ssl_t *ssl, ngx_str_t *name); ngx_int_t ngx_ssl_early_data(ngx_conf_t *cf, ngx_ssl_t *ssl, ngx_uint_t enable); +ngx_int_t ngx_ssl_conf_commands(ngx_conf_t *cf, ngx_ssl_t *ssl, + ngx_array_t *commands); + ngx_int_t ngx_ssl_client_session_cache(ngx_conf_t *cf, ngx_ssl_t *ssl, ngx_uint_t enable); ngx_int_t ngx_ssl_session_cache(ngx_ssl_t *ssl, ngx_str_t *sess_ctx, @@ -211,6 +214,7 @@ ngx_int_t ngx_ssl_session_cache(ngx_ssl_ ngx_int_t ngx_ssl_session_ticket_keys(ngx_conf_t *cf, ngx_ssl_t *ssl, ngx_array_t *paths); ngx_int_t ngx_ssl_session_cache_init(ngx_shm_zone_t *shm_zone, void *data); + ngx_int_t ngx_ssl_create_connection(ngx_ssl_t *ssl, ngx_connection_t *c, ngx_uint_t flags); diff -r 485dba3e2a01 -r 3bff3f397c05 src/http/modules/ngx_http_ssl_module.c --- a/src/http/modules/ngx_http_ssl_module.c Thu Oct 22 18:00:20 2020 +0300 +++ b/src/http/modules/ngx_http_ssl_module.c Thu Oct 22 18:00:22 2020 +0300 @@ -53,6 +53,9 @@ static char *ngx_http_ssl_session_cache( static char *ngx_http_ssl_ocsp_cache(ngx_conf_t *cf, ngx_command_t *cmd, void *conf); +static char *ngx_http_ssl_conf_command_check(ngx_conf_t *cf, void *post, + void *data); + static ngx_int_t ngx_http_ssl_init(ngx_conf_t *cf); @@ -89,6 +92,10 @@ static ngx_conf_deprecated_t ngx_http_s }; +static ngx_conf_post_t ngx_http_ssl_conf_command_post = + { ngx_http_ssl_conf_command_check }; + + static ngx_command_t ngx_http_ssl_commands[] = { { ngx_string("ssl"), @@ -280,6 +287,13 @@ static ngx_command_t ngx_http_ssl_comma offsetof(ngx_http_ssl_srv_conf_t, early_data), NULL }, + { ngx_string("ssl_conf_command"), + NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_CONF_TAKE2, + ngx_conf_set_keyval_slot, + NGX_HTTP_SRV_CONF_OFFSET, + offsetof(ngx_http_ssl_srv_conf_t, conf_commands), + &ngx_http_ssl_conf_command_post }, + ngx_null_command }; @@ -606,6 +620,7 @@ ngx_http_ssl_create_srv_conf(ngx_conf_t sscf->certificates = NGX_CONF_UNSET_PTR; sscf->certificate_keys = NGX_CONF_UNSET_PTR; sscf->passwords = NGX_CONF_UNSET_PTR; + sscf->conf_commands = NGX_CONF_UNSET_PTR; sscf->builtin_session_cache = NGX_CONF_UNSET; sscf->session_timeout = NGX_CONF_UNSET; sscf->session_tickets = NGX_CONF_UNSET; @@ -675,6 +690,8 @@ ngx_http_ssl_merge_srv_conf(ngx_conf_t * ngx_conf_merge_str_value(conf->ciphers, prev->ciphers, NGX_DEFAULT_CIPHERS); + ngx_conf_merge_ptr_value(conf->conf_commands, prev->conf_commands, NULL); + ngx_conf_merge_uint_value(conf->ocsp, prev->ocsp, 0); ngx_conf_merge_str_value(conf->ocsp_responder, prev->ocsp_responder, ""); ngx_conf_merge_ptr_value(conf->ocsp_cache_zone, @@ -913,6 +930,10 @@ ngx_http_ssl_merge_srv_conf(ngx_conf_t * return NGX_CONF_ERROR; } + if (ngx_ssl_conf_commands(cf, &conf->ssl, conf->conf_commands) != NGX_OK) { + return NGX_CONF_ERROR; + } + return NGX_CONF_OK; } @@ -1235,6 +1256,17 @@ invalid: } +static char * +ngx_http_ssl_conf_command_check(ngx_conf_t *cf, void *post, void *data) +{ +#ifndef SSL_CONF_FLAG_FILE + return "is not supported on this platform"; +#endif + + return NGX_CONF_OK; +} + + static ngx_int_t ngx_http_ssl_init(ngx_conf_t *cf) { diff -r 485dba3e2a01 -r 3bff3f397c05 src/http/modules/ngx_http_ssl_module.h --- a/src/http/modules/ngx_http_ssl_module.h Thu Oct 22 18:00:20 2020 +0300 +++ b/src/http/modules/ngx_http_ssl_module.h Thu Oct 22 18:00:22 2020 +0300 @@ -48,6 +48,7 @@ typedef struct { ngx_str_t ciphers; ngx_array_t *passwords; + ngx_array_t *conf_commands; ngx_shm_zone_t *shm_zone; diff -r 485dba3e2a01 -r 3bff3f397c05 src/mail/ngx_mail_ssl_module.c --- a/src/mail/ngx_mail_ssl_module.c Thu Oct 22 18:00:20 2020 +0300 +++ b/src/mail/ngx_mail_ssl_module.c Thu Oct 22 18:00:22 2020 +0300 @@ -26,6 +26,9 @@ static char *ngx_mail_ssl_password_file( static char *ngx_mail_ssl_session_cache(ngx_conf_t *cf, ngx_command_t *cmd, void *conf); +static char *ngx_mail_ssl_conf_command_check(ngx_conf_t *cf, void *post, + void *data); + static ngx_conf_enum_t ngx_mail_starttls_state[] = { { ngx_string("off"), NGX_MAIL_STARTTLS_OFF }, @@ -61,6 +64,10 @@ static ngx_conf_deprecated_t ngx_mail_s }; +static ngx_conf_post_t ngx_mail_ssl_conf_command_post = + { ngx_mail_ssl_conf_command_check }; + + static ngx_command_t ngx_mail_ssl_commands[] = { { ngx_string("ssl"), @@ -196,6 +203,13 @@ static ngx_command_t ngx_mail_ssl_comma offsetof(ngx_mail_ssl_conf_t, crl), NULL }, + { ngx_string("ssl_conf_command"), + NGX_MAIL_MAIN_CONF|NGX_MAIL_SRV_CONF|NGX_CONF_TAKE2, + ngx_conf_set_keyval_slot, + NGX_MAIL_SRV_CONF_OFFSET, + offsetof(ngx_mail_ssl_conf_t, conf_commands), + &ngx_mail_ssl_conf_command_post }, + ngx_null_command }; @@ -259,6 +273,7 @@ ngx_mail_ssl_create_conf(ngx_conf_t *cf) scf->certificates = NGX_CONF_UNSET_PTR; scf->certificate_keys = NGX_CONF_UNSET_PTR; scf->passwords = NGX_CONF_UNSET_PTR; + scf->conf_commands = NGX_CONF_UNSET_PTR; scf->prefer_server_ciphers = NGX_CONF_UNSET; scf->verify = NGX_CONF_UNSET_UINT; scf->verify_depth = NGX_CONF_UNSET_UINT; @@ -316,6 +331,8 @@ ngx_mail_ssl_merge_conf(ngx_conf_t *cf, ngx_conf_merge_str_value(conf->ciphers, prev->ciphers, NGX_DEFAULT_CIPHERS); + ngx_conf_merge_ptr_value(conf->conf_commands, prev->conf_commands, NULL); + conf->ssl.log = cf->log; @@ -461,6 +478,10 @@ ngx_mail_ssl_merge_conf(ngx_conf_t *cf, return NGX_CONF_ERROR; } + if (ngx_ssl_conf_commands(cf, &conf->ssl, conf->conf_commands) != NGX_OK) { + return NGX_CONF_ERROR; + } + return NGX_CONF_OK; } @@ -654,3 +675,14 @@ invalid: return NGX_CONF_ERROR; } + + +static char * +ngx_mail_ssl_conf_command_check(ngx_conf_t *cf, void *post, void *data) +{ +#ifndef SSL_CONF_FLAG_FILE + return "is not supported on this platform"; +#endif + + return NGX_CONF_OK; +} diff -r 485dba3e2a01 -r 3bff3f397c05 src/mail/ngx_mail_ssl_module.h --- a/src/mail/ngx_mail_ssl_module.h Thu Oct 22 18:00:20 2020 +0300 +++ b/src/mail/ngx_mail_ssl_module.h Thu Oct 22 18:00:22 2020 +0300 @@ -48,6 +48,7 @@ typedef struct { ngx_str_t ciphers; ngx_array_t *passwords; + ngx_array_t *conf_commands; ngx_shm_zone_t *shm_zone; diff -r 485dba3e2a01 -r 3bff3f397c05 src/stream/ngx_stream_ssl_module.c --- a/src/stream/ngx_stream_ssl_module.c Thu Oct 22 18:00:20 2020 +0300 +++ b/src/stream/ngx_stream_ssl_module.c Thu Oct 22 18:00:22 2020 +0300 @@ -45,6 +45,10 @@ static char *ngx_stream_ssl_password_fil void *conf); static char *ngx_stream_ssl_session_cache(ngx_conf_t *cf, ngx_command_t *cmd, void *conf); + +static char *ngx_stream_ssl_conf_command_check(ngx_conf_t *cf, void *post, + void *data); + static ngx_int_t ngx_stream_ssl_init(ngx_conf_t *cf); @@ -68,6 +72,10 @@ static ngx_conf_enum_t ngx_stream_ssl_v }; +static ngx_conf_post_t ngx_stream_ssl_conf_command_post = + { ngx_stream_ssl_conf_command_check }; + + static ngx_command_t ngx_stream_ssl_commands[] = { { ngx_string("ssl_handshake_timeout"), @@ -196,6 +204,13 @@ static ngx_command_t ngx_stream_ssl_com offsetof(ngx_stream_ssl_conf_t, crl), NULL }, + { ngx_string("ssl_conf_command"), + NGX_STREAM_MAIN_CONF|NGX_STREAM_SRV_CONF|NGX_CONF_TAKE2, + ngx_conf_set_keyval_slot, + NGX_STREAM_SRV_CONF_OFFSET, + offsetof(ngx_stream_ssl_conf_t, conf_commands), + &ngx_stream_ssl_conf_command_post }, + ngx_null_command }; @@ -595,6 +610,7 @@ ngx_stream_ssl_create_conf(ngx_conf_t *c scf->certificates = NGX_CONF_UNSET_PTR; scf->certificate_keys = NGX_CONF_UNSET_PTR; scf->passwords = NGX_CONF_UNSET_PTR; + scf->conf_commands = NGX_CONF_UNSET_PTR; scf->prefer_server_ciphers = NGX_CONF_UNSET; scf->verify = NGX_CONF_UNSET_UINT; scf->verify_depth = NGX_CONF_UNSET_UINT; @@ -650,6 +666,8 @@ ngx_stream_ssl_merge_conf(ngx_conf_t *cf ngx_conf_merge_str_value(conf->ciphers, prev->ciphers, NGX_DEFAULT_CIPHERS); + ngx_conf_merge_ptr_value(conf->conf_commands, prev->conf_commands, NULL); + conf->ssl.log = cf->log; @@ -811,6 +829,10 @@ ngx_stream_ssl_merge_conf(ngx_conf_t *cf return NGX_CONF_ERROR; } + if (ngx_ssl_conf_commands(cf, &conf->ssl, conf->conf_commands) != NGX_OK) { + return NGX_CONF_ERROR; + } + return NGX_CONF_OK; } @@ -1034,6 +1056,17 @@ invalid: } +static char * +ngx_stream_ssl_conf_command_check(ngx_conf_t *cf, void *post, void *data) +{ +#ifndef SSL_CONF_FLAG_FILE + return "is not supported on this platform"; +#endif + + return NGX_CONF_OK; +} + + static ngx_int_t ngx_stream_ssl_init(ngx_conf_t *cf) { diff -r 485dba3e2a01 -r 3bff3f397c05 src/stream/ngx_stream_ssl_module.h --- a/src/stream/ngx_stream_ssl_module.h Thu Oct 22 18:00:20 2020 +0300 +++ b/src/stream/ngx_stream_ssl_module.h Thu Oct 22 18:00:22 2020 +0300 @@ -46,6 +46,7 @@ typedef struct { ngx_str_t ciphers; ngx_array_t *passwords; + ngx_array_t *conf_commands; ngx_shm_zone_t *shm_zone; From mdounin at mdounin.ru Thu Oct 22 15:02:10 2020 From: mdounin at mdounin.ru (Maxim Dounin) Date: Thu, 22 Oct 2020 15:02:10 +0000 Subject: [nginx] Upstream: proxy_ssl_conf_command and friends. Message-ID: details: https://hg.nginx.org/nginx/rev/1a719ee45526 branches: changeset: 7730:1a719ee45526 user: Maxim Dounin date: Thu Oct 22 18:00:23 2020 +0300 description: Upstream: proxy_ssl_conf_command and friends. Similarly to ssl_conf_command, proxy_ssl_conf_command (grpc_ssl_conf_command, uwsgi_ssl_conf_command) can be used to set arbitrary OpenSSL configuration parameters as long as nginx is compiled with OpenSSL 1.0.2 or later, when connecting to upstream servers with SSL. Full list of available configuration commands can be found in the SSL_CONF_cmd manual page (https://www.openssl.org/docs/man1.1.1/man3/SSL_CONF_cmd.html). diffstat: src/http/modules/ngx_http_grpc_module.c | 34 ++++++++++++++++++++++++++++++ src/http/modules/ngx_http_proxy_module.c | 36 ++++++++++++++++++++++++++++++++ src/http/modules/ngx_http_uwsgi_module.c | 34 ++++++++++++++++++++++++++++++ 3 files changed, 104 insertions(+), 0 deletions(-) diffs (281 lines): diff -r 3bff3f397c05 -r 1a719ee45526 src/http/modules/ngx_http_grpc_module.c --- a/src/http/modules/ngx_http_grpc_module.c Thu Oct 22 18:00:22 2020 +0300 +++ b/src/http/modules/ngx_http_grpc_module.c Thu Oct 22 18:00:23 2020 +0300 @@ -40,6 +40,7 @@ typedef struct { ngx_str_t ssl_certificate; ngx_str_t ssl_certificate_key; ngx_array_t *ssl_passwords; + ngx_array_t *ssl_conf_commands; #endif } ngx_http_grpc_loc_conf_t; @@ -208,6 +209,8 @@ static char *ngx_http_grpc_pass(ngx_conf #if (NGX_HTTP_SSL) static char *ngx_http_grpc_ssl_password_file(ngx_conf_t *cf, ngx_command_t *cmd, void *conf); +static char *ngx_http_grpc_ssl_conf_command_check(ngx_conf_t *cf, void *post, + void *data); static ngx_int_t ngx_http_grpc_set_ssl(ngx_conf_t *cf, ngx_http_grpc_loc_conf_t *glcf); #endif @@ -242,6 +245,9 @@ static ngx_conf_bitmask_t ngx_http_grpc { ngx_null_string, 0 } }; +static ngx_conf_post_t ngx_http_grpc_ssl_conf_command_post = + { ngx_http_grpc_ssl_conf_command_check }; + #endif @@ -438,6 +444,13 @@ static ngx_command_t ngx_http_grpc_comm 0, NULL }, + { ngx_string("grpc_ssl_conf_command"), + NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE2, + ngx_conf_set_keyval_slot, + NGX_HTTP_LOC_CONF_OFFSET, + offsetof(ngx_http_grpc_loc_conf_t, ssl_conf_commands), + &ngx_http_grpc_ssl_conf_command_post }, + #endif ngx_null_command @@ -4359,6 +4372,7 @@ ngx_http_grpc_create_loc_conf(ngx_conf_t conf->upstream.ssl_verify = NGX_CONF_UNSET; conf->ssl_verify_depth = NGX_CONF_UNSET_UINT; conf->ssl_passwords = NGX_CONF_UNSET_PTR; + conf->ssl_conf_commands = NGX_CONF_UNSET_PTR; #endif /* the hardcoded values */ @@ -4469,6 +4483,9 @@ ngx_http_grpc_merge_loc_conf(ngx_conf_t prev->ssl_certificate_key, ""); ngx_conf_merge_ptr_value(conf->ssl_passwords, prev->ssl_passwords, NULL); + ngx_conf_merge_ptr_value(conf->ssl_conf_commands, + prev->ssl_conf_commands, NULL); + if (conf->ssl && ngx_http_grpc_set_ssl(cf, conf) != NGX_OK) { return NGX_CONF_ERROR; } @@ -4836,6 +4853,17 @@ ngx_http_grpc_ssl_password_file(ngx_conf } +static char * +ngx_http_grpc_ssl_conf_command_check(ngx_conf_t *cf, void *post, void *data) +{ +#ifndef SSL_CONF_FLAG_FILE + return "is not supported on this platform"; +#endif + + return NGX_CONF_OK; +} + + static ngx_int_t ngx_http_grpc_set_ssl(ngx_conf_t *cf, ngx_http_grpc_loc_conf_t *glcf) { @@ -4926,6 +4954,12 @@ ngx_http_grpc_set_ssl(ngx_conf_t *cf, ng #endif + if (ngx_ssl_conf_commands(cf, glcf->upstream.ssl, glcf->ssl_conf_commands) + != NGX_OK) + { + return NGX_ERROR; + } + return NGX_OK; } diff -r 3bff3f397c05 -r 1a719ee45526 src/http/modules/ngx_http_proxy_module.c --- a/src/http/modules/ngx_http_proxy_module.c Thu Oct 22 18:00:22 2020 +0300 +++ b/src/http/modules/ngx_http_proxy_module.c Thu Oct 22 18:00:23 2020 +0300 @@ -127,6 +127,7 @@ typedef struct { ngx_str_t ssl_certificate; ngx_str_t ssl_certificate_key; ngx_array_t *ssl_passwords; + ngx_array_t *ssl_conf_commands; #endif } ngx_http_proxy_loc_conf_t; @@ -229,6 +230,10 @@ static char *ngx_http_proxy_ssl_password #endif static char *ngx_http_proxy_lowat_check(ngx_conf_t *cf, void *post, void *data); +#if (NGX_HTTP_SSL) +static char *ngx_http_proxy_ssl_conf_command_check(ngx_conf_t *cf, void *post, + void *data); +#endif static ngx_int_t ngx_http_proxy_rewrite_regex(ngx_conf_t *cf, ngx_http_proxy_rewrite_t *pr, ngx_str_t *regex, ngx_uint_t caseless); @@ -274,6 +279,9 @@ static ngx_conf_bitmask_t ngx_http_prox { ngx_null_string, 0 } }; +static ngx_conf_post_t ngx_http_proxy_ssl_conf_command_post = + { ngx_http_proxy_ssl_conf_command_check }; + #endif @@ -764,6 +772,13 @@ static ngx_command_t ngx_http_proxy_com 0, NULL }, + { ngx_string("proxy_ssl_conf_command"), + NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE2, + ngx_conf_set_keyval_slot, + NGX_HTTP_LOC_CONF_OFFSET, + offsetof(ngx_http_proxy_loc_conf_t, ssl_conf_commands), + &ngx_http_proxy_ssl_conf_command_post }, + #endif ngx_null_command @@ -3340,6 +3355,7 @@ ngx_http_proxy_create_loc_conf(ngx_conf_ conf->upstream.ssl_verify = NGX_CONF_UNSET; conf->ssl_verify_depth = NGX_CONF_UNSET_UINT; conf->ssl_passwords = NGX_CONF_UNSET_PTR; + conf->ssl_conf_commands = NGX_CONF_UNSET_PTR; #endif /* "proxy_cyclic_temp_file" is disabled */ @@ -3687,6 +3703,9 @@ ngx_http_proxy_merge_loc_conf(ngx_conf_t prev->ssl_certificate_key, ""); ngx_conf_merge_ptr_value(conf->ssl_passwords, prev->ssl_passwords, NULL); + ngx_conf_merge_ptr_value(conf->ssl_conf_commands, + prev->ssl_conf_commands, NULL); + if (conf->ssl && ngx_http_proxy_set_ssl(cf, conf) != NGX_OK) { return NGX_CONF_ERROR; } @@ -4845,6 +4864,17 @@ ngx_http_proxy_lowat_check(ngx_conf_t *c #if (NGX_HTTP_SSL) +static char * +ngx_http_proxy_ssl_conf_command_check(ngx_conf_t *cf, void *post, void *data) +{ +#ifndef SSL_CONF_FLAG_FILE + return "is not supported on this platform"; +#endif + + return NGX_CONF_OK; +} + + static ngx_int_t ngx_http_proxy_set_ssl(ngx_conf_t *cf, ngx_http_proxy_loc_conf_t *plcf) { @@ -4922,6 +4952,12 @@ ngx_http_proxy_set_ssl(ngx_conf_t *cf, n return NGX_ERROR; } + if (ngx_ssl_conf_commands(cf, plcf->upstream.ssl, plcf->ssl_conf_commands) + != NGX_OK) + { + return NGX_ERROR; + } + return NGX_OK; } diff -r 3bff3f397c05 -r 1a719ee45526 src/http/modules/ngx_http_uwsgi_module.c --- a/src/http/modules/ngx_http_uwsgi_module.c Thu Oct 22 18:00:22 2020 +0300 +++ b/src/http/modules/ngx_http_uwsgi_module.c Thu Oct 22 18:00:23 2020 +0300 @@ -57,6 +57,7 @@ typedef struct { ngx_str_t ssl_certificate; ngx_str_t ssl_certificate_key; ngx_array_t *ssl_passwords; + ngx_array_t *ssl_conf_commands; #endif } ngx_http_uwsgi_loc_conf_t; @@ -96,6 +97,8 @@ static char *ngx_http_uwsgi_cache_key(ng #if (NGX_HTTP_SSL) static char *ngx_http_uwsgi_ssl_password_file(ngx_conf_t *cf, ngx_command_t *cmd, void *conf); +static char *ngx_http_uwsgi_ssl_conf_command_check(ngx_conf_t *cf, void *post, + void *data); static ngx_int_t ngx_http_uwsgi_set_ssl(ngx_conf_t *cf, ngx_http_uwsgi_loc_conf_t *uwcf); #endif @@ -134,6 +137,9 @@ static ngx_conf_bitmask_t ngx_http_uwsg { ngx_null_string, 0 } }; +static ngx_conf_post_t ngx_http_uwsgi_ssl_conf_command_post = + { ngx_http_uwsgi_ssl_conf_command_check }; + #endif @@ -561,6 +567,13 @@ static ngx_command_t ngx_http_uwsgi_comm 0, NULL }, + { ngx_string("uwsgi_ssl_conf_command"), + NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE2, + ngx_conf_set_keyval_slot, + NGX_HTTP_LOC_CONF_OFFSET, + offsetof(ngx_http_uwsgi_loc_conf_t, ssl_conf_commands), + &ngx_http_uwsgi_ssl_conf_command_post }, + #endif ngx_null_command @@ -1500,6 +1513,7 @@ ngx_http_uwsgi_create_loc_conf(ngx_conf_ conf->upstream.ssl_verify = NGX_CONF_UNSET; conf->ssl_verify_depth = NGX_CONF_UNSET_UINT; conf->ssl_passwords = NGX_CONF_UNSET_PTR; + conf->ssl_conf_commands = NGX_CONF_UNSET_PTR; #endif /* "uwsgi_cyclic_temp_file" is disabled */ @@ -1830,6 +1844,9 @@ ngx_http_uwsgi_merge_loc_conf(ngx_conf_t prev->ssl_certificate_key, ""); ngx_conf_merge_ptr_value(conf->ssl_passwords, prev->ssl_passwords, NULL); + ngx_conf_merge_ptr_value(conf->ssl_conf_commands, + prev->ssl_conf_commands, NULL); + if (conf->ssl && ngx_http_uwsgi_set_ssl(cf, conf) != NGX_OK) { return NGX_CONF_ERROR; } @@ -2376,6 +2393,17 @@ ngx_http_uwsgi_ssl_password_file(ngx_con } +static char * +ngx_http_uwsgi_ssl_conf_command_check(ngx_conf_t *cf, void *post, void *data) +{ +#ifndef SSL_CONF_FLAG_FILE + return "is not supported on this platform"; +#endif + + return NGX_CONF_OK; +} + + static ngx_int_t ngx_http_uwsgi_set_ssl(ngx_conf_t *cf, ngx_http_uwsgi_loc_conf_t *uwcf) { @@ -2453,6 +2481,12 @@ ngx_http_uwsgi_set_ssl(ngx_conf_t *cf, n return NGX_ERROR; } + if (ngx_ssl_conf_commands(cf, uwcf->upstream.ssl, uwcf->ssl_conf_commands) + != NGX_OK) + { + return NGX_ERROR; + } + return NGX_OK; } From mdounin at mdounin.ru Thu Oct 22 15:02:14 2020 From: mdounin at mdounin.ru (Maxim Dounin) Date: Thu, 22 Oct 2020 15:02:14 +0000 Subject: [nginx] Stream: proxy_ssl_conf_command directive. Message-ID: details: https://hg.nginx.org/nginx/rev/fd0b2226919b branches: changeset: 7731:fd0b2226919b user: Maxim Dounin date: Thu Oct 22 18:00:27 2020 +0300 description: Stream: proxy_ssl_conf_command directive. Similarly to ssl_conf_command, proxy_ssl_conf_command can be used to set arbitrary OpenSSL configuration parameters as long as nginx is compiled with OpenSSL 1.0.2 or later, when connecting to upstream servers with SSL. Full list of available configuration commands can be found in the SSL_CONF_cmd manual page (https://www.openssl.org/docs/man1.1.1/man3/SSL_CONF_cmd.html). diffstat: src/stream/ngx_stream_proxy_module.c | 34 ++++++++++++++++++++++++++++++++++ 1 files changed, 34 insertions(+), 0 deletions(-) diffs (93 lines): diff -r 1a719ee45526 -r fd0b2226919b src/stream/ngx_stream_proxy_module.c --- a/src/stream/ngx_stream_proxy_module.c Thu Oct 22 18:00:23 2020 +0300 +++ b/src/stream/ngx_stream_proxy_module.c Thu Oct 22 18:00:27 2020 +0300 @@ -49,6 +49,7 @@ typedef struct { ngx_str_t ssl_certificate; ngx_str_t ssl_certificate_key; ngx_array_t *ssl_passwords; + ngx_array_t *ssl_conf_commands; ngx_ssl_t *ssl; #endif @@ -94,6 +95,8 @@ static char *ngx_stream_proxy_bind(ngx_c static ngx_int_t ngx_stream_proxy_send_proxy_protocol(ngx_stream_session_t *s); static char *ngx_stream_proxy_ssl_password_file(ngx_conf_t *cf, ngx_command_t *cmd, void *conf); +static char *ngx_stream_proxy_ssl_conf_command_check(ngx_conf_t *cf, void *post, + void *data); static void ngx_stream_proxy_ssl_init_connection(ngx_stream_session_t *s); static void ngx_stream_proxy_ssl_handshake(ngx_connection_t *pc); static void ngx_stream_proxy_ssl_save_session(ngx_connection_t *c); @@ -112,6 +115,9 @@ static ngx_conf_bitmask_t ngx_stream_pr { ngx_null_string, 0 } }; +static ngx_conf_post_t ngx_stream_proxy_ssl_conf_command_post = + { ngx_stream_proxy_ssl_conf_command_check }; + #endif @@ -331,6 +337,13 @@ static ngx_command_t ngx_stream_proxy_c 0, NULL }, + { ngx_string("proxy_ssl_conf_command"), + NGX_STREAM_MAIN_CONF|NGX_STREAM_SRV_CONF|NGX_CONF_TAKE2, + ngx_conf_set_keyval_slot, + NGX_STREAM_SRV_CONF_OFFSET, + offsetof(ngx_stream_proxy_srv_conf_t, ssl_conf_commands), + &ngx_stream_proxy_ssl_conf_command_post }, + #endif ngx_null_command @@ -1008,6 +1021,17 @@ ngx_stream_proxy_ssl_password_file(ngx_c } +static char * +ngx_stream_proxy_ssl_conf_command_check(ngx_conf_t *cf, void *post, void *data) +{ +#ifndef SSL_CONF_FLAG_FILE + return "is not supported on this platform"; +#endif + + return NGX_CONF_OK; +} + + static void ngx_stream_proxy_ssl_init_connection(ngx_stream_session_t *s) { @@ -1985,6 +2009,7 @@ ngx_stream_proxy_create_srv_conf(ngx_con conf->ssl_verify = NGX_CONF_UNSET; conf->ssl_verify_depth = NGX_CONF_UNSET_UINT; conf->ssl_passwords = NGX_CONF_UNSET_PTR; + conf->ssl_conf_commands = NGX_CONF_UNSET_PTR; #endif return conf; @@ -2072,6 +2097,9 @@ ngx_stream_proxy_merge_srv_conf(ngx_conf ngx_conf_merge_ptr_value(conf->ssl_passwords, prev->ssl_passwords, NULL); + ngx_conf_merge_ptr_value(conf->ssl_conf_commands, + prev->ssl_conf_commands, NULL); + if (conf->ssl_enable && ngx_stream_proxy_set_ssl(cf, conf) != NGX_OK) { return NGX_CONF_ERROR; } @@ -2156,6 +2184,12 @@ ngx_stream_proxy_set_ssl(ngx_conf_t *cf, return NGX_ERROR; } + if (ngx_ssl_conf_commands(cf, pscf->ssl, pscf->ssl_conf_commands) + != NGX_OK) + { + return NGX_ERROR; + } + return NGX_OK; } From mdounin at mdounin.ru Thu Oct 22 15:03:37 2020 From: mdounin at mdounin.ru (Maxim Dounin) Date: Thu, 22 Oct 2020 15:03:37 +0000 Subject: [nginx] SSL: ssl_reject_handshake directive (ticket #195). Message-ID: details: https://hg.nginx.org/nginx/rev/59e1c73fe02b branches: changeset: 7732:59e1c73fe02b user: Maxim Dounin date: Thu Oct 22 18:02:28 2020 +0300 description: SSL: ssl_reject_handshake directive (ticket #195). In some cases it might be needed to reject SSL handshake based on SNI server name provided, for example, to make sure an invalid certificate is not returned to clients trying to contact a name-based virtual server without SSL configured. Previously, a "ssl_ciphers aNULL;" was used for this. This workaround, however, is not compatible with TLSv1.3, in particular, when using BoringSSL, where it is not possible to configure TLSv1.3 ciphers at all. With this change, the ssl_reject_handshake directive is introduced, which instructs nginx to reject SSL handshakes with an "unrecognized_name" alert in a particular server block. For example, to reject handshake with names other than example.com, one can use the following configuration: server { listen 443 ssl; ssl_reject_handshake on; } server { listen 443 ssl; server_name example.com; ssl_certificate example.com.crt; ssl_certificate_key example.com.key; } The following configuration can be used to reject all SSL handshakes without SNI server name provided: server { listen 443 ssl; ssl_reject_handshake on; } server { listen 443 ssl; server_name ~^; ssl_certificate example.crt; ssl_certificate_key example.key; } Additionally, the ssl_reject_handshake directive makes configuring certificates for the default server block optional. If no certificates are configured in the default server for a given listening socket, certificates must be defined in all non-default server blocks with the listening socket in question. diffstat: src/event/ngx_event_openssl.c | 12 +++- src/event/ngx_event_openssl.h | 1 + src/http/modules/ngx_http_ssl_module.c | 93 ++++++++++++++++++++++++--------- src/http/modules/ngx_http_ssl_module.h | 1 + src/http/ngx_http_request.c | 41 +++++++++----- 5 files changed, 105 insertions(+), 43 deletions(-) diffs (309 lines): diff -r fd0b2226919b -r 59e1c73fe02b src/event/ngx_event_openssl.c --- a/src/event/ngx_event_openssl.c Thu Oct 22 18:00:27 2020 +0300 +++ b/src/event/ngx_event_openssl.c Thu Oct 22 18:02:28 2020 +0300 @@ -1793,6 +1793,13 @@ ngx_ssl_handshake(ngx_connection_t *c) return NGX_ERROR; } + if (c->ssl->handshake_rejected) { + ngx_connection_error(c, err, "handshake rejected"); + ERR_clear_error(); + + return NGX_ERROR; + } + c->read->error = 1; ngx_ssl_connection_error(c, sslerr, err, "SSL_do_handshake() failed"); @@ -3354,8 +3361,9 @@ ngx_ssl_session_id_context(ngx_ssl_t *ss } } - if (SSL_CTX_get_ex_data(ssl->ctx, ngx_ssl_certificate_index) == NULL) { - + if (SSL_CTX_get_ex_data(ssl->ctx, ngx_ssl_certificate_index) == NULL + && certificates != NULL) + { /* * If certificates are loaded dynamically, we use certificate * names as specified in the configuration (with variables). diff -r fd0b2226919b -r 59e1c73fe02b src/event/ngx_event_openssl.h --- a/src/event/ngx_event_openssl.h Thu Oct 22 18:00:27 2020 +0300 +++ b/src/event/ngx_event_openssl.h Thu Oct 22 18:02:28 2020 +0300 @@ -95,6 +95,7 @@ struct ngx_ssl_connection_s { u_char early_buf; unsigned handshaked:1; + unsigned handshake_rejected:1; unsigned renegotiation:1; unsigned buffer:1; unsigned no_wait_shutdown:1; diff -r fd0b2226919b -r 59e1c73fe02b src/http/modules/ngx_http_ssl_module.c --- a/src/http/modules/ngx_http_ssl_module.c Thu Oct 22 18:00:27 2020 +0300 +++ b/src/http/modules/ngx_http_ssl_module.c Thu Oct 22 18:02:28 2020 +0300 @@ -294,6 +294,13 @@ static ngx_command_t ngx_http_ssl_comma offsetof(ngx_http_ssl_srv_conf_t, conf_commands), &ngx_http_ssl_conf_command_post }, + { ngx_string("ssl_reject_handshake"), + NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_CONF_FLAG, + ngx_conf_set_flag_slot, + NGX_HTTP_SRV_CONF_OFFSET, + offsetof(ngx_http_ssl_srv_conf_t, reject_handshake), + NULL }, + ngx_null_command }; @@ -614,6 +621,7 @@ ngx_http_ssl_create_srv_conf(ngx_conf_t sscf->enable = NGX_CONF_UNSET; sscf->prefer_server_ciphers = NGX_CONF_UNSET; sscf->early_data = NGX_CONF_UNSET; + sscf->reject_handshake = NGX_CONF_UNSET; sscf->buffer_size = NGX_CONF_UNSET_SIZE; sscf->verify = NGX_CONF_UNSET_UINT; sscf->verify_depth = NGX_CONF_UNSET_UINT; @@ -660,6 +668,7 @@ ngx_http_ssl_merge_srv_conf(ngx_conf_t * prev->prefer_server_ciphers, 0); ngx_conf_merge_value(conf->early_data, prev->early_data, 0); + ngx_conf_merge_value(conf->reject_handshake, prev->reject_handshake, 0); ngx_conf_merge_bitmask_value(conf->protocols, prev->protocols, (NGX_CONF_BITMASK_SET|NGX_SSL_TLSv1 @@ -707,7 +716,27 @@ ngx_http_ssl_merge_srv_conf(ngx_conf_t * if (conf->enable) { - if (conf->certificates == NULL) { + if (conf->certificates) { + if (conf->certificate_keys == NULL) { + ngx_log_error(NGX_LOG_EMERG, cf->log, 0, + "no \"ssl_certificate_key\" is defined for " + "the \"ssl\" directive in %s:%ui", + conf->file, conf->line); + return NGX_CONF_ERROR; + } + + if (conf->certificate_keys->nelts < conf->certificates->nelts) { + ngx_log_error(NGX_LOG_EMERG, cf->log, 0, + "no \"ssl_certificate_key\" is defined " + "for certificate \"%V\" and " + "the \"ssl\" directive in %s:%ui", + ((ngx_str_t *) conf->certificates->elts) + + conf->certificates->nelts - 1, + conf->file, conf->line); + return NGX_CONF_ERROR; + } + + } else if (!conf->reject_handshake) { ngx_log_error(NGX_LOG_EMERG, cf->log, 0, "no \"ssl_certificate\" is defined for " "the \"ssl\" directive in %s:%ui", @@ -715,30 +744,7 @@ ngx_http_ssl_merge_srv_conf(ngx_conf_t * return NGX_CONF_ERROR; } - if (conf->certificate_keys == NULL) { - ngx_log_error(NGX_LOG_EMERG, cf->log, 0, - "no \"ssl_certificate_key\" is defined for " - "the \"ssl\" directive in %s:%ui", - conf->file, conf->line); - return NGX_CONF_ERROR; - } - - if (conf->certificate_keys->nelts < conf->certificates->nelts) { - ngx_log_error(NGX_LOG_EMERG, cf->log, 0, - "no \"ssl_certificate_key\" is defined " - "for certificate \"%V\" and " - "the \"ssl\" directive in %s:%ui", - ((ngx_str_t *) conf->certificates->elts) - + conf->certificates->nelts - 1, - conf->file, conf->line); - return NGX_CONF_ERROR; - } - - } else { - - if (conf->certificates == NULL) { - return NGX_CONF_OK; - } + } else if (conf->certificates) { if (conf->certificate_keys == NULL || conf->certificate_keys->nelts < conf->certificates->nelts) @@ -750,6 +756,9 @@ ngx_http_ssl_merge_srv_conf(ngx_conf_t * + conf->certificates->nelts - 1); return NGX_CONF_ERROR; } + + } else if (!conf->reject_handshake) { + return NGX_CONF_OK; } if (ngx_ssl_create(&conf->ssl, conf->protocols, conf) != NGX_OK) { @@ -808,7 +817,7 @@ ngx_http_ssl_merge_srv_conf(ngx_conf_t * return NGX_CONF_ERROR; #endif - } else { + } else if (conf->certificates) { /* configure certificates */ @@ -947,6 +956,10 @@ ngx_http_ssl_compile_certificates(ngx_co ngx_http_complex_value_t *cv; ngx_http_compile_complex_value_t ccv; + if (conf->certificates == NULL) { + return NGX_OK; + } + cert = conf->certificates->elts; key = conf->certificate_keys->elts; nelts = conf->certificates->nelts; @@ -1327,7 +1340,33 @@ ngx_http_ssl_init(ngx_conf_t *cf) cscf = addr[a].default_server; sscf = cscf->ctx->srv_conf[ngx_http_ssl_module.ctx_index]; - if (sscf->certificates == NULL) { + if (sscf->certificates) { + continue; + } + + if (!sscf->reject_handshake) { + ngx_log_error(NGX_LOG_EMERG, cf->log, 0, + "no \"ssl_certificate\" is defined for " + "the \"listen ... ssl\" directive in %s:%ui", + cscf->file_name, cscf->line); + return NGX_ERROR; + } + + /* + * if no certificates are defined in the default server, + * check all non-default server blocks + */ + + cscfp = addr[a].servers.elts; + for (s = 0; s < addr[a].servers.nelts; s++) { + + cscf = cscfp[s]; + sscf = cscf->ctx->srv_conf[ngx_http_ssl_module.ctx_index]; + + if (sscf->certificates || sscf->reject_handshake) { + continue; + } + ngx_log_error(NGX_LOG_EMERG, cf->log, 0, "no \"ssl_certificate\" is defined for " "the \"listen ... ssl\" directive in %s:%ui", diff -r fd0b2226919b -r 59e1c73fe02b src/http/modules/ngx_http_ssl_module.h --- a/src/http/modules/ngx_http_ssl_module.h Thu Oct 22 18:00:27 2020 +0300 +++ b/src/http/modules/ngx_http_ssl_module.h Thu Oct 22 18:02:28 2020 +0300 @@ -21,6 +21,7 @@ typedef struct { ngx_flag_t prefer_server_ciphers; ngx_flag_t early_data; + ngx_flag_t reject_handshake; ngx_uint_t protocols; diff -r fd0b2226919b -r 59e1c73fe02b src/http/ngx_http_request.c --- a/src/http/ngx_http_request.c Thu Oct 22 18:00:27 2020 +0300 +++ b/src/http/ngx_http_request.c Thu Oct 22 18:02:28 2020 +0300 @@ -871,10 +871,14 @@ ngx_http_ssl_servername(ngx_ssl_conn_t * return SSL_TLSEXT_ERR_ALERT_FATAL; } + hc = c->data; + servername = SSL_get_servername(ssl_conn, TLSEXT_NAMETYPE_host_name); if (servername == NULL) { - return SSL_TLSEXT_ERR_OK; + ngx_log_debug0(NGX_LOG_DEBUG_HTTP, c->log, 0, + "SSL server name: null"); + goto done; } ngx_log_debug1(NGX_LOG_DEBUG_HTTP, c->log, 0, @@ -883,7 +887,7 @@ ngx_http_ssl_servername(ngx_ssl_conn_t * host.len = ngx_strlen(servername); if (host.len == 0) { - return SSL_TLSEXT_ERR_OK; + goto done; } host.data = (u_char *) servername; @@ -891,32 +895,27 @@ ngx_http_ssl_servername(ngx_ssl_conn_t * rc = ngx_http_validate_host(&host, c->pool, 1); if (rc == NGX_ERROR) { - *ad = SSL_AD_INTERNAL_ERROR; - return SSL_TLSEXT_ERR_ALERT_FATAL; + goto error; } if (rc == NGX_DECLINED) { - return SSL_TLSEXT_ERR_OK; + goto done; } - hc = c->data; - rc = ngx_http_find_virtual_server(c, hc->addr_conf->virtual_names, &host, NULL, &cscf); if (rc == NGX_ERROR) { - *ad = SSL_AD_INTERNAL_ERROR; - return SSL_TLSEXT_ERR_ALERT_FATAL; + goto error; } if (rc == NGX_DECLINED) { - return SSL_TLSEXT_ERR_OK; + goto done; } hc->ssl_servername = ngx_palloc(c->pool, sizeof(ngx_str_t)); if (hc->ssl_servername == NULL) { - *ad = SSL_AD_INTERNAL_ERROR; - return SSL_TLSEXT_ERR_ALERT_FATAL; + goto error; } *hc->ssl_servername = host; @@ -933,8 +932,7 @@ ngx_http_ssl_servername(ngx_ssl_conn_t * if (sscf->ssl.ctx) { if (SSL_set_SSL_CTX(ssl_conn, sscf->ssl.ctx) == NULL) { - *ad = SSL_AD_INTERNAL_ERROR; - return SSL_TLSEXT_ERR_ALERT_FATAL; + goto error; } /* @@ -960,7 +958,22 @@ ngx_http_ssl_servername(ngx_ssl_conn_t * #endif } +done: + + sscf = ngx_http_get_module_srv_conf(hc->conf_ctx, ngx_http_ssl_module); + + if (sscf->reject_handshake) { + c->ssl->handshake_rejected = 1; + *ad = SSL_AD_UNRECOGNIZED_NAME; + return SSL_TLSEXT_ERR_ALERT_FATAL; + } + return SSL_TLSEXT_ERR_OK; + +error: + + *ad = SSL_AD_INTERNAL_ERROR; + return SSL_TLSEXT_ERR_ALERT_FATAL; } #endif From eran.kornblau at kaltura.com Mon Oct 26 12:20:52 2020 From: eran.kornblau at kaltura.com (Eran Kornblau) Date: Mon, 26 Oct 2020 12:20:52 +0000 Subject: ngx_str_rbtree_lookup gets uint32 hash Message-ID: Some pitfall I stepped on a couple of times, so thought I'd share here - ngx_str_rbtree_lookup currently uses uint32_t for the hash param, however ngx_rbtree_key_t is ngx_uint_t. This means that if someone calculates a hash that is potentially int64 (e.g. using ngx_hash_key/_lc), the nodes will not be found when looking them up the rbtree. Even though it doesn't matter for nginx core (all places that reference this function in core use crc32 for the hash...) IMHO it would be good to change the function signature to use ngx_uint_t or ngx_rbtree_key_t. Such a change is not expected to cause any backward compatibility issue for modules that depend on this function. Makes sense? Thanks Eran -------------- next part -------------- An HTML attachment was scrubbed... URL: From mdounin at mdounin.ru Tue Oct 27 15:13:28 2020 From: mdounin at mdounin.ru (Maxim Dounin) Date: Tue, 27 Oct 2020 15:13:28 +0000 Subject: [nginx] nginx-1.19.4-RELEASE Message-ID: details: https://hg.nginx.org/nginx/rev/dc0cc425fa63 branches: changeset: 7733:dc0cc425fa63 user: Maxim Dounin date: Tue Oct 27 18:09:20 2020 +0300 description: nginx-1.19.4-RELEASE diffstat: docs/xml/nginx/changes.xml | 34 ++++++++++++++++++++++++++++++++++ 1 files changed, 34 insertions(+), 0 deletions(-) diffs (44 lines): diff -r 59e1c73fe02b -r dc0cc425fa63 docs/xml/nginx/changes.xml --- a/docs/xml/nginx/changes.xml Thu Oct 22 18:02:28 2020 +0300 +++ b/docs/xml/nginx/changes.xml Tue Oct 27 18:09:20 2020 +0300 @@ -5,6 +5,40 @@ + + + + +????????? ssl_conf_command, proxy_ssl_conf_command, grpc_ssl_conf_command +? uwsgi_ssl_conf_command. + + +the "ssl_conf_command", "proxy_ssl_conf_command", "grpc_ssl_conf_command", +and "uwsgi_ssl_conf_command" directives. + + + + + +????????? ssl_reject_handshake. + + +the "ssl_reject_handshake" directive. + + + + + +????????? proxy_smtp_auth ? ???????? ??????-???????. + + +the "proxy_smtp_auth" directive in mail proxy. + + + + + + From mdounin at mdounin.ru Tue Oct 27 15:13:31 2020 From: mdounin at mdounin.ru (Maxim Dounin) Date: Tue, 27 Oct 2020 15:13:31 +0000 Subject: [nginx] release-1.19.4 tag Message-ID: details: https://hg.nginx.org/nginx/rev/df41a6b6c2aa branches: changeset: 7734:df41a6b6c2aa user: Maxim Dounin date: Tue Oct 27 18:09:20 2020 +0300 description: release-1.19.4 tag diffstat: .hgtags | 1 + 1 files changed, 1 insertions(+), 0 deletions(-) diffs (8 lines): diff -r dc0cc425fa63 -r df41a6b6c2aa .hgtags --- a/.hgtags Tue Oct 27 18:09:20 2020 +0300 +++ b/.hgtags Tue Oct 27 18:09:20 2020 +0300 @@ -453,3 +453,4 @@ cbe6ba650211541310618849168631ce0b788f35 062920e2f3bf871ef7a3d8496edec1b3065faf80 release-1.19.1 a7b46539f507e6c64efa0efda69ad60b6f4ffbce release-1.19.2 3cbc2602325f0ac08917a4397d76f5155c34b7b1 release-1.19.3 +dc0cc425fa63a80315f6efb68697cadb6626cdf2 release-1.19.4 From xeioex at nginx.com Thu Oct 29 12:59:56 2020 From: xeioex at nginx.com (Dmitry Volyntsev) Date: Thu, 29 Oct 2020 12:59:56 +0000 Subject: [njs] Configure: generating $NJS_LIB_OBJS using sed. Message-ID: details: https://hg.nginx.org/njs/rev/19d2a8d68e3a branches: changeset: 1547:19d2a8d68e3a user: Dmitry Volyntsev date: Thu Oct 29 12:46:19 2020 +0000 description: Configure: generating $NJS_LIB_OBJS using sed. diffstat: auto/init | 36 ++++++++++++++++++++++++++++++++++++ auto/make | 36 ++++-------------------------------- configure | 32 +------------------------------- 3 files changed, 41 insertions(+), 63 deletions(-) diffs (146 lines): diff -r 3d8f6b9548c0 -r 19d2a8d68e3a auto/init --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/auto/init Thu Oct 29 12:46:19 2020 +0000 @@ -0,0 +1,36 @@ + +# Copyright (C) Dmitry Volyntsev +# Copyright (C) NGINX, Inc. + +# Initialize variables with null values if they are not defined. +CFLAGS=${CFLAGS=} +NJS_TEST_CFLAGS=${NJS_TEST_CFLAGS=} +NJS_TEST_LIBS=${NJS_TEST_LIBS=} + + +# Initialize variables with default if they are not defined. +CC=${CC:-cc} +AR=${AR:-ar} +NJS_CFLAGS=${NJS_CFLAGS=} + +NJS_BUILD_DIR=${NJS_BUILD_DIR:-build} + +NJS_AUTOTEST=$NJS_BUILD_DIR/autotest +NJS_AUTOCONF_ERR=$NJS_BUILD_DIR/autoconf.err +NJS_AUTO_CONFIG_H=$NJS_BUILD_DIR/njs_auto_config.h +NJS_MAKEFILE=$NJS_BUILD_DIR/Makefile + +test -d $NJS_BUILD_DIR || mkdir $NJS_BUILD_DIR + +> $NJS_AUTOCONF_ERR + +cat << END > $NJS_AUTO_CONFIG_H + +/* This file is auto-generated by configure */ + +END + +NJS_LIBRT= + +njs_regex_cont=' \\\ + ' diff -r 3d8f6b9548c0 -r 19d2a8d68e3a auto/make --- a/auto/make Mon Oct 19 21:42:01 2020 +0200 +++ b/auto/make Thu Oct 29 12:46:19 2020 +0000 @@ -9,6 +9,8 @@ echo "creating $NJS_MAKEFILE" mkdir -p $NJS_BUILD_DIR/src mkdir -p $NJS_BUILD_DIR/test +njs_objs=`echo $NJS_LIB_SRCS \ + | sed -e "s# *\([^ ]*\.\)c#$NJS_BUILD_DIR/\1o$njs_regex_cont#g"` cat << END > $NJS_MAKEFILE @@ -20,38 +22,10 @@ NJS_LINK = ${CC} ${NJS_LD_OPT} NJS_CFLAGS = ${NJS_CFLAGS} ${NJS_CC_OPT} ${CFLAGS} default: $NJS_DEFAULT_TARGET -END - - -# The include paths list. - -printf "NJS_LIB_INCS =" >> $NJS_MAKEFILE - -for njs_inc in src $NJS_BUILD_DIR -do - printf " -I$njs_inc" >> $NJS_MAKEFILE -done - -echo >> $NJS_MAKEFILE -echo >> $NJS_MAKEFILE - -# The njs object files list. - -echo "NJS_LIB_OBJS = \\" >> $NJS_MAKEFILE +NJS_LIB_INCS = -Isrc -I$NJS_BUILD_DIR -for njs_src in $NJS_LIB_SRCS -do - fname=$(basename $njs_src) - njs_obj="src/${fname%.c}.o" - echo " $NJS_BUILD_DIR/$njs_obj \\" >> $NJS_MAKEFILE -done - -echo >> $NJS_MAKEFILE - -# The njs static library. - -cat << END >> $NJS_MAKEFILE +NJS_LIB_OBJS = $njs_objs libnjs: $NJS_BUILD_DIR/libnjs.a @@ -61,10 +35,8 @@ libnjs: $NJS_BUILD_DIR/libnjs.a \$(NJS_STATIC_LINK) $NJS_BUILD_DIR/libnjs.a \\ \$(NJS_LIB_OBJS) - END - # object files. for njs_src in $NJS_LIB_SRCS diff -r 3d8f6b9548c0 -r 19d2a8d68e3a configure --- a/configure Mon Oct 19 21:42:01 2020 +0200 +++ b/configure Thu Oct 29 12:46:19 2020 +0000 @@ -13,37 +13,7 @@ set -e # Stop on uninitialized variable. set -u - -# Initialize variables with null values if they are not defined. -CFLAGS=${CFLAGS=} -NJS_TEST_CFLAGS=${NJS_TEST_CFLAGS=} -NJS_TEST_LIBS=${NJS_TEST_LIBS=} - - -# Initialize variables with default if they are not defined. -CC=${CC:-cc} -AR=${AR:-ar} -NJS_CFLAGS=${NJS_CFLAGS=} - -NJS_BUILD_DIR=${NJS_BUILD_DIR:-build} - -NJS_AUTOTEST=$NJS_BUILD_DIR/autotest -NJS_AUTOCONF_ERR=$NJS_BUILD_DIR/autoconf.err -NJS_AUTO_CONFIG_H=$NJS_BUILD_DIR/njs_auto_config.h -NJS_MAKEFILE=$NJS_BUILD_DIR/Makefile - -test -d $NJS_BUILD_DIR || mkdir $NJS_BUILD_DIR - -> $NJS_AUTOCONF_ERR - -cat << END > $NJS_AUTO_CONFIG_H - -/* This file is auto-generated by configure */ - -END - -NJS_LIBRT= - +. auto/init . auto/os . auto/options . auto/cc From xeioex at nginx.com Thu Oct 29 12:59:58 2020 From: xeioex at nginx.com (Dmitry Volyntsev) Date: Thu, 29 Oct 2020 12:59:58 +0000 Subject: [njs] Configure: refactored NJS_VER. Message-ID: details: https://hg.nginx.org/njs/rev/ff14a0253f15 branches: changeset: 1548:ff14a0253f15 user: Jakub Jirutka date: Thu Oct 22 01:51:31 2020 +0200 description: Configure: refactored NJS_VER. diffstat: auto/make | 11 ++++++----- 1 files changed, 6 insertions(+), 5 deletions(-) diffs (29 lines): diff -r 19d2a8d68e3a -r ff14a0253f15 auto/make --- a/auto/make Thu Oct 29 12:46:19 2020 +0000 +++ b/auto/make Thu Oct 22 01:51:31 2020 +0200 @@ -21,6 +21,8 @@ NJS_STATIC_LINK = ${AR} -r -c NJS_LINK = ${CC} ${NJS_LD_OPT} NJS_CFLAGS = ${NJS_CFLAGS} ${NJS_CC_OPT} ${CFLAGS} +NJS_VER = $(grep NJS_VERSION src/njs.h | sed -e 's/.*"\(.*\)".*/\1/') + default: $NJS_DEFAULT_TARGET NJS_LIB_INCS = -Isrc -I$NJS_BUILD_DIR @@ -241,12 +243,11 @@ ts_test: ts tsc ./test/ts/test.ts dist: - NJS_VER=`grep NJS_VERSION src/njs.h | sed -e 's/.*"\(.*\)".*/\1/'`; \\ - rm -rf njs-\$\${NJS_VER} \\ - && hg archive njs-\$\${NJS_VER}.tar.gz \\ - -p njs-\$\${NJS_VER} \\ + rm -rf njs-\$(NJS_VER) \\ + && hg archive njs-\$(NJS_VER).tar.gz \\ + -p njs-\$(NJS_VER) \\ -X ".hg*" \\ - && echo njs-\$\${NJS_VER}.tar.gz done + && echo njs-\$(NJS_VER).tar.gz done END From xeioex at nginx.com Thu Oct 29 13:00:00 2020 From: xeioex at nginx.com (Dmitry Volyntsev) Date: Thu, 29 Oct 2020 13:00:00 +0000 Subject: [njs] Introduced .hgignore. Message-ID: details: https://hg.nginx.org/njs/rev/3e0684a2e793 branches: changeset: 1549:3e0684a2e793 user: Jakub Jirutka date: Thu Oct 22 22:45:00 2020 +0200 description: Introduced .hgignore. diffstat: .gitignore | 4 ++++ .hgignore | 4 ++++ 2 files changed, 8 insertions(+), 0 deletions(-) diffs (16 lines): diff -r ff14a0253f15 -r 3e0684a2e793 .gitignore --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/.gitignore Thu Oct 22 22:45:00 2020 +0200 @@ -0,0 +1,4 @@ +node_modules/ +package-lock.json +/build/ +/Makefile diff -r ff14a0253f15 -r 3e0684a2e793 .hgignore --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/.hgignore Thu Oct 22 22:45:00 2020 +0200 @@ -0,0 +1,4 @@ +/node_modules/ +package-lock.json +^build/ +^Makefile$ From xeioex at nginx.com Thu Oct 29 13:00:03 2020 From: xeioex at nginx.com (Dmitry Volyntsev) Date: Thu, 29 Oct 2020 13:00:03 +0000 Subject: [njs] Types: moved all TS type descriptions to ts/ in the repo root. Message-ID: details: https://hg.nginx.org/njs/rev/1ddcc8b77dab branches: changeset: 1550:1ddcc8b77dab user: Jakub Jirutka date: Mon Oct 19 23:51:54 2020 +0200 description: Types: moved all TS type descriptions to ts/ in the repo root. diffstat: auto/make | 7 +- nginx/ts/ngx_http_js_module.d.ts | 367 ---------------------- nginx/ts/ngx_stream_js_module.d.ts | 148 --------- src/ts/crypto.d.ts | 76 ---- src/ts/fs.d.ts | 384 ----------------------- src/ts/njs_core.d.ts | 608 ------------------------------------- src/ts/njs_shell.d.ts | 9 - src/ts/querystring.d.ts | 101 ------ ts/ngx_http_js_module.d.ts | 367 ++++++++++++++++++++++ ts/ngx_stream_js_module.d.ts | 148 +++++++++ ts/njs_core.d.ts | 608 +++++++++++++++++++++++++++++++++++++ ts/njs_modules/crypto.d.ts | 76 ++++ ts/njs_modules/fs.d.ts | 384 +++++++++++++++++++++++ ts/njs_modules/querystring.d.ts | 101 ++++++ ts/njs_shell.d.ts | 9 + 15 files changed, 1697 insertions(+), 1696 deletions(-) diffs (truncated from 3460 to 1000 lines): diff -r 3e0684a2e793 -r 1ddcc8b77dab auto/make --- a/auto/make Thu Oct 22 22:45:00 2020 +0200 +++ b/auto/make Mon Oct 19 23:51:54 2020 +0200 @@ -234,10 +234,11 @@ benchmark: $NJS_BUILD_DIR/njs_auto_confi $NJS_BUILD_DIR/njs_benchmark +.PHONY: ts ts: - mkdir -p $NJS_BUILD_DIR/ts - cp nginx/ts/*.ts $NJS_BUILD_DIR/ts/ - cp src/ts/*.ts $NJS_BUILD_DIR/ts/ + mkdir -p $NJS_BUILD_DIR/ts/njs_modules + cp ts/*.d.ts $NJS_BUILD_DIR/ts/ + cp ts/njs_modules/* $NJS_BUILD_DIR/ts/njs_modules/ ts_test: ts tsc ./test/ts/test.ts diff -r 3e0684a2e793 -r 1ddcc8b77dab nginx/ts/ngx_http_js_module.d.ts --- a/nginx/ts/ngx_http_js_module.d.ts Thu Oct 22 22:45:00 2020 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,367 +0,0 @@ -/// - -interface NginxHTTPArgs { - readonly [prop: string]: NjsByteString; -} - -interface NginxHeadersIn { - // common request headers - readonly 'Accept'?: NjsByteString; - readonly 'Accept-Charset'?: NjsByteString; - readonly 'Accept-Encoding'?: NjsByteString; - readonly 'Accept-Language'?: NjsByteString; - readonly 'Authorization'?: NjsByteString; - readonly 'Cache-Control'?: NjsByteString; - readonly 'Connection'?: NjsByteString; - readonly 'Content-Length'?: NjsByteString; - readonly 'Content-Type'?: NjsByteString; - readonly 'Cookie'?: NjsByteString; - readonly 'Date'?: NjsByteString; - readonly 'Expect'?: NjsByteString; - readonly 'Forwarded'?: NjsByteString; - readonly 'From'?: NjsByteString; - readonly 'Host'?: NjsByteString; - readonly 'If-Match'?: NjsByteString; - readonly 'If-Modified-Since'?: NjsByteString; - readonly 'If-None-Match'?: NjsByteString; - readonly 'If-Range'?: NjsByteString; - readonly 'If-Unmodified-Since'?: NjsByteString; - readonly 'Max-Forwards'?: NjsByteString; - readonly 'Origin'?: NjsByteString; - readonly 'Pragma'?: NjsByteString; - readonly 'Proxy-Authorization'?: NjsByteString; - readonly 'Range'?: NjsByteString; - readonly 'Referer'?: NjsByteString; - readonly 'TE'?: NjsByteString; - readonly 'User-Agent'?: NjsByteString; - readonly 'Upgrade'?: NjsByteString; - readonly 'Via'?: NjsByteString; - readonly 'Warning'?: NjsByteString; - readonly 'X-Forwarded-For'?: NjsByteString; - - readonly [prop: string]: NjsByteString; -} - -interface NginxHeadersOut { - // common response headers - 'Age'?: NjsStringLike; - 'Allow'?: NjsStringLike; - 'Alt-Svc'?: NjsStringLike; - 'Cache-Control'?: NjsStringLike; - 'Connection'?: NjsStringLike; - 'Content-Disposition'?: NjsStringLike; - 'Content-Encoding'?: NjsStringLike; - 'Content-Language'?: NjsStringLike; - 'Content-Length'?: NjsStringLike; - 'Content-Location'?: NjsStringLike; - 'Content-Range'?: NjsStringLike; - 'Content-Type'?: NjsStringLike; - 'Date'?: NjsStringLike; - 'ETag'?: NjsStringLike; - 'Expires'?: NjsStringLike; - 'Last-Modified'?: NjsStringLike; - 'Link'?: NjsStringLike; - 'Location'?: NjsStringLike; - 'Pragma'?: NjsStringLike; - 'Proxy-Authenticate'?: NjsStringLike; - 'Retry-After'?: NjsStringLike; - 'Server'?: NjsStringLike; - 'Trailer'?: NjsStringLike; - 'Transfer-Encoding'?: NjsStringLike; - 'Upgrade'?: NjsStringLike; - 'Vary'?: NjsStringLike; - 'Via'?: NjsStringLike; - 'Warning'?: NjsStringLike; - 'WWW-Authenticate'?: NjsStringLike; - - 'Set-Cookie'?: NjsStringLike[]; - - [prop: string]: NjsStringLike | NjsStringLike[]; -} - -interface NginxVariables { - readonly 'ancient_browser'?: NjsByteString; - readonly 'arg_'?: NjsByteString; - readonly 'args'?: NjsByteString; - readonly 'binary_remote_addr'?: NjsByteString; - readonly 'body_bytes_sent'?: NjsByteString; - readonly 'bytes_received'?: NjsByteString; - readonly 'bytes_sent'?: NjsByteString; - readonly 'connection'?: NjsByteString; - readonly 'connection_requests'?: NjsByteString; - readonly 'connections_active'?: NjsByteString; - readonly 'connections_reading'?: NjsByteString; - readonly 'connections_waiting'?: NjsByteString; - readonly 'connections_writing'?: NjsByteString; - readonly 'content_length'?: NjsByteString; - readonly 'content_type'?: NjsByteString; - readonly 'cookie_'?: NjsByteString; - readonly 'date_gmt'?: NjsByteString; - readonly 'date_local'?: NjsByteString; - readonly 'document_root'?: NjsByteString; - readonly 'document_uri'?: NjsByteString; - readonly 'fastcgi_path_info'?: NjsByteString; - readonly 'fastcgi_script_name'?: NjsByteString; - readonly 'geoip_area_code'?: NjsByteString; - readonly 'geoip_city'?: NjsByteString; - readonly 'geoip_city_continent_code'?: NjsByteString; - readonly 'geoip_city_country_code'?: NjsByteString; - readonly 'geoip_city_country_code3'?: NjsByteString; - readonly 'geoip_city_country_name'?: NjsByteString; - readonly 'geoip_country_code'?: NjsByteString; - readonly 'geoip_country_code3'?: NjsByteString; - readonly 'geoip_country_name'?: NjsByteString; - readonly 'geoip_dma_code'?: NjsByteString; - readonly 'geoip_latitude'?: NjsByteString; - readonly 'geoip_longitude'?: NjsByteString; - readonly 'geoip_org'?: NjsByteString; - readonly 'geoip_postal_code'?: NjsByteString; - readonly 'geoip_region'?: NjsByteString; - readonly 'geoip_region_name'?: NjsByteString; - readonly 'gzip_ratio'?: NjsByteString; - readonly 'host'?: NjsByteString; - readonly 'hostname'?: NjsByteString; - readonly 'http2'?: NjsByteString; - readonly 'http_'?: NjsByteString; - readonly 'https'?: NjsByteString; - readonly 'invalid_referer'?: NjsByteString; - readonly 'is_args'?: NjsByteString; - readonly 'jwt_claim_'?: NjsByteString; - readonly 'jwt_header_'?: NjsByteString; - readonly 'limit_conn_status'?: NjsByteString; - readonly 'limit_rate'?: NjsByteString; - readonly 'limit_req_status'?: NjsByteString; - readonly 'memcached_key'?: NjsByteString; - readonly 'modern_browser'?: NjsByteString; - readonly 'msec'?: NjsByteString; - readonly 'msie'?: NjsByteString; - readonly 'nginx_version'?: NjsByteString; - readonly 'pid'?: NjsByteString; - readonly 'pipe'?: NjsByteString; - readonly 'protocol'?: NjsByteString; - readonly 'proxy_add_x_forwarded_for'?: NjsByteString; - readonly 'proxy_host'?: NjsByteString; - readonly 'proxy_port'?: NjsByteString; - readonly 'proxy_protocol_addr'?: NjsByteString; - readonly 'proxy_protocol_port'?: NjsByteString; - readonly 'proxy_protocol_server_addr'?: NjsByteString; - readonly 'proxy_protocol_server_port'?: NjsByteString; - readonly 'query_string'?: NjsByteString; - readonly 'realip_remote_addr'?: NjsByteString; - readonly 'realip_remote_port'?: NjsByteString; - readonly 'realpath_root'?: NjsByteString; - readonly 'remote_addr'?: NjsByteString; - readonly 'remote_port'?: NjsByteString; - readonly 'remote_user'?: NjsByteString; - readonly 'request'?: NjsByteString; - readonly 'request_body'?: NjsByteString; - readonly 'request_body_file'?: NjsByteString; - readonly 'request_completion'?: NjsByteString; - readonly 'request_filename'?: NjsByteString; - readonly 'request_id'?: NjsByteString; - readonly 'request_length'?: NjsByteString; - readonly 'request_method'?: NjsByteString; - readonly 'request_time'?: NjsByteString; - readonly 'request_uri'?: NjsByteString; - readonly 'scheme'?: NjsByteString; - readonly 'secure_link'?: NjsByteString; - readonly 'secure_link_expires'?: NjsByteString; - readonly 'sent_http_'?: NjsByteString; - readonly 'sent_trailer_'?: NjsByteString; - readonly 'server_addr'?: NjsByteString; - readonly 'server_name'?: NjsByteString; - readonly 'server_port'?: NjsByteString; - readonly 'server_protocol'?: NjsByteString; - readonly 'session_log_binary_id'?: NjsByteString; - readonly 'session_log_id'?: NjsByteString; - readonly 'session_time'?: NjsByteString; - readonly 'slice_range'?: NjsByteString; - readonly 'spdy'?: NjsByteString; - readonly 'spdy_request_priority'?: NjsByteString; - readonly 'ssl_cipher'?: NjsByteString; - readonly 'ssl_ciphers'?: NjsByteString; - readonly 'ssl_client_cert'?: NjsByteString; - readonly 'ssl_client_escaped_cert'?: NjsByteString; - readonly 'ssl_client_fingerprint'?: NjsByteString; - readonly 'ssl_client_i_dn'?: NjsByteString; - readonly 'ssl_client_i_dn_legacy'?: NjsByteString; - readonly 'ssl_client_raw_cert'?: NjsByteString; - readonly 'ssl_client_s_dn'?: NjsByteString; - readonly 'ssl_client_s_dn_legacy'?: NjsByteString; - readonly 'ssl_client_serial'?: NjsByteString; - readonly 'ssl_client_v_end'?: NjsByteString; - readonly 'ssl_client_v_remain'?: NjsByteString; - readonly 'ssl_client_v_start'?: NjsByteString; - readonly 'ssl_client_verify'?: NjsByteString; - readonly 'ssl_curves'?: NjsByteString; - readonly 'ssl_early_data'?: NjsByteString; - readonly 'ssl_preread_alpn_protocols'?: NjsByteString; - readonly 'ssl_preread_protocol'?: NjsByteString; - readonly 'ssl_preread_server_name'?: NjsByteString; - readonly 'ssl_protocol'?: NjsByteString; - readonly 'ssl_server_name'?: NjsByteString; - readonly 'ssl_session_id'?: NjsByteString; - readonly 'ssl_session_reused'?: NjsByteString; - readonly 'status'?: NjsByteString; - readonly 'tcpinfo_rtt'?: NjsByteString; - readonly 'tcpinfo_rttvar'?: NjsByteString; - readonly 'tcpinfo_snd_cwnd'?: NjsByteString; - readonly 'tcpinfo_rcv_space'?: NjsByteString; - readonly 'time_iso8601'?: NjsByteString; - readonly 'time_local'?: NjsByteString; - readonly 'uid_got'?: NjsByteString; - readonly 'uid_reset'?: NjsByteString; - readonly 'uid_set'?: NjsByteString; - readonly 'upstream_addr'?: NjsByteString; - readonly 'upstream_bytes_received'?: NjsByteString; - readonly 'upstream_bytes_sent'?: NjsByteString; - readonly 'upstream_cache_status'?: NjsByteString; - readonly 'upstream_connect_time'?: NjsByteString; - readonly 'upstream_cookie_'?: NjsByteString; - readonly 'upstream_first_byte_time'?: NjsByteString; - readonly 'upstream_header_time'?: NjsByteString; - readonly 'upstream_http_'?: NjsByteString; - readonly 'upstream_queue_time'?: NjsByteString; - readonly 'upstream_response_length'?: NjsByteString; - readonly 'upstream_response_time'?: NjsByteString; - readonly 'upstream_session_time'?: NjsByteString; - readonly 'upstream_status'?: NjsByteString; - readonly 'upstream_trailer_'?: NjsByteString; - readonly 'uri'?: NjsByteString; - - [prop: string]: NjsStringLike; -} - -interface NginxSubrequestOptions { - /** - * Arguments string, by default an empty string is used. - */ - args?: NjsStringLike, - /** - * Request body, by default the request body of the parent request object is used. - */ - body?: NjsStringLike, - /** - * HTTP method, by default the GET method is used. - */ - method?: "GET" | "POST" | "OPTIONS" | "HEAD" | "PROPFIND" | "PUT" - | "MKCOL" | "DELETE" | "COPY" | "MOVE" | "PROPPATCH" - | "LOCK" | "PATCH" | "TRACE", - /** - * if true, the created subrequest is a detached subrequest. - * Responses to detached subrequests are ignored. - */ - detached?: boolean -} - -interface NginxHTTPRequest { - /** - * Request arguments object. - */ - readonly args: NginxHTTPArgs; - /** - * Writes a string to the error log on the error level of logging. - * @param message Message to log. - */ - error(message: NjsStringLike): void; - /** - * Finishes sending a response to the client. - */ - finish(): void; - /** - * Incoming headers object. - */ - readonly headersIn: NginxHeadersIn; - /** - * Outgoing headers object. - */ - readonly headersOut: NginxHeadersOut; - /** - * HTTP protocol version. - */ - readonly httpVersion: NjsByteString; - /** - * Performs an internal redirect to the specified uri. - * If the uri starts with the ?@? prefix, it is considered a named location. - * The actual redirect happens after the handler execution is completed. - * @param uri Location to redirect to. - */ - internalRedirect(uri: NjsStringLike): void; - /** - * Writes a string to the error log on the info level of logging. - * @param message Message to log. - */ - log(message: NjsStringLike): void; - /** - * HTTP method. - */ - readonly method: NjsByteString; - /** - * Parent for subrequest object. - */ - readonly parent?: NginxHTTPRequest; - /** - * Client address. - */ - readonly remoteAddress: NjsByteString; - /** - * Client request body if it has not been written to a temporary file. - * To ensure that the client request body is in memory, its size should be - * limited by client_max_body_size, and a sufficient buffer size should be set - * using client_body_buffer_size. The property is available only in the js_content directive. - */ - readonly requestBody?: NjsByteString; - /** - * Subrequest response body. The size of response body is limited by - * the subrequest_output_buffer_size directive. - */ - readonly responseBody?: NjsByteString; - /** - * Sends the entire response with the specified status to the client. - * It is possible to specify either a redirect URL (for codes 301, 302, 303, 307, and 308) - * or the response body text (for other codes) as the second argument. - * @param status Respose status code. - * @param body Respose body. - */ - return(status: number, body?: NjsStringLike): void; - /** - * Sends the HTTP headers to the client. - */ - send(part: NjsStringLike): void; - /** - * Sends the HTTP headers to the client. - */ - sendHeader(): void; - /** - * Respose status code. - */ - status: number; - /** - * Creates a subrequest with the given uri and options. - * A subrequest shares its input headers with the client request. - * To send headers different from original headers to a proxied server, - * the proxy_set_header directive can be used. To send a completely new - * set of headers to a proxied server, the proxy_pass_request_headers directive can be used. - * @param uri Subrequest location. - * @param options Subrequest options. - * @param callback Completion callback. - */ - subrequest(uri: NjsStringLike, options?: NginxSubrequestOptions | string): Promise; - subrequest(uri: NjsStringLike, options: NginxSubrequestOptions | string, - callback:(reply:NginxHTTPRequest) => void): void; - subrequest(uri: NjsStringLike, callback:(reply:NginxHTTPRequest) => void): void; - subrequest(uri: NjsStringLike, options: NginxSubrequestOptions & { detached: true }): void; - /** - * Current URI in request, normalized. - */ - readonly uri: NjsByteString; - /** - * nginx variables object. - */ - readonly variables: NginxVariables; - /** - * Writes a string to the error log on the warn level of logging. - * @param message Message to log. - */ - warn(message: NjsStringLike): void; -} diff -r 3e0684a2e793 -r 1ddcc8b77dab nginx/ts/ngx_stream_js_module.d.ts --- a/nginx/ts/ngx_stream_js_module.d.ts Thu Oct 22 22:45:00 2020 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,148 +0,0 @@ -/// - -interface NginxStreamVariables { - readonly 'binary_remote_addr'?: NjsByteString; - readonly 'bytes_received'?: NjsByteString; - readonly 'bytes_sent'?: NjsByteString; - readonly 'connection'?: NjsByteString; - readonly 'geoip_area_code'?: NjsByteString; - readonly 'geoip_city'?: NjsByteString; - readonly 'geoip_city_continent_code'?: NjsByteString; - readonly 'geoip_city_country_code'?: NjsByteString; - readonly 'geoip_city_country_code3'?: NjsByteString; - readonly 'geoip_city_country_name'?: NjsByteString; - readonly 'geoip_country_code'?: NjsByteString; - readonly 'geoip_country_code3'?: NjsByteString; - readonly 'geoip_country_name'?: NjsByteString; - readonly 'geoip_dma_code'?: NjsByteString; - readonly 'geoip_latitude'?: NjsByteString; - readonly 'geoip_longitude'?: NjsByteString; - readonly 'geoip_org'?: NjsByteString; - readonly 'geoip_postal_code'?: NjsByteString; - readonly 'geoip_region'?: NjsByteString; - readonly 'geoip_region_name'?: NjsByteString; - readonly 'hostname'?: NjsByteString; - readonly 'limit_conn_status'?: NjsByteString; - readonly 'msec'?: NjsByteString; - readonly 'nginx_version'?: NjsByteString; - readonly 'pid'?: NjsByteString; - readonly 'proxy_add_x_forwarded_for'?: NjsByteString; - readonly 'proxy_host'?: NjsByteString; - readonly 'proxy_port'?: NjsByteString; - readonly 'proxy_protocol_addr'?: NjsByteString; - readonly 'proxy_protocol_port'?: NjsByteString; - readonly 'proxy_protocol_server_addr'?: NjsByteString; - readonly 'proxy_protocol_server_port'?: NjsByteString; - readonly 'realip_remote_addr'?: NjsByteString; - readonly 'realip_remote_port'?: NjsByteString; - readonly 'remote_addr'?: NjsByteString; - readonly 'remote_port'?: NjsByteString; - readonly 'server_addr'?: NjsByteString; - readonly 'server_port'?: NjsByteString; - readonly 'ssl_cipher'?: NjsByteString; - readonly 'ssl_ciphers'?: NjsByteString; - readonly 'ssl_client_cert'?: NjsByteString; - readonly 'ssl_client_escaped_cert'?: NjsByteString; - readonly 'ssl_client_fingerprint'?: NjsByteString; - readonly 'ssl_client_i_dn'?: NjsByteString; - readonly 'ssl_client_raw_cert'?: NjsByteString; - readonly 'ssl_client_s_dn'?: NjsByteString; - readonly 'ssl_client_s_dn_legacy'?: NjsByteString; - readonly 'ssl_client_serial'?: NjsByteString; - readonly 'ssl_client_v_end'?: NjsByteString; - readonly 'ssl_client_v_remain'?: NjsByteString; - readonly 'ssl_client_v_start'?: NjsByteString; - readonly 'ssl_client_verify'?: NjsByteString; - readonly 'ssl_curves'?: NjsByteString; - readonly 'ssl_early_data'?: NjsByteString; - readonly 'ssl_preread_alpn_protocols'?: NjsByteString; - readonly 'ssl_preread_protocol'?: NjsByteString; - readonly 'ssl_preread_server_name'?: NjsByteString; - readonly 'ssl_protocol'?: NjsByteString; - readonly 'ssl_server_name'?: NjsByteString; - readonly 'ssl_session_id'?: NjsByteString; - readonly 'ssl_session_reused'?: NjsByteString; - readonly 'status'?: NjsByteString; - readonly 'time_iso8601'?: NjsByteString; - readonly 'time_local'?: NjsByteString; - - [prop: string]: NjsByteString; -} - -interface NginxStreamCallbackFlags { - /** - * True if data is a last buffer. - */ - last: boolean -} - -interface NginxStreamSendOptions { - /** - * True if data is a last buffer. - */ - last?: boolean - /** - * True if the buffer should have the flush flag. - */ - flush?: boolean -} - -interface NginxStreamRequest { - /** - * Successfully finalizes the phase handler. - */ - allow(): void; - /** - * Finalizes the phase handler and passes control to the next handler. - */ - decline(): void; - /** - * Finalizes the phase handler with the access error code. - */ - deny(): void; - /** - * Successfully finalizes the current phase handler - * or finalizes it with the specified numeric code. - * @param code Finalization code. - */ - done(code?: number): void; - /** - * Writes a string to the error log on the error level of logging. - * @param message Message to log. - */ - error(message: NjsStringLike): void; - /** - * Writes a string to the error log on the info level of logging. - * @param message Message to log. - */ - log(message: NjsStringLike): void; - /** - * Unregisters the callback set by on() method. - */ - off(event: "upload" | "download"): void; - /** - * Registers a callback for the specified event. - */ - on(event: "upload" | "download", - callback:(data:NjsByteString, flags: NginxStreamCallbackFlags) => void): void; - /** - * Client address. - */ - readonly remoteAddress: NjsByteString; - /** - * Sends the data to the client. - * @param data Data to send. - * @param options Object used to override nginx buffer flags derived from - * an incoming data chunk buffer. - */ - send(data: NjsStringLike, options?: NginxStreamSendOptions): void; - /** - * nginx variables object. - */ - readonly variables: NginxStreamVariables; - /** - * Writes a string to the error log on the warn level of logging. - * @param message Message to log. - */ - warn(message: NjsStringLike): void; -} diff -r 3e0684a2e793 -r 1ddcc8b77dab src/ts/crypto.d.ts --- a/src/ts/crypto.d.ts Thu Oct 22 22:45:00 2020 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,76 +0,0 @@ -/// - -declare module "crypto" { - - export type Algorithm = "md5" | "sha1" | "sha256"; - - export type DigestEncoding = Exclude; - - export interface Hash { - /** - * Updates the hash content with the given `data` and returns self. - */ - update(data: NjsStringLike | Buffer | DataView | TypedArray): Hash; - - /** - * Calculates the digest of all of the data passed using `hash.update()`. - * - * @example - * import cr from 'crypto' - * cr.createHash('sha1').update('A').update('B').digest('base64url') // => 'BtlFlCqiamG-GMPiK_GbvKjdK10' - * - * @param encoding The encoding of the return value. If not provided, a `Buffer` object - * (or a byte string before version 0.4.4) is returned. - * @return A calculated digest. - */ - digest(): Buffer; - digest(encoding: DigestEncoding): string; - } - - export interface Hmac { - /** - * Updates the HMAC content with the given `data` and returns self. - */ - update(data: NjsStringLike | Buffer | DataView | TypedArray): Hmac; - - /** - * Calculates the HMAC digest of all of the data passed using `hmac.update()`. - * - * @example - * import cr from 'crypto' - * cr.createHmac('sha1', 'secret.key').update('AB').digest('base64url') // => 'Oglm93xn23_MkiaEq_e9u8zk374' - * - * @param encoding The encoding of the return value. If not provided, a `Buffer` object - * (or a byte string before version 0.4.4) is returned. - * @return The calculated HMAC digest. - */ - digest(): Buffer; - digest(encoding: DigestEncoding): string; - } - - interface Crypto { - /** - * Creates and returns a `Hash` object that can be used to generate hash digests using - * the given `algorithm`. - * - * @param algorithm `'md5'`, `'sha1'`, or `'sha256'` - * @returns A `Hash` object. - */ - createHash(algorithm: Algorithm): Hash; - - /** - * Creates and returns an HMAC object that uses the given `algorithm` and secret `key`. - * - * @param algorithm `'md5'`, `'sha1'`, or `'sha256'` - * @param key The secret key. - * @returns An `HMAC` object. - */ - createHmac(algorithm: Algorithm, key: NjsStringLike): Hmac; - } - - const crypto: Crypto; - - // It's exported like this because njs doesn't support named imports. - // TODO: Replace NjsFS with individual named exports as soon as njs supports named imports. - export default crypto; -} diff -r 3e0684a2e793 -r 1ddcc8b77dab src/ts/fs.d.ts --- a/src/ts/fs.d.ts Thu Oct 22 22:45:00 2020 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,384 +0,0 @@ -/// - -declare module "fs" { - - /** - * File system flag that controls opening of a file. - * - * - `'a'` - Open a file for appending. The file is created if it does not exist. - * - `'ax'` - The same as `'a'` but fails if the file already exists. - * - `'a+'` - Open a file for reading and appending. If the file does not exist, it will be created. - * - `'ax+'` - The same as `'a+'` but fails if the file already exists. - * - `'as'` - Open a file for appending in synchronous mode. If the file does not exist, it will be created. - * - `'as+'` - Open a file for reading and appending in synchronous mode. If the file does not exist, it will be created. - * - `'r'` - Open a file for reading. An exception occurs if the file does not exist. - * - `'r+'` - Open a file for reading and writing. An exception occurs if the file does not exist. - * - `'rs+'` - Open a file for reading and writing in synchronous mode. Instructs the operating system to bypass the local file system cache. - * - `'w'` - Open a file for writing. If the file does not exist, it will be created. If the file exists, it will be replaced. - * - `'wx'` - The same as `'w'` but fails if the file already exists. - * - `'w+'` - Open a file for reading and writing. If the file does not exist, it will be created. If the file exists, it will be replaced. - * - `'wx+'` - The same as `'w+'` but fails if the file already exists. - */ - export type OpenMode = "a" | "ax" | "a+" | "ax+" | "as" | "as+" | "r" | "r+" | "rs+" | "w" | "wx" | "w+" | "wx+"; - - export type FileEncoding = BufferEncoding; - - /** - * Valid types for path values in "fs". - */ - export type PathLike = string | Buffer; - - /** - * A representation of a directory entry - a file or a subdirectory. - * - * When `readdirSync()` is called with the `withFileTypes` option, the resulting array contains - * `fs.Dirent` objects. - */ - export interface Dirent { - /** - * @returns `true` if the object describes a block device. - */ - isBlockDevice(): boolean; - /** - * @returns `true` if the object describes a character device. - */ - isCharacterDevice(): boolean; - /** - * @returns `true` if the object describes a file system directory. - */ - isDirectory(): boolean; - /** - * @returns `true` if the object describes a first-in-first-out (FIFO) pipe. - */ - isFIFO(): boolean; - /** - * @returns `true` if the object describes a regular file. - */ - isFile(): boolean; - /** - * @returns `true` if the object describes a socket. - */ - isSocket(): boolean; - /** - * @returns `true` if the object describes a symbolic link. - */ - isSymbolicLink(): boolean; - - /** - * The name of the file this object refers to. - */ - name: string; - } - - type WriteFileOptions = { - mode?: number; - flag?: OpenMode; - }; - - type Constants = { - /** - * Indicates that the file is visible to the calling process, used by default if no mode - * is specified. - */ - F_OK: 0; - /** - * Indicates that the file can be read by the calling process. - */ - R_OK: 4; - /** - * Indicates that the file can be written by the calling process. - */ - W_OK: 2; - /** - * Indicates that the file can be executed by the calling process. - */ - X_OK: 1; - }; - - interface Promises { - /** - * Asynchronously tests permissions for a file or directory specified in the `path`. - * If the check fails, an error will be returned, otherwise, the method will return undefined. - * - * @example - * import fs from 'fs' - * fs.promises.access('/file/path', fs.constants.R_OK | fs.constants.W_OK) - * .then(() => console.log('has access')) - * .catch(() => console.log('no access')) - * - * @since 0.3.9 - * @param path A path to a file or directory. - * @param mode An optional integer that specifies the accessibility checks to be performed. - * Defaults to `fs.constants.F_OK`. - */ - access(path: PathLike, mode?: number): Promise; - - /** - * Asynchronously appends specified `data` to a file with provided `filename`. - * If the file does not exist, it will be created. - * - * @since 0.4.4 - * @param path A path to a file. - * @param data The data to write. - * @param options An object optionally specifying the file mode and flag. - * If `mode` is not supplied, the default of `0o666` is used. - * If `flag` is not supplied, the default of `'a'` is used. - */ - appendFile(path: PathLike, data: NjsStringLike | Buffer, options?: WriteFileOptions): Promise; - - /** - * Asynchronously creates a directory at the specified `path`. - * - * @since 0.4.2 - * @param path A path to a file. - * @param options The file mode (or an object specifying the file mode). Defaults to `0o777`. - */ - mkdir(path: PathLike, options?: { mode?: number } | number): Promise; - - /** - * Asynchronously reads the contents of a directory at the specified `path`. - * - * @since 0.4.2 - * @param path A path to a file. - * @param options A string that specifies encoding or an object optionally specifying - * the following keys: - * - `encoding` - `'utf8'` (default) or `'buffer'` (since 0.4.4) - * - `withFileTypes` - if set to `true`, the files array will contain `fs.Dirent` objects; defaults to `false`. - */ - readdir(path: PathLike, options?: { encoding?: "utf8"; withFileTypes?: false; } | "utf8"): Promise; - readdir(path: PathLike, options: { encoding: "buffer"; withFileTypes?: false; } | "buffer"): Promise; - readdir(path: PathLike, options: { encoding?: "utf8" | "buffer"; withFileTypes: true; }): Promise; - - /** - * Asynchronously returns the contents of the file with provided `filename`. - * If an encoding is specified, a `string` is returned, otherwise, a `Buffer`. - * - * @param path A path to a file. - * @param options A string that specifies encoding or an object with the following optional keys: - * - `encoding` - `'utf8'`, `'hex'`, `'base64'`, or `'base64url'` (the last three since 0.4.4). - * - `flag` - file system flag, defaults to `r`. - */ - readFile(path: PathLike): Promise; - readFile(path: PathLike, options?: { flag?: OpenMode; }): Promise; - readFile(path: PathLike, options: { encoding?: FileEncoding; flag?: OpenMode; } | FileEncoding): Promise; - - /** - * Asynchronously computes the canonical pathname by resolving `.`, `..` and symbolic links using - * `realpath(3)`. - * - * @since 0.3.9 - * @param path A path to a file. - * @param options The encoding (or an object specifying the encoding), used as the encoding of the result. - */ - realpath(path: PathLike, options?: { encoding?: "utf8" } | "utf8"): Promise; - realpath(path: PathLike, options: { encoding: "buffer" } | "buffer"): Promise; - - /** - * Asynchronously changes the name or location of a file from `oldPath` to `newPath`. - * - * @since 0.3.4 - * @param oldPath A path to a file. - * @param newPath A path to a file. - */ - rename(oldPath: PathLike, newPath: PathLike): Promise; - - /** - * Asynchronously removes a directory at the specified `path`. - * - * @since 0.4.2 - * @param path A path to a file. - */ - rmdir(path: PathLike): Promise; - - /** - * Asynchronously creates the link called `path` pointing to `target` using `symlink(2)`. - * Relative targets are relative to the link?s parent directory. - * - * @since 0.3.9 - * @param target A path to an existing file. - * @param path A path to the new symlink. - */ - symlink(target: PathLike, path: PathLike): Promise; - - /** - * Asynchronously unlinks a file by `path`. - * - * @since 0.3.9 - * @param path A path to a file. - */ - unlink(path: PathLike): Promise; - - /** - * Asynchronously writes `data` to a file with provided `filename`. If the file does not - * exist, it will be created, if the file exists, it will be replaced. - * - * @since 0.4.4 - * @param path A path to a file. - * @param data The data to write. - * @param options An object optionally specifying the file mode and flag. - * If `mode` is not supplied, the default of `0o666` is used. - * If `flag` is not supplied, the default of `'w'` is used. - */ - writeFile(path: PathLike, data: NjsStringLike | Buffer, options?: WriteFileOptions): Promise; - } - - interface NjsFS { - /** - * Promissified versions of file system methods. - * - * @since 0.3.9 - */ - promises: Promises - /** - * File Access Constants - */ - constants: Constants - - /** - * Synchronously tests permissions for a file or directory specified in the `path`. - * If the check fails, an error will be returned, otherwise, the method will return undefined. - * - * @example - * try { - * fs.accessSync('/file/path', fs.constants.R_OK | fs.constants.W_OK); - * console.log('has access'); - * } catch (e) { - * console.log('no access'); - * } - * - * @since 0.3.9 - * @param path A path to a file or directory. - * @param mode An optional integer that specifies the accessibility checks to be performed. - * Defaults to `fs.constants.F_OK`. - */ - accessSync(path: PathLike, mode?: number): void; - - /** - * Synchronously appends specified `data` to a file with provided `filename`. - * If the file does not exist, it will be created. - * - * @since 0.4.4 - * @param path A path to a file. - * @param data The data to write. - * @param options An object optionally specifying the file mode and flag. - * If `mode` is not supplied, the default of `0o666` is used. - * If `flag` is not supplied, the default of `'a'` is used. - */ - appendFileSync(path: PathLike, data: NjsStringLike | Buffer, options?: WriteFileOptions): void; - - /** - * Synchronously creates a directory at the specified `path`. - * - * @since 0.4.2 - * @param path A path to a file. - * @param options The file mode (or an object specifying the file mode). Defaults to `0o777`. - */ - mkdirSync(path: PathLike, options?: { mode?: number } | number): void; - - /** - * Synchronously reads the contents of a directory at the specified `path`. - * - * @since 0.4.2 - * @param path A path to a file. - * @param options A string that specifies encoding or an object optionally specifying - * the following keys: - * - `encoding` - `'utf8'` (default) or `'buffer'` (since 0.4.4) - * - `withFileTypes` - if set to `true`, the files array will contain `fs.Dirent` objects; - * defaults to `false`. - */ - readdirSync(path: PathLike, options?: { encoding?: "utf8"; withFileTypes?: false; } | "utf8"): string[]; - readdirSync(path: PathLike, options: { encoding: "buffer"; withFileTypes?: false; } | "buffer"): Buffer[]; - readdirSync(path: PathLike, options: { encoding?: "utf8" | "buffer"; withFileTypes: true; }): Dirent[]; - - /** - * Synchronously returns the contents of the file with provided `filename`. - * If an encoding is specified, a `string` is returned, otherwise, a `Buffer`. - * - * @example - * import fs from 'fs' - * var file = fs.readFileSync('/file/path.tar.gz') - * var gzipped = file.slice(0,2).toString('hex') === '1f8b'; gzipped // => true - * - * @param path A path to a file. - * @param options A string that specifies encoding or an object with the following optional keys: - * - `encoding` - `'utf8'`, `'hex'`, `'base64'`, or `'base64url'` (the last three since 0.4.4). - * - `flag` - file system flag, defaults to `r`. - */ - readFileSync(path: PathLike): Buffer; - readFileSync(path: PathLike, options?: { flag?: OpenMode; }): Buffer; - readFileSync(path: PathLike, options: { encoding?: FileEncoding; flag?: OpenMode; } | FileEncoding): string; - - /** - * Synchronously computes the canonical pathname by resolving `.`, `..` and symbolic links using - * `realpath(3)`. - * - * @since 0.3.9 - * @param path A path to a file. - * @param options The encoding (or an object specifying the encoding), used as the encoding of the result. - */ - realpathSync(path: PathLike, options?: { encoding?: "utf8" } | "utf8"): string; - realpathSync(path: PathLike, options: { encoding: "buffer" } | "buffer"): Buffer; - - /** - * Synchronously changes the name or location of a file from `oldPath` to `newPath`. - * - * @example - * import fs from 'fs' - * var file = fs.renameSync('hello.txt', 'HelloWorld.txt') - * - * @since 0.3.4 - * @param oldPath A path to a file. - * @param newPath A path to a file. - */ - renameSync(oldPath: PathLike, newPath: PathLike): void; - - /** - * Synchronously removes a directory at the specified `path`. - * - * @since 0.4.2 - * @param path A path to a file. - */ - rmdirSync(path: PathLike): void; - - /** - * Synchronously creates the link called `path` pointing to `target` using `symlink(2)`. - * Relative targets are relative to the link?s parent directory. - * - * @since 0.3.9 - * @param target A path to an existing file. - * @param path A path to the new symlink. - */ - symlinkSync(target: PathLike, path: PathLike): void; - - /** - * Synchronously unlinks a file by `path`. - * - * @since 0.3.9 - * @param path A path to a file. - */ - unlinkSync(path: PathLike): void; - - /** - * Synchronously writes `data` to a file with provided `filename`. If the file does not exist, - * it will be created, if the file exists, it will be replaced. - * - * @example - * import fs from 'fs' - * fs.writeFileSync('hello.txt', 'Hello world') - * - * @since 0.4.4 - * @param path A path to a file. - * @param data The data to write. - * @param options An object optionally specifying the file mode and flag. - * If `mode` is not supplied, the default of `0o666` is used. - * If `flag` is not supplied, the default of `'w'` is used. - */ From xeioex at nginx.com Thu Oct 29 13:00:05 2020 From: xeioex at nginx.com (Dmitry Volyntsev) Date: Thu, 29 Oct 2020 13:00:05 +0000 Subject: [njs] Types: added tsconfig.json and package.json for type descriptions. Message-ID: details: https://hg.nginx.org/njs/rev/e1dc1fd52fe9 branches: changeset: 1551:e1dc1fd52fe9 user: Jakub Jirutka date: Tue Oct 20 21:16:20 2020 +0200 description: Types: added tsconfig.json and package.json for type descriptions. diffstat: ts/package.json | 30 ++++++++++++++++++++++++++++++ ts/tsconfig.json | 24 ++++++++++++++++++++++++ 2 files changed, 54 insertions(+), 0 deletions(-) diffs (62 lines): diff -r 1ddcc8b77dab -r e1dc1fd52fe9 ts/package.json --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/ts/package.json Tue Oct 20 21:16:20 2020 +0200 @@ -0,0 +1,30 @@ +{ + "name": "njs-types", + "version": "0.0.0-dev", + "description": "TypeScript definitions for njs scripting language and nginx js modules.", + "scripts": { + "lint": "tsc" + }, + "files": [ + "**/*.d.ts" + ], + "types": "index.d.ts", + "repository": { + "type": "git", + "url": "https://github.com/nginx/njs.git" + }, + "keywords": [ + "nginx", + "njs", + "types" + ], + "author": "NGINX, Inc.", + "license": "BSD-2-Clause", + "bugs": { + "url": "https://github.com/nginx/njs/issues" + }, + "homepage": "https://nginx.org/en/docs/njs/", + "devDependencies": { + "typescript": "^4.0.3" + } +} diff -r 1ddcc8b77dab -r e1dc1fd52fe9 ts/tsconfig.json --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/ts/tsconfig.json Tue Oct 20 21:16:20 2020 +0200 @@ -0,0 +1,24 @@ +{ + "compilerOptions": { + "target": "es5", + "module": "es2015", + "lib": [ + "ES2015", + "ES2016.Array.Include", + "ES2017.Object", + "ES2017.String" + ], + "noEmit": true, + "strict": true, + "noImplicitAny": true, + "strictNullChecks": true, + "strictFunctionTypes": true, + "strictBindCallApply": true, + "strictPropertyInitialization": true, + "noImplicitThis": true, + "alwaysStrict": true, + + "moduleResolution": "node", + "forceConsistentCasingInFileNames": true + } +} From xeioex at nginx.com Thu Oct 29 13:00:07 2020 From: xeioex at nginx.com (Dmitry Volyntsev) Date: Thu, 29 Oct 2020 13:00:07 +0000 Subject: [njs] Types: added missing var "console" into njs_shell. Message-ID: details: https://hg.nginx.org/njs/rev/862ff6f2c684 branches: changeset: 1552:862ff6f2c684 user: Jakub Jirutka date: Sat Oct 24 23:59:18 2020 +0200 description: Types: added missing var "console" into njs_shell. diffstat: ts/njs_shell.d.ts | 2 ++ 1 files changed, 2 insertions(+), 0 deletions(-) diffs (9 lines): diff -r e1dc1fd52fe9 -r 862ff6f2c684 ts/njs_shell.d.ts --- a/ts/njs_shell.d.ts Tue Oct 20 21:16:20 2020 +0200 +++ b/ts/njs_shell.d.ts Sat Oct 24 23:59:18 2020 +0200 @@ -7,3 +7,5 @@ interface Console { time(label?: NjsStringLike): void; timeEnd(label?: NjsStringLike): void; } + +declare const console: Console; From xeioex at nginx.com Thu Oct 29 13:00:09 2020 From: xeioex at nginx.com (Dmitry Volyntsev) Date: Thu, 29 Oct 2020 13:00:09 +0000 Subject: [njs] Types: fixed index types in modules. Message-ID: details: https://hg.nginx.org/njs/rev/3cc202e562e4 branches: changeset: 1553:3cc202e562e4 user: Jakub Jirutka date: Mon Oct 19 23:18:22 2020 +0200 description: Types: fixed index types in modules. Fixes the following type errors: Property ''xxx'' of type 'NjsByteString | undefined' is not assignable to string index type 'NjsStringLike'.ts(2411) While string index signatures are a powerful way to describe the "dictionary" pattern, they also enforce that all properties match their return type. diffstat: ts/ngx_http_js_module.d.ts | 6 +++--- ts/ngx_stream_js_module.d.ts | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diffs (42 lines): diff -r 862ff6f2c684 -r 3cc202e562e4 ts/ngx_http_js_module.d.ts --- a/ts/ngx_http_js_module.d.ts Sat Oct 24 23:59:18 2020 +0200 +++ b/ts/ngx_http_js_module.d.ts Mon Oct 19 23:18:22 2020 +0200 @@ -39,7 +39,7 @@ interface NginxHeadersIn { readonly 'Warning'?: NjsByteString; readonly 'X-Forwarded-For'?: NjsByteString; - readonly [prop: string]: NjsByteString; + readonly [prop: string]: NjsByteString | undefined; } interface NginxHeadersOut { @@ -76,7 +76,7 @@ interface NginxHeadersOut { 'Set-Cookie'?: NjsStringLike[]; - [prop: string]: NjsStringLike | NjsStringLike[]; + [prop: string]: NjsStringLike | NjsStringLike[] | undefined; } interface NginxVariables { @@ -229,7 +229,7 @@ interface NginxVariables { readonly 'upstream_trailer_'?: NjsByteString; readonly 'uri'?: NjsByteString; - [prop: string]: NjsStringLike; + [prop: string]: NjsStringLike | undefined; } interface NginxSubrequestOptions { diff -r 862ff6f2c684 -r 3cc202e562e4 ts/ngx_stream_js_module.d.ts --- a/ts/ngx_stream_js_module.d.ts Sat Oct 24 23:59:18 2020 +0200 +++ b/ts/ngx_stream_js_module.d.ts Mon Oct 19 23:18:22 2020 +0200 @@ -66,7 +66,7 @@ interface NginxStreamVariables { readonly 'time_iso8601'?: NjsByteString; readonly 'time_local'?: NjsByteString; - [prop: string]: NjsByteString; + [prop: string]: NjsByteString | undefined; } interface NginxStreamCallbackFlags { From xeioex at nginx.com Thu Oct 29 13:00:13 2020 From: xeioex at nginx.com (Dmitry Volyntsev) Date: Thu, 29 Oct 2020 13:00:13 +0000 Subject: [njs] Types: refactored working with TypeScript API description. Message-ID: details: https://hg.nginx.org/njs/rev/a3ae0d653f49 branches: changeset: 1554:a3ae0d653f49 user: Jakub Jirutka date: Thu Oct 29 12:50:05 2020 +0000 description: Types: refactored working with TypeScript API description. diffstat: auto/make | 47 +++++++++++++++++++++----- auto/sources | 2 + ts/README.md | 79 ++++++++++++++++++++++++++++++++++++++++++++ ts/index.d.ts | 4 ++ ts/ngx_http_js_module.d.ts | 2 +- ts/ngx_stream_js_module.d.ts | 2 +- ts/njs_shell.d.ts | 2 +- ts/package.json | 3 +- 8 files changed, 128 insertions(+), 13 deletions(-) diffs (211 lines): diff -r 3cc202e562e4 -r a3ae0d653f49 auto/make --- a/auto/make Mon Oct 19 23:18:22 2020 +0200 +++ b/auto/make Thu Oct 29 12:50:05 2020 +0000 @@ -22,6 +22,9 @@ NJS_LINK = ${CC} ${NJS_LD_OPT} NJS_CFLAGS = ${NJS_CFLAGS} ${NJS_CC_OPT} ${CFLAGS} NJS_VER = $(grep NJS_VERSION src/njs.h | sed -e 's/.*"\(.*\)".*/\1/') +NJS_TYPES_VER = \$(NJS_VER) + +NPM = npm default: $NJS_DEFAULT_TARGET @@ -234,15 +237,6 @@ benchmark: $NJS_BUILD_DIR/njs_auto_confi $NJS_BUILD_DIR/njs_benchmark -.PHONY: ts -ts: - mkdir -p $NJS_BUILD_DIR/ts/njs_modules - cp ts/*.d.ts $NJS_BUILD_DIR/ts/ - cp ts/njs_modules/* $NJS_BUILD_DIR/ts/njs_modules/ - -ts_test: ts - tsc ./test/ts/test.ts - dist: rm -rf njs-\$(NJS_VER) \\ && hg archive njs-\$(NJS_VER).tar.gz \\ @@ -251,6 +245,41 @@ dist: && echo njs-\$(NJS_VER).tar.gz done END +njs_ts_deps=`echo $NJS_TS_SRCS \ + | sed -e "s# *\([^ ][^ ]*\)#\1$njs_regex_cont#g"` + +cat << END >> $NJS_MAKEFILE + +$NJS_BUILD_DIR/ts/package.json: $njs_ts_deps + cp -fr ts $NJS_BUILD_DIR/ + cp LICENSE $NJS_BUILD_DIR/ts/ + sed 's/\("version":\s*\)"\([^"]\+\)"/\1"\$(NJS_TYPES_VER)"/' \\ + ts/package.json > $NJS_BUILD_DIR/ts/package.json + +$NJS_BUILD_DIR/ts/node_modules: $NJS_BUILD_DIR/ts/package.json + cd $NJS_BUILD_DIR/ts && \$(NPM) install + touch $NJS_BUILD_DIR/ts/node_modules + +$NJS_BUILD_DIR/njs-types-\$(NJS_TYPES_VER).tgz: $NJS_BUILD_DIR/ts/package.json + hg id -i > $NJS_BUILD_DIR/ts/COMMITHASH || true + cd $NJS_BUILD_DIR && \$(NPM) pack ./ts + +.PHONY: ts +ts: $NJS_BUILD_DIR/ts/package.json + +ts_lint: $NJS_BUILD_DIR/ts/node_modules + cd $NJS_BUILD_DIR/ts && \$(NPM) run lint + +ts_test: ts + tsc ./test/ts/test.ts + +ts_publish: ts_clean $NJS_BUILD_DIR/njs-types-\$(NJS_TYPES_VER).tgz + cd $NJS_BUILD_DIR/ && \$(NPM) publish njs-types-\$(NJS_TYPES_VER).tgz + +ts_clean: + rm -rf $NJS_BUILD_DIR/ts +END + # Makefile. diff -r 3cc202e562e4 -r a3ae0d653f49 auto/sources --- a/auto/sources Mon Oct 19 23:18:22 2020 +0200 +++ b/auto/sources Thu Oct 29 12:50:05 2020 +0000 @@ -71,3 +71,5 @@ NJS_TEST_SRCS=" \ src/test/njs_unit_test.c \ src/test/njs_benchmark.c \ " + +NJS_TS_SRCS=$(find ts/ -name "*.d.ts" -o -name "*.json") diff -r 3cc202e562e4 -r a3ae0d653f49 ts/README.md --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/ts/README.md Thu Oct 29 12:50:05 2020 +0000 @@ -0,0 +1,79 @@ +# TypeScript definitions for njs + +This package contains type definitions for [njs](https://github.com/nginx/njs) ? NGINX JavaScript. + + +## Usage + +Install **njs-types** from the [npm registry](https://www.npmjs.com/) into your project: + +```sh +# using npm: +npm install --save-dev njs-types +# or using yarn: +yarn add --dev njs-types +``` + +njs-types provides three entry points with global declarations for each of njs environments: + +* `njs_shell.d.ts` ? njs shell +* `ngx_http_js_module.d.ts` ? NGINX JS HTTP Module +* `ngx_stream_js_module.d.ts` ? NGINX JS Stream Module + +You can either reference them using [triple-slash directive](https://www.typescriptlang.org/docs/handbook/triple-slash-directives.html) at top of your `.ts` files (adjust `path` to point into your project?s node_modules): + +```ts +/// +``` + +or include them using the [files](https://www.typescriptlang.org/tsconfig#files) flag in your `tsconfig.json`, for example: + +```json +{ + "compilerOptions": { + "target": "ES5", + "module": "es2015", + "lib": [ + "ES2015", + "ES2016.Array.Include", + "ES2017.Object", + "ES2017.String" + ], + "outDir": "./lib", + "downlevelIteration": true, + + "strict": true, + "noImplicitAny": true, + "strictNullChecks": true, + "strictFunctionTypes": true, + "strictBindCallApply": true, + "strictPropertyInitialization": true, + "noImplicitThis": true, + "alwaysStrict": true, + + "moduleResolution": "node", + + "skipLibCheck": true, + "forceConsistentCasingInFileNames": true, + }, + "include": [ + "./src", + ], + "files": [ + "./node_modules/njs-types/ngx_http_js_module.d.ts", + ], +} +``` + + +## Versions + +njs-types is typically being released together with njs. +Their major and minor release numbers (the first two numbers) are always aligned, but the patch version (the third number) may differ. +That's because njs-types may be updated between njs releases and in such case the patch version is incremented. + +It's the same strategy as used in [DefinitelyTyped](https://github.com/DefinitelyTyped/DefinitelyTyped#how-do-definitely-typed-package-versions-relate-to-versions-of-the-corresponding-library). +The reason is that npmjs enforces [SemVer](https://semver.org/) which doesn't allow four-part version number nor provide post-release suffixes. + +You can find from which commit the package was built in file `COMMITHASH` inside the published package. +It contains global revision id in the upstream repository https://hg.nginx.org/njs/ (Mercurial). diff -r 3cc202e562e4 -r a3ae0d653f49 ts/index.d.ts --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/ts/index.d.ts Thu Oct 29 12:50:05 2020 +0000 @@ -0,0 +1,4 @@ +/// +/// +/// +/// diff -r 3cc202e562e4 -r a3ae0d653f49 ts/ngx_http_js_module.d.ts --- a/ts/ngx_http_js_module.d.ts Mon Oct 19 23:18:22 2020 +0200 +++ b/ts/ngx_http_js_module.d.ts Thu Oct 29 12:50:05 2020 +0000 @@ -1,4 +1,4 @@ -/// +/// interface NginxHTTPArgs { readonly [prop: string]: NjsByteString; diff -r 3cc202e562e4 -r a3ae0d653f49 ts/ngx_stream_js_module.d.ts --- a/ts/ngx_stream_js_module.d.ts Mon Oct 19 23:18:22 2020 +0200 +++ b/ts/ngx_stream_js_module.d.ts Thu Oct 29 12:50:05 2020 +0000 @@ -1,4 +1,4 @@ -/// +/// interface NginxStreamVariables { readonly 'binary_remote_addr'?: NjsByteString; diff -r 3cc202e562e4 -r a3ae0d653f49 ts/njs_shell.d.ts --- a/ts/njs_shell.d.ts Mon Oct 19 23:18:22 2020 +0200 +++ b/ts/njs_shell.d.ts Thu Oct 29 12:50:05 2020 +0000 @@ -1,4 +1,4 @@ -/// +/// interface Console { log(...args: any[]): void; diff -r 3cc202e562e4 -r a3ae0d653f49 ts/package.json --- a/ts/package.json Mon Oct 19 23:18:22 2020 +0200 +++ b/ts/package.json Thu Oct 29 12:50:05 2020 +0000 @@ -6,7 +6,8 @@ "lint": "tsc" }, "files": [ - "**/*.d.ts" + "**/*.d.ts", + "COMMITHASH" ], "types": "index.d.ts", "repository": { From xeioex at nginx.com Thu Oct 29 13:00:15 2020 From: xeioex at nginx.com (Dmitry Volyntsev) Date: Thu, 29 Oct 2020 13:00:15 +0000 Subject: [njs] Types: refactored ts_test. Message-ID: details: https://hg.nginx.org/njs/rev/fa3ffb3a159e branches: changeset: 1555:fa3ffb3a159e user: Jakub Jirutka date: Thu Oct 29 12:51:21 2020 +0000 description: Types: refactored ts_test. diffstat: auto/make | 19 +++++++++++++++++-- auto/sources | 2 ++ test/ts/package.json | 15 +++++++++++++++ test/ts/test.ts | 22 +++++++++------------- test/ts/tsconfig.json | 35 +++++++++++++++++++++++++++++++++++ 5 files changed, 78 insertions(+), 15 deletions(-) diffs (172 lines): diff -r a3ae0d653f49 -r fa3ffb3a159e auto/make --- a/auto/make Thu Oct 29 12:50:05 2020 +0000 +++ b/auto/make Thu Oct 29 12:51:21 2020 +0000 @@ -248,6 +248,9 @@ END njs_ts_deps=`echo $NJS_TS_SRCS \ | sed -e "s# *\([^ ][^ ]*\)#\1$njs_regex_cont#g"` +njs_test_ts_deps=`echo $NJS_TEST_TS_SRCS \ + | sed -e "s# *\([^ ][^ ]*\)#\1$njs_regex_cont#g"` + cat << END >> $NJS_MAKEFILE $NJS_BUILD_DIR/ts/package.json: $njs_ts_deps @@ -270,8 +273,20 @@ ts: $NJS_BUILD_DIR/ts/package.json ts_lint: $NJS_BUILD_DIR/ts/node_modules cd $NJS_BUILD_DIR/ts && \$(NPM) run lint -ts_test: ts - tsc ./test/ts/test.ts +$NJS_BUILD_DIR/test/ts/package.json: $njs_test_ts_deps + mkdir -p $NJS_BUILD_DIR/test + cp -fr test/ts $NJS_BUILD_DIR/test/ + +$NJS_BUILD_DIR/test/ts/node_modules: \\ + $NJS_BUILD_DIR/njs-types-\$(NJS_TYPES_VER).tgz \\ + $NJS_BUILD_DIR/test/ts/package.json + cd $NJS_BUILD_DIR/test/ts && \$(NPM) install \\ + --save-dev file:../../njs-types-\$(NJS_TYPES_VER).tgz + cd $NJS_BUILD_DIR/test/ts && \$(NPM) install + touch $NJS_BUILD_DIR/test/ts/node_modules + +ts_test: $NJS_BUILD_DIR/test/ts/node_modules + cd $NJS_BUILD_DIR/test/ts && \$(NPM) test ts_publish: ts_clean $NJS_BUILD_DIR/njs-types-\$(NJS_TYPES_VER).tgz cd $NJS_BUILD_DIR/ && \$(NPM) publish njs-types-\$(NJS_TYPES_VER).tgz diff -r a3ae0d653f49 -r fa3ffb3a159e auto/sources --- a/auto/sources Thu Oct 29 12:50:05 2020 +0000 +++ b/auto/sources Thu Oct 29 12:51:21 2020 +0000 @@ -73,3 +73,5 @@ NJS_TEST_SRCS=" \ " NJS_TS_SRCS=$(find ts/ -name "*.d.ts" -o -name "*.json") + +NJS_TEST_TS_SRCS=$(find test/ts/ -name "*.ts" -o -name "*.json") diff -r a3ae0d653f49 -r fa3ffb3a159e test/ts/package.json --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/ts/package.json Thu Oct 29 12:51:21 2020 +0000 @@ -0,0 +1,15 @@ +{ + "private": true, + "name": "njs-types-test", + "version": "0.0.0", + "description": "Tests for njs TypeScript type definitions.", + "scripts": { + "test": "tsc" + }, + "author": "NGINX, Inc.", + "license": "BSD-2-Clause", + "devDependencies": { + "njs-types": "file:../../ts", + "typescript": "~4.0.3" + } +} diff -r a3ae0d653f49 -r fa3ffb3a159e test/ts/test.ts --- a/test/ts/test.ts Thu Oct 29 12:50:05 2020 +0000 +++ b/test/ts/test.ts Thu Oct 29 12:51:21 2020 +0000 @@ -1,8 +1,3 @@ -/// -/// -/// -/// - import fs from 'fs'; import qs from 'querystring'; import crypto from 'crypto'; @@ -15,9 +10,9 @@ function http_module(r: NginxHTTPRequest s = 'ordinary string'; bs = String.bytesFrom('000000', 'hex'); - bs = s.toBytes(); + var bs2: NjsByteString | null = s.toBytes(); bs = s.toUTF8(); - bs.fromBytes(null, null); + bs.fromBytes(undefined, undefined); s = bs + ''; @@ -30,29 +25,30 @@ function http_module(r: NginxHTTPRequest bs = r.args.x; bs = r.args[1]; - s = r.args.x.fromUTF8(); + var s2: string | null = r.args.x.fromUTF8(); s = r.args.x + ''; // r.headersIn - r.headersIn['Accept'].fromBytes() == 'dddd'; + r.headersIn['Accept']?.fromBytes() == 'dddd'; // r.headersOut r.headersOut['Content-Type'] = 'text/plain'; // Warning: r.headersOut['Content-Type'] = ['a', 'b']; r.headersOut['Connection'] = undefined; - r.headersOut['Connection'] = null; + + delete r.headersOut['Bar']; r.headersOut['Set-Cookie'] = ['aaa', 'bbb']; r.headersOut['Foo'] = ['aaa', 'bbb']; - r.subrequest('/uri', reply => r.return(200, reply.headersOut["Location"])); + r.subrequest('/uri', reply => r.return(200, reply.headersOut["Location"] ?? '')); // r.log r.log(bs); - r.log(r.headersOut['Connection']); + r.log(r.headersOut['Connection'] ?? ''); // r.variables @@ -64,7 +60,7 @@ function http_module(r: NginxHTTPRequest r.subrequest('/p/sub2', reply => r.return(reply.status)); r.subrequest('/p/sub3', {detached:true}); r.subrequest('/p/sub4', 'a=1&b=2').then(reply => r.return(reply.status, - JSON.stringify(JSON.parse(reply.responseBody)))); + JSON.stringify(JSON.parse(reply.responseBody ?? '')))); } diff -r a3ae0d653f49 -r fa3ffb3a159e test/ts/tsconfig.json --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/ts/tsconfig.json Thu Oct 29 12:51:21 2020 +0000 @@ -0,0 +1,35 @@ +{ + "compilerOptions": { + "target": "ES5", + "module": "es2015", + "lib": [ + "ES2015", + "ES2016.Array.Include", + "ES2017.Object", + "ES2017.String" + ], + "noEmit": true, + "downlevelIteration": true, + + "strict": true, + "noImplicitAny": true, + "strictNullChecks": true, + "strictFunctionTypes": true, + "strictBindCallApply": true, + "strictPropertyInitialization": true, + "noImplicitThis": true, + "alwaysStrict": true, + + "moduleResolution": "node", + "forceConsistentCasingInFileNames": true + }, + "include": [ + "**/*.ts" + ], + "exclude": [ + "./node_modules/**" + ], + "files": [ + "./node_modules/njs-types/ngx_http_js_module.d.ts" + ] +} From jonnybarnes at gmail.com Fri Oct 30 22:21:43 2020 From: jonnybarnes at gmail.com (Jonny Barnes) Date: Fri, 30 Oct 2020 22:21:43 +0000 Subject: HTTP/3 with multiple server blocks Message-ID: Can we do this? First issue is if I add the line `listen 443 http3 resueport` to more than one server {} block the nginx conf test gives the following error: > nginx: [emerg] duplicate listen options for 0.0.0.0:443 in /usr/local/nginx/conf/sites-enabled/legolas:2 > nginx: configuration file /usr/local/nginx/conf/nginx.conf test failed It seemingly works if i only have it for one of my server blocks. But I can?t get my firefox browser to connect with HTTP/3. It does connect to quic.nginx.org over HTTP/3. -------------- next part -------------- An HTML attachment was scrubbed... URL: From harishkumarivaturi at gmail.com Sat Oct 31 12:50:26 2020 From: harishkumarivaturi at gmail.com (HARISH KUMAR Ivaturi) Date: Sat, 31 Oct 2020 13:50:26 +0100 Subject: Nginx HTTP/3 Message-ID: Hi Does anyone know how to include Nginx HTTP/3 support in Devstack? BR Harish Kumar -------------- next part -------------- An HTML attachment was scrubbed... URL: