diff options
author | Valentin Bartenev <vbart@nginx.com> | 2017-05-30 17:12:20 +0300 |
---|---|---|
committer | Valentin Bartenev <vbart@nginx.com> | 2017-05-30 17:12:20 +0300 |
commit | c0bf729c8e7a79d9d7929cb715e3f7237218fcd9 (patch) | |
tree | 4c77611846553c3155f723cb97c94e639aa8cc8f /src/nxt_controller.c | |
parent | f5c3b1c637b4c7c98a9efbc1b99f825dbbe37a51 (diff) | |
download | unit-c0bf729c8e7a79d9d7929cb715e3f7237218fcd9.tar.gz unit-c0bf729c8e7a79d9d7929cb715e3f7237218fcd9.tar.bz2 |
Controller: support for partial PUT and DELETE operations.
Diffstat (limited to 'src/nxt_controller.c')
-rw-r--r-- | src/nxt_controller.c | 203 |
1 files changed, 152 insertions, 51 deletions
diff --git a/src/nxt_controller.c b/src/nxt_controller.c index 15c7b0cd..299242d7 100644 --- a/src/nxt_controller.c +++ b/src/nxt_controller.c @@ -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, 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, nxt_controller_response_t *resp); static nxt_buf_t *nxt_controller_response_body(nxt_controller_response_t *resp, @@ -554,89 +552,192 @@ static void nxt_controller_process_request(nxt_task_t *task, nxt_event_conn_t *c, nxt_controller_request_t *req) { + nxt_int_t rc; 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_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)); if (nxt_str_eq(&req->parser.method, "GET", 3)) { - path.start = req->parser.target_start; + value = nxt_conf_json_get_value(nxt_controller_conf.root, &path); - if (req->parser.args_start != NULL) { - path.length = req->parser.args_start - path.start; + if (value == NULL) { + status = 404; + goto done; + } - } else { - path.length = req->parser.target_end - path.start; + resp.json_value = value; + + status = 200; + goto done; + } + + if (nxt_str_eq(&req->parser.method, "PUT", 3)) { + + mp = nxt_mem_pool_create(512); + + if (nxt_slow_path(mp == NULL)) { + status = 500; + goto done; } - value = nxt_conf_json_get_value(nxt_controller_conf.root, &path); + mbuf = &c->read->mem; - if (value != NULL) { - nxt_str_set(&resp.status_line, "200 OK"); - resp.json_value = value; + value = nxt_conf_json_parse(mbuf->pos, mbuf->free - mbuf->pos, mp); - } else { - nxt_str_set(&resp.status_line, "404 Not Found"); - nxt_str_set(&resp.json_string, - "{ \"error\": \"Requested value doesn't exist\" }"); + if (value == NULL) { + nxt_mem_pool_destroy(mp); + status = 400; + goto done; } - } else if (nxt_str_eq(&req->parser.method, "PUT", 3)) { + if (path.length != 1) { + rc = nxt_conf_json_op_compile(nxt_controller_conf.root, value, + &ops, &path, c->mem_pool); - if (nxt_controller_request_body_parse(task, c, req) == NXT_OK) { + if (rc != NXT_OK) { + if (rc == NXT_DECLINED) { + status = 404; + goto done; + } - nxt_mem_pool_destroy(nxt_controller_conf.pool); - nxt_controller_conf = req->conf; + status = 500; + goto done; + } - nxt_str_set(&resp.status_line, "201 Created"); - nxt_str_set(&resp.json_string, - "{ \"success\": \"Configuration updated\" }"); + value = nxt_conf_json_clone_value(nxt_controller_conf.root, + ops, mp); - } else { - nxt_str_set(&resp.status_line, "400 Bad Request"); - nxt_str_set(&resp.json_string, - "{ \"error\": \"Invalid JSON\" }"); + if (nxt_slow_path(value == NULL)) { + nxt_mem_pool_destroy(mp); + status = 500; + goto done; + } } - } else { - nxt_str_set(&resp.status_line, "405 Method Not Allowed"); - nxt_str_set(&resp.json_string, "{ \"error\": \"Invalid method\" }"); - } + nxt_mem_pool_destroy(nxt_controller_conf.pool); - if (nxt_controller_response(task, c, &resp) != NXT_OK) { - nxt_controller_conn_close(task, c, req); + 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)) { -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; + if (path.length == 1) { + mp = nxt_mem_pool_create(128); - mp = nxt_mem_pool_create(512); + if (nxt_slow_path(mp == NULL)) { + status = 500; + goto done; + } - if (nxt_slow_path(mp == NULL)) { - return NXT_ERROR; - } + value = nxt_conf_json_parse(empty_obj.start, empty_obj.length, mp); - mbuf = &c->read->mem; + } else { + rc = nxt_conf_json_op_compile(nxt_controller_conf.root, NULL, &ops, + &path, c->mem_pool); - value = nxt_conf_json_parse(mbuf->pos, mbuf->free - mbuf->pos, mp); + if (rc != NXT_OK) { + if (rc == NXT_DECLINED) { + status = 404; + goto done; + } - if (value == NULL) { - return NXT_ERROR; + 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; } - r->conf.root = value; - r->conf.pool = mp; + status = 405; - return NXT_OK; +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.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) { + nxt_controller_conn_close(task, c, req); + } } |