Controller: support for partial PUT and DELETE operations.
This commit is contained in:
@@ -10,6 +10,7 @@
|
|||||||
|
|
||||||
|
|
||||||
typedef struct nxt_conf_json_value_s nxt_conf_json_value_t;
|
typedef struct nxt_conf_json_value_s nxt_conf_json_value_t;
|
||||||
|
typedef struct nxt_conf_json_op_s nxt_conf_json_op_t;
|
||||||
|
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
@@ -21,9 +22,17 @@ typedef struct {
|
|||||||
nxt_conf_json_value_t *nxt_conf_json_get_value(nxt_conf_json_value_t *value,
|
nxt_conf_json_value_t *nxt_conf_json_get_value(nxt_conf_json_value_t *value,
|
||||||
nxt_str_t *path);
|
nxt_str_t *path);
|
||||||
nxt_conf_json_value_t *nxt_conf_json_object_get_member(
|
nxt_conf_json_value_t *nxt_conf_json_object_get_member(
|
||||||
nxt_conf_json_value_t *value, u_char *name, size_t length);
|
nxt_conf_json_value_t *value, nxt_str_t *name, uint32_t *index);
|
||||||
|
|
||||||
|
nxt_int_t nxt_conf_json_op_compile(nxt_conf_json_value_t *object,
|
||||||
|
nxt_conf_json_value_t *value, nxt_conf_json_op_t **ops, nxt_str_t *path,
|
||||||
|
nxt_mem_pool_t *pool);
|
||||||
|
nxt_conf_json_value_t *nxt_conf_json_clone_value(nxt_conf_json_value_t *value,
|
||||||
|
nxt_conf_json_op_t *op, nxt_mem_pool_t *pool);
|
||||||
|
|
||||||
nxt_conf_json_value_t *nxt_conf_json_parse(u_char *pos, size_t length,
|
nxt_conf_json_value_t *nxt_conf_json_parse(u_char *pos, size_t length,
|
||||||
nxt_mem_pool_t *pool);
|
nxt_mem_pool_t *pool);
|
||||||
|
|
||||||
uintptr_t nxt_conf_json_print_value(u_char *pos, nxt_conf_json_value_t *value,
|
uintptr_t nxt_conf_json_print_value(u_char *pos, nxt_conf_json_value_t *value,
|
||||||
nxt_conf_json_pretty_t *pretty);
|
nxt_conf_json_pretty_t *pretty);
|
||||||
|
|
||||||
|
|||||||
@@ -13,6 +13,9 @@
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
#define NXT_CONF_JSON_STR_SIZE 14
|
||||||
|
|
||||||
|
|
||||||
typedef enum {
|
typedef enum {
|
||||||
NXT_CONF_JSON_NULL = 0,
|
NXT_CONF_JSON_NULL = 0,
|
||||||
NXT_CONF_JSON_BOOLEAN,
|
NXT_CONF_JSON_BOOLEAN,
|
||||||
@@ -25,6 +28,14 @@ typedef enum {
|
|||||||
} nxt_conf_json_type_t;
|
} nxt_conf_json_type_t;
|
||||||
|
|
||||||
|
|
||||||
|
typedef enum {
|
||||||
|
NXT_CONF_JSON_OP_PASS = 0,
|
||||||
|
NXT_CONF_JSON_OP_CREATE,
|
||||||
|
NXT_CONF_JSON_OP_REPLACE,
|
||||||
|
NXT_CONF_JSON_OP_DELETE,
|
||||||
|
} nxt_conf_json_op_action_t;
|
||||||
|
|
||||||
|
|
||||||
typedef struct nxt_conf_json_array_s nxt_conf_json_array_t;
|
typedef struct nxt_conf_json_array_s nxt_conf_json_array_t;
|
||||||
typedef struct nxt_conf_json_object_s nxt_conf_json_object_t;
|
typedef struct nxt_conf_json_object_s nxt_conf_json_object_t;
|
||||||
|
|
||||||
@@ -34,7 +45,7 @@ struct nxt_conf_json_value_s {
|
|||||||
uint32_t boolean; /* 1 bit. */
|
uint32_t boolean; /* 1 bit. */
|
||||||
int64_t integer;
|
int64_t integer;
|
||||||
/* double number; */
|
/* double number; */
|
||||||
u_char str[15];
|
u_char str[1 + NXT_CONF_JSON_STR_SIZE];
|
||||||
nxt_str_t *string;
|
nxt_str_t *string;
|
||||||
nxt_conf_json_array_t *array;
|
nxt_conf_json_array_t *array;
|
||||||
nxt_conf_json_object_t *object;
|
nxt_conf_json_object_t *object;
|
||||||
@@ -62,6 +73,14 @@ struct nxt_conf_json_object_s {
|
|||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
struct nxt_conf_json_op_s {
|
||||||
|
uint32_t index;
|
||||||
|
uint32_t action; /* nxt_conf_json_op_action_t */
|
||||||
|
void *ctx;
|
||||||
|
nxt_conf_json_op_t *next;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
static u_char *nxt_conf_json_skip_space(u_char *pos, u_char *end);
|
static u_char *nxt_conf_json_skip_space(u_char *pos, u_char *end);
|
||||||
static u_char *nxt_conf_json_parse_value(u_char *pos, u_char *end,
|
static u_char *nxt_conf_json_parse_value(u_char *pos, u_char *end,
|
||||||
nxt_conf_json_value_t *value, nxt_mem_pool_t *pool);
|
nxt_conf_json_value_t *value, nxt_mem_pool_t *pool);
|
||||||
@@ -78,6 +97,10 @@ static u_char *nxt_conf_json_parse_string(u_char *pos, u_char *end,
|
|||||||
static u_char *nxt_conf_json_parse_number(u_char *pos, u_char *end,
|
static u_char *nxt_conf_json_parse_number(u_char *pos, u_char *end,
|
||||||
nxt_conf_json_value_t *value, nxt_mem_pool_t *pool);
|
nxt_conf_json_value_t *value, nxt_mem_pool_t *pool);
|
||||||
|
|
||||||
|
static nxt_int_t nxt_conf_json_copy_value(nxt_conf_json_value_t *dst,
|
||||||
|
nxt_conf_json_value_t *src, nxt_conf_json_op_t *op, nxt_mem_pool_t *pool);
|
||||||
|
static nxt_int_t nxt_conf_json_copy_object(nxt_conf_json_value_t *dst,
|
||||||
|
nxt_conf_json_value_t *src, nxt_conf_json_op_t *op, nxt_mem_pool_t *pool);
|
||||||
|
|
||||||
static uintptr_t nxt_conf_json_print_integer(u_char *pos,
|
static uintptr_t nxt_conf_json_print_integer(u_char *pos,
|
||||||
nxt_conf_json_value_t *value);
|
nxt_conf_json_value_t *value);
|
||||||
@@ -107,40 +130,75 @@ nxt_conf_json_indentation(u_char *pos, nxt_conf_json_pretty_t *pretty)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
u_char *start;
|
||||||
|
u_char *end;
|
||||||
|
nxt_bool_t last;
|
||||||
|
} nxt_conf_path_parse_t;
|
||||||
|
|
||||||
|
|
||||||
|
static void nxt_conf_json_path_next_token(nxt_conf_path_parse_t *parse,
|
||||||
|
nxt_str_t *token);
|
||||||
|
|
||||||
|
|
||||||
nxt_conf_json_value_t *
|
nxt_conf_json_value_t *
|
||||||
nxt_conf_json_get_value(nxt_conf_json_value_t *value, nxt_str_t *path)
|
nxt_conf_json_get_value(nxt_conf_json_value_t *value, nxt_str_t *path)
|
||||||
{
|
{
|
||||||
u_char *p, *start, *end;
|
nxt_str_t token;
|
||||||
|
nxt_conf_path_parse_t parse;
|
||||||
|
|
||||||
p = path->start;
|
parse.start = path->start;
|
||||||
end = p + path->length;
|
parse.end = path->start + path->length;
|
||||||
|
parse.last = 0;
|
||||||
|
|
||||||
if (p != end && end[-1] == '/') {
|
do {
|
||||||
end--;
|
nxt_conf_json_path_next_token(&parse, &token);
|
||||||
}
|
|
||||||
|
|
||||||
while (p != end) {
|
if (token.length == 0) {
|
||||||
start = p + 1;
|
|
||||||
p = start;
|
|
||||||
|
|
||||||
while (p != end && *p != '/') {
|
if (parse.last) {
|
||||||
p++;
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
value = nxt_conf_json_object_get_member(value, start, p - start);
|
value = nxt_conf_json_object_get_member(value, &token, NULL);
|
||||||
|
|
||||||
if (value == NULL) {
|
if (value == NULL) {
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
} while (parse.last == 0);
|
||||||
|
|
||||||
return value;
|
return value;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static void
|
||||||
|
nxt_conf_json_path_next_token(nxt_conf_path_parse_t *parse, nxt_str_t *token)
|
||||||
|
{
|
||||||
|
u_char *p, *end;
|
||||||
|
|
||||||
|
end = parse->end;
|
||||||
|
p = parse->start + 1;
|
||||||
|
|
||||||
|
token->start = p;
|
||||||
|
|
||||||
|
while (p < end && *p != '/') {
|
||||||
|
p++;
|
||||||
|
}
|
||||||
|
|
||||||
|
parse->start = p;
|
||||||
|
parse->last = (p >= end);
|
||||||
|
|
||||||
|
token->length = p - token->start;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
nxt_conf_json_value_t *
|
nxt_conf_json_value_t *
|
||||||
nxt_conf_json_object_get_member(nxt_conf_json_value_t *value, u_char *name,
|
nxt_conf_json_object_get_member(nxt_conf_json_value_t *value, nxt_str_t *name,
|
||||||
size_t length)
|
uint32_t *index)
|
||||||
{
|
{
|
||||||
nxt_str_t str;
|
nxt_str_t str;
|
||||||
nxt_uint_t n;
|
nxt_uint_t n;
|
||||||
@@ -164,7 +222,12 @@ nxt_conf_json_object_get_member(nxt_conf_json_value_t *value, u_char *name,
|
|||||||
str = *member->name.u.string;
|
str = *member->name.u.string;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (nxt_str_eq(&str, name, length)) {
|
if (nxt_strstr_eq(&str, name)) {
|
||||||
|
|
||||||
|
if (index != NULL) {
|
||||||
|
*index = n;
|
||||||
|
}
|
||||||
|
|
||||||
return &member->value;
|
return &member->value;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -173,6 +236,301 @@ nxt_conf_json_object_get_member(nxt_conf_json_value_t *value, u_char *name,
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
nxt_int_t
|
||||||
|
nxt_conf_json_op_compile(nxt_conf_json_value_t *object,
|
||||||
|
nxt_conf_json_value_t *value, nxt_conf_json_op_t **ops, nxt_str_t *path,
|
||||||
|
nxt_mem_pool_t *pool)
|
||||||
|
{
|
||||||
|
nxt_str_t token;
|
||||||
|
nxt_conf_json_op_t *op, **parent;
|
||||||
|
nxt_conf_path_parse_t parse;
|
||||||
|
nxt_conf_json_obj_member_t *member;
|
||||||
|
|
||||||
|
parse.start = path->start;
|
||||||
|
parse.end = path->start + path->length;
|
||||||
|
parse.last = 0;
|
||||||
|
|
||||||
|
parent = ops;
|
||||||
|
|
||||||
|
for ( ;; ) {
|
||||||
|
op = nxt_mem_zalloc(pool, sizeof(nxt_conf_json_op_t));
|
||||||
|
if (nxt_slow_path(op == NULL)) {
|
||||||
|
return NXT_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
*parent = op;
|
||||||
|
parent = (nxt_conf_json_op_t **) &op->ctx;
|
||||||
|
|
||||||
|
nxt_conf_json_path_next_token(&parse, &token);
|
||||||
|
|
||||||
|
object = nxt_conf_json_object_get_member(object, &token, &op->index);
|
||||||
|
|
||||||
|
if (parse.last) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (object == NULL) {
|
||||||
|
return NXT_DECLINED;
|
||||||
|
}
|
||||||
|
|
||||||
|
op->action = NXT_CONF_JSON_OP_PASS;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (value == NULL) {
|
||||||
|
|
||||||
|
if (object == NULL) {
|
||||||
|
return NXT_DECLINED;
|
||||||
|
}
|
||||||
|
|
||||||
|
op->action = NXT_CONF_JSON_OP_DELETE;
|
||||||
|
|
||||||
|
return NXT_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (object == NULL) {
|
||||||
|
|
||||||
|
member = nxt_mem_zalloc(pool, sizeof(nxt_conf_json_obj_member_t));
|
||||||
|
if (nxt_slow_path(member == NULL)) {
|
||||||
|
return NXT_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (token.length > NXT_CONF_JSON_STR_SIZE) {
|
||||||
|
|
||||||
|
member->name.u.string = nxt_mem_alloc(pool, sizeof(nxt_str_t));
|
||||||
|
if (nxt_slow_path(member->name.u.string == NULL)) {
|
||||||
|
return NXT_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
*member->name.u.string = token;
|
||||||
|
member->name.type = NXT_CONF_JSON_STRING;
|
||||||
|
|
||||||
|
} else {
|
||||||
|
member->name.u.str[0] = token.length;
|
||||||
|
nxt_memcpy(&member->name.u.str[1], token.start, token.length);
|
||||||
|
|
||||||
|
member->name.type = NXT_CONF_JSON_SHORT_STRING;
|
||||||
|
}
|
||||||
|
|
||||||
|
member->value = *value;
|
||||||
|
|
||||||
|
op->action = NXT_CONF_JSON_OP_CREATE;
|
||||||
|
op->ctx = member;
|
||||||
|
|
||||||
|
} else {
|
||||||
|
op->action = NXT_CONF_JSON_OP_REPLACE;
|
||||||
|
op->ctx = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
return NXT_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
nxt_conf_json_value_t *
|
||||||
|
nxt_conf_json_clone_value(nxt_conf_json_value_t *value, nxt_conf_json_op_t *op,
|
||||||
|
nxt_mem_pool_t *pool)
|
||||||
|
{
|
||||||
|
nxt_conf_json_value_t *copy;
|
||||||
|
|
||||||
|
copy = nxt_mem_alloc(pool, sizeof(nxt_conf_json_value_t));
|
||||||
|
if (nxt_slow_path(copy == NULL)) {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (nxt_slow_path(nxt_conf_json_copy_value(copy, value, op, pool)
|
||||||
|
!= NXT_OK))
|
||||||
|
{
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
return copy;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static nxt_int_t
|
||||||
|
nxt_conf_json_copy_value(nxt_conf_json_value_t *dst, nxt_conf_json_value_t *src,
|
||||||
|
nxt_conf_json_op_t *op, nxt_mem_pool_t *pool)
|
||||||
|
{
|
||||||
|
size_t size;
|
||||||
|
nxt_int_t rc;
|
||||||
|
nxt_uint_t n;
|
||||||
|
|
||||||
|
if (op != NULL && src->type != NXT_CONF_JSON_OBJECT) {
|
||||||
|
return NXT_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
dst->type = src->type;
|
||||||
|
|
||||||
|
switch (src->type) {
|
||||||
|
|
||||||
|
case NXT_CONF_JSON_STRING:
|
||||||
|
|
||||||
|
dst->u.string = nxt_str_dup(pool, NULL, src->u.string);
|
||||||
|
|
||||||
|
if (nxt_slow_path(dst->u.string == NULL)) {
|
||||||
|
return NXT_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
break;
|
||||||
|
|
||||||
|
case NXT_CONF_JSON_ARRAY:
|
||||||
|
|
||||||
|
size = sizeof(nxt_conf_json_array_t)
|
||||||
|
+ src->u.array->count * sizeof(nxt_conf_json_value_t);
|
||||||
|
|
||||||
|
dst->u.array = nxt_mem_alloc(pool, size);
|
||||||
|
if (nxt_slow_path(dst->u.array == NULL)) {
|
||||||
|
return NXT_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
dst->u.array->count = src->u.array->count;
|
||||||
|
|
||||||
|
for (n = 0; n < src->u.array->count; n++) {
|
||||||
|
rc = nxt_conf_json_copy_value(&dst->u.array->elements[n],
|
||||||
|
&src->u.array->elements[n],
|
||||||
|
NULL, pool);
|
||||||
|
|
||||||
|
if (nxt_slow_path(rc != NXT_OK)) {
|
||||||
|
return NXT_ERROR;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
break;
|
||||||
|
|
||||||
|
case NXT_CONF_JSON_OBJECT:
|
||||||
|
return nxt_conf_json_copy_object(dst, src, op, pool);
|
||||||
|
|
||||||
|
default:
|
||||||
|
dst->u = src->u;
|
||||||
|
}
|
||||||
|
|
||||||
|
return NXT_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static nxt_int_t
|
||||||
|
nxt_conf_json_copy_object(nxt_conf_json_value_t *dst,
|
||||||
|
nxt_conf_json_value_t *src, nxt_conf_json_op_t *op, nxt_mem_pool_t *pool)
|
||||||
|
{
|
||||||
|
size_t size;
|
||||||
|
nxt_int_t rc;
|
||||||
|
nxt_uint_t s, d, count, index;
|
||||||
|
nxt_conf_json_op_t *pass_op;
|
||||||
|
nxt_conf_json_value_t *value;
|
||||||
|
nxt_conf_json_obj_member_t *member;
|
||||||
|
|
||||||
|
count = src->u.object->count;
|
||||||
|
|
||||||
|
if (op != NULL) {
|
||||||
|
if (op->action == NXT_CONF_JSON_OP_CREATE) {
|
||||||
|
count++;
|
||||||
|
|
||||||
|
} else if (op->action == NXT_CONF_JSON_OP_DELETE) {
|
||||||
|
count--;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
size = sizeof(nxt_conf_json_object_t)
|
||||||
|
+ count * sizeof(nxt_conf_json_obj_member_t);
|
||||||
|
|
||||||
|
dst->u.object = nxt_mem_alloc(pool, size);
|
||||||
|
if (nxt_slow_path(dst->u.object == NULL)) {
|
||||||
|
return NXT_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
dst->u.object->count = count;
|
||||||
|
|
||||||
|
s = 0;
|
||||||
|
d = 0;
|
||||||
|
|
||||||
|
pass_op = NULL;
|
||||||
|
|
||||||
|
do {
|
||||||
|
if (pass_op == NULL) {
|
||||||
|
index = (op == NULL || op->action == NXT_CONF_JSON_OP_CREATE)
|
||||||
|
? src->u.object->count : op->index;
|
||||||
|
}
|
||||||
|
|
||||||
|
while (s != index) {
|
||||||
|
rc = nxt_conf_json_copy_value(&dst->u.object->members[d].name,
|
||||||
|
&src->u.object->members[s].name,
|
||||||
|
NULL, pool);
|
||||||
|
|
||||||
|
if (nxt_slow_path(rc != NXT_OK)) {
|
||||||
|
return NXT_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
rc = nxt_conf_json_copy_value(&dst->u.object->members[d].value,
|
||||||
|
&src->u.object->members[s].value,
|
||||||
|
pass_op, pool);
|
||||||
|
|
||||||
|
if (nxt_slow_path(rc != NXT_OK)) {
|
||||||
|
return NXT_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
s++;
|
||||||
|
d++;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (pass_op != NULL) {
|
||||||
|
pass_op = NULL;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (op != NULL) {
|
||||||
|
switch (op->action) {
|
||||||
|
case NXT_CONF_JSON_OP_PASS:
|
||||||
|
pass_op = op->ctx;
|
||||||
|
index++;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case NXT_CONF_JSON_OP_CREATE:
|
||||||
|
member = op->ctx;
|
||||||
|
|
||||||
|
rc = nxt_conf_json_copy_value(&dst->u.object->members[d].name,
|
||||||
|
&member->name, NULL, pool);
|
||||||
|
|
||||||
|
if (nxt_slow_path(rc != NXT_OK)) {
|
||||||
|
return NXT_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
dst->u.object->members[d].value = member->value;
|
||||||
|
|
||||||
|
d++;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case NXT_CONF_JSON_OP_REPLACE:
|
||||||
|
rc = nxt_conf_json_copy_value(&dst->u.object->members[d].name,
|
||||||
|
&src->u.object->members[s].name,
|
||||||
|
NULL, pool);
|
||||||
|
|
||||||
|
if (nxt_slow_path(rc != NXT_OK)) {
|
||||||
|
return NXT_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
value = op->ctx;
|
||||||
|
|
||||||
|
dst->u.object->members[d].value = *value;
|
||||||
|
|
||||||
|
s++;
|
||||||
|
d++;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case NXT_CONF_JSON_OP_DELETE:
|
||||||
|
s++;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
op = op->next;
|
||||||
|
}
|
||||||
|
|
||||||
|
} while (d != count);
|
||||||
|
|
||||||
|
dst->type = src->type;
|
||||||
|
|
||||||
|
return NXT_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
nxt_conf_json_value_t *
|
nxt_conf_json_value_t *
|
||||||
nxt_conf_json_parse(u_char *pos, size_t length, nxt_mem_pool_t *pool)
|
nxt_conf_json_parse(u_char *pos, size_t length, nxt_mem_pool_t *pool)
|
||||||
{
|
{
|
||||||
@@ -672,7 +1030,7 @@ nxt_conf_json_parse_string(u_char *pos, u_char *end,
|
|||||||
|
|
||||||
size = last - pos - surplus;
|
size = last - pos - surplus;
|
||||||
|
|
||||||
if (size > 14) {
|
if (size > NXT_CONF_JSON_STR_SIZE) {
|
||||||
value->type = NXT_CONF_JSON_STRING;
|
value->type = NXT_CONF_JSON_STRING;
|
||||||
value->u.string = nxt_str_alloc(pool, size);
|
value->u.string = nxt_str_alloc(pool, size);
|
||||||
|
|
||||||
@@ -775,7 +1133,7 @@ nxt_conf_json_parse_string(u_char *pos, u_char *end,
|
|||||||
|
|
||||||
} while (pos != last);
|
} while (pos != last);
|
||||||
|
|
||||||
if (size > 14) {
|
if (size > NXT_CONF_JSON_STR_SIZE) {
|
||||||
value->u.string->length = s - value->u.string->start;
|
value->u.string->length = s - value->u.string->start;
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
|
|||||||
@@ -55,8 +55,6 @@ static nxt_int_t nxt_controller_request_content_length(void *ctx,
|
|||||||
|
|
||||||
static void nxt_controller_process_request(nxt_task_t *task,
|
static void nxt_controller_process_request(nxt_task_t *task,
|
||||||
nxt_event_conn_t *c, nxt_controller_request_t *r);
|
nxt_event_conn_t *c, nxt_controller_request_t *r);
|
||||||
static nxt_int_t nxt_controller_request_body_parse(nxt_task_t *task,
|
|
||||||
nxt_event_conn_t *c, nxt_controller_request_t *r);
|
|
||||||
static nxt_int_t nxt_controller_response(nxt_task_t *task, nxt_event_conn_t *c,
|
static nxt_int_t nxt_controller_response(nxt_task_t *task, nxt_event_conn_t *c,
|
||||||
nxt_controller_response_t *resp);
|
nxt_controller_response_t *resp);
|
||||||
static nxt_buf_t *nxt_controller_response_body(nxt_controller_response_t *resp,
|
static nxt_buf_t *nxt_controller_response_body(nxt_controller_response_t *resp,
|
||||||
@@ -554,55 +552,187 @@ static void
|
|||||||
nxt_controller_process_request(nxt_task_t *task, nxt_event_conn_t *c,
|
nxt_controller_process_request(nxt_task_t *task, nxt_event_conn_t *c,
|
||||||
nxt_controller_request_t *req)
|
nxt_controller_request_t *req)
|
||||||
{
|
{
|
||||||
|
nxt_int_t rc;
|
||||||
nxt_str_t path;
|
nxt_str_t path;
|
||||||
|
nxt_uint_t status;
|
||||||
|
nxt_buf_mem_t *mbuf;
|
||||||
|
nxt_mem_pool_t *mp;
|
||||||
|
nxt_conf_json_op_t *ops;
|
||||||
nxt_conf_json_value_t *value;
|
nxt_conf_json_value_t *value;
|
||||||
nxt_controller_response_t resp;
|
nxt_controller_response_t resp;
|
||||||
|
|
||||||
|
static const nxt_str_t empty_obj = nxt_string("{}");
|
||||||
|
|
||||||
|
path.start = req->parser.target_start;
|
||||||
|
|
||||||
|
if (req->parser.args_start != NULL) {
|
||||||
|
path.length = req->parser.args_start - path.start;
|
||||||
|
|
||||||
|
} else {
|
||||||
|
path.length = req->parser.target_end - path.start;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (path.length > 1 && path.start[path.length - 1] == '/') {
|
||||||
|
path.length--;
|
||||||
|
}
|
||||||
|
|
||||||
nxt_memzero(&resp, sizeof(nxt_controller_response_t));
|
nxt_memzero(&resp, sizeof(nxt_controller_response_t));
|
||||||
|
|
||||||
if (nxt_str_eq(&req->parser.method, "GET", 3)) {
|
if (nxt_str_eq(&req->parser.method, "GET", 3)) {
|
||||||
|
|
||||||
path.start = req->parser.target_start;
|
|
||||||
|
|
||||||
if (req->parser.args_start != NULL) {
|
|
||||||
path.length = req->parser.args_start - path.start;
|
|
||||||
|
|
||||||
} else {
|
|
||||||
path.length = req->parser.target_end - path.start;
|
|
||||||
}
|
|
||||||
|
|
||||||
value = nxt_conf_json_get_value(nxt_controller_conf.root, &path);
|
value = nxt_conf_json_get_value(nxt_controller_conf.root, &path);
|
||||||
|
|
||||||
if (value != NULL) {
|
if (value == NULL) {
|
||||||
nxt_str_set(&resp.status_line, "200 OK");
|
status = 404;
|
||||||
resp.json_value = value;
|
goto done;
|
||||||
|
|
||||||
} else {
|
|
||||||
nxt_str_set(&resp.status_line, "404 Not Found");
|
|
||||||
nxt_str_set(&resp.json_string,
|
|
||||||
"{ \"error\": \"Requested value doesn't exist\" }");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
} else if (nxt_str_eq(&req->parser.method, "PUT", 3)) {
|
resp.json_value = value;
|
||||||
|
|
||||||
if (nxt_controller_request_body_parse(task, c, req) == NXT_OK) {
|
status = 200;
|
||||||
|
goto done;
|
||||||
|
}
|
||||||
|
|
||||||
nxt_mem_pool_destroy(nxt_controller_conf.pool);
|
if (nxt_str_eq(&req->parser.method, "PUT", 3)) {
|
||||||
nxt_controller_conf = req->conf;
|
|
||||||
|
|
||||||
nxt_str_set(&resp.status_line, "201 Created");
|
mp = nxt_mem_pool_create(512);
|
||||||
nxt_str_set(&resp.json_string,
|
|
||||||
"{ \"success\": \"Configuration updated\" }");
|
|
||||||
|
|
||||||
} else {
|
if (nxt_slow_path(mp == NULL)) {
|
||||||
nxt_str_set(&resp.status_line, "400 Bad Request");
|
status = 500;
|
||||||
nxt_str_set(&resp.json_string,
|
goto done;
|
||||||
"{ \"error\": \"Invalid JSON\" }");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
} else {
|
mbuf = &c->read->mem;
|
||||||
|
|
||||||
|
value = nxt_conf_json_parse(mbuf->pos, mbuf->free - mbuf->pos, mp);
|
||||||
|
|
||||||
|
if (value == NULL) {
|
||||||
|
nxt_mem_pool_destroy(mp);
|
||||||
|
status = 400;
|
||||||
|
goto done;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (path.length != 1) {
|
||||||
|
rc = nxt_conf_json_op_compile(nxt_controller_conf.root, value,
|
||||||
|
&ops, &path, c->mem_pool);
|
||||||
|
|
||||||
|
if (rc != NXT_OK) {
|
||||||
|
if (rc == NXT_DECLINED) {
|
||||||
|
status = 404;
|
||||||
|
goto done;
|
||||||
|
}
|
||||||
|
|
||||||
|
status = 500;
|
||||||
|
goto done;
|
||||||
|
}
|
||||||
|
|
||||||
|
value = nxt_conf_json_clone_value(nxt_controller_conf.root,
|
||||||
|
ops, mp);
|
||||||
|
|
||||||
|
if (nxt_slow_path(value == NULL)) {
|
||||||
|
nxt_mem_pool_destroy(mp);
|
||||||
|
status = 500;
|
||||||
|
goto done;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
nxt_mem_pool_destroy(nxt_controller_conf.pool);
|
||||||
|
|
||||||
|
nxt_controller_conf.root = value;
|
||||||
|
nxt_controller_conf.pool = mp;
|
||||||
|
|
||||||
|
nxt_str_set(&resp.json_string, "{ \"success\": \"Updated.\" }");
|
||||||
|
|
||||||
|
status = 200;
|
||||||
|
goto done;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (nxt_str_eq(&req->parser.method, "DELETE", 6)) {
|
||||||
|
|
||||||
|
if (path.length == 1) {
|
||||||
|
mp = nxt_mem_pool_create(128);
|
||||||
|
|
||||||
|
if (nxt_slow_path(mp == NULL)) {
|
||||||
|
status = 500;
|
||||||
|
goto done;
|
||||||
|
}
|
||||||
|
|
||||||
|
value = nxt_conf_json_parse(empty_obj.start, empty_obj.length, mp);
|
||||||
|
|
||||||
|
} else {
|
||||||
|
rc = nxt_conf_json_op_compile(nxt_controller_conf.root, NULL, &ops,
|
||||||
|
&path, c->mem_pool);
|
||||||
|
|
||||||
|
if (rc != NXT_OK) {
|
||||||
|
if (rc == NXT_DECLINED) {
|
||||||
|
status = 404;
|
||||||
|
goto done;
|
||||||
|
}
|
||||||
|
|
||||||
|
status = 500;
|
||||||
|
goto done;
|
||||||
|
}
|
||||||
|
|
||||||
|
mp = nxt_mem_pool_create(512);
|
||||||
|
|
||||||
|
if (nxt_slow_path(mp == NULL)) {
|
||||||
|
status = 500;
|
||||||
|
goto done;
|
||||||
|
}
|
||||||
|
|
||||||
|
value = nxt_conf_json_clone_value(nxt_controller_conf.root,
|
||||||
|
ops, mp);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (nxt_slow_path(value == NULL)) {
|
||||||
|
nxt_mem_pool_destroy(mp);
|
||||||
|
status = 500;
|
||||||
|
goto done;
|
||||||
|
}
|
||||||
|
|
||||||
|
nxt_mem_pool_destroy(nxt_controller_conf.pool);
|
||||||
|
|
||||||
|
nxt_controller_conf.root = value;
|
||||||
|
nxt_controller_conf.pool = mp;
|
||||||
|
|
||||||
|
nxt_str_set(&resp.json_string, "{ \"success\": \"Deleted.\" }");
|
||||||
|
|
||||||
|
status = 200;
|
||||||
|
goto done;
|
||||||
|
}
|
||||||
|
|
||||||
|
status = 405;
|
||||||
|
|
||||||
|
done:
|
||||||
|
|
||||||
|
switch (status) {
|
||||||
|
|
||||||
|
case 200:
|
||||||
|
nxt_str_set(&resp.status_line, "200 OK");
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 400:
|
||||||
|
nxt_str_set(&resp.status_line, "400 Bad Request");
|
||||||
|
nxt_str_set(&resp.json_string,
|
||||||
|
"{ \"error\": \"Invalid JSON.\" }");
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 404:
|
||||||
|
nxt_str_set(&resp.status_line, "404 Not Found");
|
||||||
|
nxt_str_set(&resp.json_string,
|
||||||
|
"{ \"error\": \"Value doesn't exist.\" }");
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 405:
|
||||||
nxt_str_set(&resp.status_line, "405 Method Not Allowed");
|
nxt_str_set(&resp.status_line, "405 Method Not Allowed");
|
||||||
nxt_str_set(&resp.json_string, "{ \"error\": \"Invalid method\" }");
|
nxt_str_set(&resp.json_string, "{ \"error\": \"Invalid method.\" }");
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 500:
|
||||||
|
nxt_str_set(&resp.status_line, "500 Internal Server Error");
|
||||||
|
nxt_str_set(&resp.json_string,
|
||||||
|
"{ \"error\": \"Memory allocation failed.\" }");
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (nxt_controller_response(task, c, &resp) != NXT_OK) {
|
if (nxt_controller_response(task, c, &resp) != NXT_OK) {
|
||||||
@@ -611,35 +741,6 @@ nxt_controller_process_request(nxt_task_t *task, nxt_event_conn_t *c,
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static nxt_int_t
|
|
||||||
nxt_controller_request_body_parse(nxt_task_t *task, nxt_event_conn_t *c,
|
|
||||||
nxt_controller_request_t *r)
|
|
||||||
{
|
|
||||||
nxt_buf_mem_t *mbuf;
|
|
||||||
nxt_mem_pool_t *mp;
|
|
||||||
nxt_conf_json_value_t *value;
|
|
||||||
|
|
||||||
mp = nxt_mem_pool_create(512);
|
|
||||||
|
|
||||||
if (nxt_slow_path(mp == NULL)) {
|
|
||||||
return NXT_ERROR;
|
|
||||||
}
|
|
||||||
|
|
||||||
mbuf = &c->read->mem;
|
|
||||||
|
|
||||||
value = nxt_conf_json_parse(mbuf->pos, mbuf->free - mbuf->pos, mp);
|
|
||||||
|
|
||||||
if (value == NULL) {
|
|
||||||
return NXT_ERROR;
|
|
||||||
}
|
|
||||||
|
|
||||||
r->conf.root = value;
|
|
||||||
r->conf.pool = mp;
|
|
||||||
|
|
||||||
return NXT_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
static nxt_int_t
|
static nxt_int_t
|
||||||
nxt_controller_response(nxt_task_t *task, nxt_event_conn_t *c,
|
nxt_controller_response(nxt_task_t *task, nxt_event_conn_t *c,
|
||||||
nxt_controller_response_t *resp)
|
nxt_controller_response_t *resp)
|
||||||
|
|||||||
Reference in New Issue
Block a user