diff options
author | Sergey Poznyakoff <gray@gnu.org.ua> | 2016-01-04 14:08:29 +0200 |
---|---|---|
committer | Sergey Poznyakoff <gray@gnu.org.ua> | 2016-01-04 14:08:29 +0200 |
commit | 2c03055b8ed023e7d8d65f2dbd51cd128040fcfb (patch) | |
tree | 7792b90c2a99e1910ffbdd2f277b68f63190f0c0 /src/ctl.c | |
parent | 2782ae034e51d5e9c74a9b1f2c6e6c452bd83243 (diff) | |
download | pies-2c03055b8ed023e7d8d65f2dbd51cd128040fcfb.tar.gz pies-2c03055b8ed023e7d8d65f2dbd51cd128040fcfb.tar.bz2 |
Redo URI handling.
* src/ctl.c (res_instance)
(res_programs): Take partial URI as argument (instead of full
URI split on path delimiter)
(ctlio_resource): New member uri_len; Change signature of handler.
(find_resource): Compare URI prefix.
(ctlio_do_command): Redo URI parsing. Improve error checking.
* src/piesctl.c (shttp_print_error): New function.
(shttp_fatal): Print error on 404 and 409 responses.
Diffstat (limited to 'src/ctl.c')
-rw-r--r-- | src/ctl.c | 147 |
1 files changed, 89 insertions, 58 deletions
@@ -888,5 +888,5 @@ method_decode (char const *method) -static void res_instance (struct ctlio *, enum http_method, size_t, char **, +static void res_instance (struct ctlio *, enum http_method, char const *, struct json_value *); -static void res_programs (struct ctlio *, enum http_method, size_t, char **, +static void res_programs (struct ctlio *, enum http_method, char const *, struct json_value *); @@ -895,7 +895,7 @@ struct ctlio_resource { - char *uri; + char const *uri; + size_t uri_len; int states; void (*handler) (struct ctlio *, enum http_method, - size_t pathc, char **pathv, - struct json_value *); + char const *uri, struct json_value *); }; @@ -903,5 +903,7 @@ struct ctlio_resource static struct ctlio_resource restab[] = { - { "instance", CTL_ADMIN_STATE, res_instance }, - { "programs", CTL_ADMIN_STATE|CTL_USER_STATE, res_programs }, +#define S(s) #s, (sizeof (#s)-1) + { S(/instance), CTL_ADMIN_STATE, res_instance }, + { S(/programs), CTL_ADMIN_STATE|CTL_USER_STATE, res_programs }, { NULL } +#undef S }; @@ -912,6 +914,26 @@ find_resource (struct ctlio *io, const char *endpoint) struct ctlio_resource *p; + size_t len = strlen (endpoint); + + if (len == 0) + return NULL; + + if (endpoint[len-1] == '/') + --len; for (p = restab; p->uri; p++) - if (strcmp (p->uri, endpoint) == 0) + if (len >= p->uri_len && memcmp (p->uri, endpoint, p->uri_len) == 0 + && (endpoint[p->uri_len] == 0 || endpoint[p->uri_len] == '/')) + return p; + return NULL; +} + +static char * +json_extract (char *uri) +{ + char *p = strrchr (uri, '/'); + if (p && strchr ("\"{[", p[1])) + { + *p++ = 0; return p; + } return NULL; @@ -919,4 +941,14 @@ find_resource (struct ctlio *io, const char *endpoint) +static size_t +delim_count (char const *str, int delim) +{ + size_t i = 0; + for (; *str; str++) + if (*str == delim) + ++i; + return i; +} + static void -ctlio_do_command (struct ctlio *io, struct wordsplit *uri) +ctlio_do_command (struct ctlio *io) { @@ -926,2 +958,4 @@ ctlio_do_command (struct ctlio *io, struct wordsplit *uri) struct json_value *json; + char *uri = io->input.input_uri; + char *json_query = NULL; @@ -960,9 +994,3 @@ ctlio_do_command (struct ctlio *io, struct wordsplit *uri) - if (uri->ws_wordc < 1) - { - ctlio_reply (io, 404, NULL); - return; - } - - res = find_resource (io, uri->ws_wordv[0]); + res = find_resource (io, uri); if (!res) @@ -972,2 +1000,14 @@ ctlio_do_command (struct ctlio *io, struct wordsplit *uri) } + uri += res->uri_len; + if (uri[0]) + { + json_query = json_extract (uri); + if (delim_count (uri, '/') > 1) + { + ctlio_reply (io, 404, "resource not found"); + return; + } + } + if (!uri[0]) + uri = NULL; @@ -986,2 +1026,8 @@ ctlio_do_command (struct ctlio *io, struct wordsplit *uri) { + if (json_query) + { + ctlio_reply (io, 400, "JSON query supplied twice"); + return; + } + json = json_parse_string (ctlbuf_peek (&io->input.ibuf), @@ -990,17 +1036,23 @@ ctlio_do_command (struct ctlio *io, struct wordsplit *uri) { - ctlio_reply (io, 400, NULL); + ctlio_reply (io, 400, "JSON error: %s", json_err_diag); //FIXME: Reply json + return; } } - else if (method != METH_POST - && uri->ws_wordc > 1 - && strchr ("\"{[", uri->ws_wordv[uri->ws_wordc-1][0])) + else if (json_query) { - json = json_parse_string (uri->ws_wordv[uri->ws_wordc-1], - strlen (uri->ws_wordv[uri->ws_wordc-1])); - if (!json) - ctlio_reply (io, 400, NULL); - free (uri->ws_wordv[uri->ws_wordc-1]); - uri->ws_wordv[uri->ws_wordc-1] = NULL; - uri->ws_wordc--; + if (method == METH_POST) + { + ctlio_reply (io, 400, NULL); + return; + } + else + { + json = json_parse_string (json_query, strlen (json_query)); + if (!json) + { + ctlio_reply (io, 400, "JSON error: %s", json_err_diag); + return; + } + } } @@ -1009,3 +1061,3 @@ ctlio_do_command (struct ctlio *io, struct wordsplit *uri) - res->handler (io, method, uri->ws_wordc, uri->ws_wordv, json); + res->handler (io, method, uri, json); json_value_free (json); @@ -1036,16 +1088,3 @@ ctlrd (int fd, void *data) if (rc == 200) - { - struct wordsplit ws; - - ws.ws_delim = "/"; - if (wordsplit (io->input.input_uri, &ws, - WRDSF_DELIM | WRDSF_SQUEEZE_DELIMS - | WRDSF_NOVAR | WRDSF_NOCMD)) - ctlio_reply (io, 500, NULL); - else - { - ctlio_do_command (io, &ws); - wordsplit_free (&ws); - } - } + ctlio_do_command (io); else @@ -1206,4 +1245,3 @@ static void res_instance (struct ctlio *io, enum http_method meth, - size_t pathc, char **pathv, - struct json_value *req) + char const *uri, struct json_value *req) { @@ -1225,11 +1263,6 @@ res_instance (struct ctlio *io, enum http_method meth, - if (pathc > 2) - { - ctlio_reply (io, 404, NULL); - return; - } - io->output.reply = json_reply_create (); - if (pathc == 2) + if (uri) { + ++uri; /* skip leading / */ if (meth == METH_GET) @@ -1237,3 +1270,3 @@ res_instance (struct ctlio *io, enum http_method meth, for (p = idparam; p->name; p++) - if (strcmp (p->name, pathv[1]) == 0) + if (strcmp (p->name, uri) == 0) break; @@ -1247,4 +1280,3 @@ res_instance (struct ctlio *io, enum http_method meth, } - else if (strcmp (pathv[1], "PID") == 0 - || strcmp (pathv[1], "instance") == 0) + else if (strcmp (uri, "PID") == 0 || strcmp (uri, "instance") == 0) { @@ -1742,4 +1774,3 @@ static void res_programs (struct ctlio *io, enum http_method meth, - size_t pathc, char **pathv, - struct json_value *json) + char const *uri, struct json_value *json) { @@ -1760,3 +1791,3 @@ res_programs (struct ctlio *io, enum http_method meth, { - if (pathc != 2) + if (!uri) ctlio_reply (io, 404, NULL); @@ -1764,3 +1795,3 @@ res_programs (struct ctlio *io, enum http_method meth, { - struct prog *prog = progman_locate (pathv[1]); + struct prog *prog = progman_locate (uri); if (!prog) |