From 90fdc8cf6094a5cfafacca2a160e19233b7d9e77 Mon Sep 17 00:00:00 2001 From: Jan-Piet Mens Date: Fri, 23 Oct 2015 15:32:52 +0200 Subject: [PATCH] support /last with fields --- README.md | 6 +++++- http.c | 24 +++++++++++++++++------- ocat.c | 2 +- storage.c | 34 ++++++++++++++++++++++++++++++++-- storage.h | 2 +- 5 files changed, 56 insertions(+), 12 deletions(-) diff --git a/README.md b/README.md index f27434a..0e8f2ff 100644 --- a/README.md +++ b/README.md @@ -398,12 +398,16 @@ curl 'http://127.0.0.1:8083/api/0/monitor' #### `last` -Returns a list of last users' positions. (Can be limited by _user_ and _device_.) +Returns a list of last users' positions. (Can be limited by _user_, _device_, and _fields_, a comma-separated list of fields which should be returned instead of the default of all fields.) ``` curl http://127.0.0.1:8083/api/0/last [-d user=jjolie [-d device=phone]] ``` +``` +curl 'http://127.0.0.1:8083/api/0/last?fields=tst,tid,addr,topic,isotst' +``` + #### `list` List users. If _user_ is specified, lists that user's devices. If both _user_ and _device_ are specified, lists that device's `.rec` files. diff --git a/http.c b/http.c index 2970946..e7e0b87 100644 --- a/http.c +++ b/http.c @@ -38,6 +38,8 @@ #ifdef WITH_HTTP +#define MAXPARTS 40 + /* A transparent 40x40 PNG image with a black border */ static unsigned char border40x40png[] = { 0x89, 0x50, 0x4E, 0x47, 0x0D, 0x0A, 0x1A, 0x0A, 0x00, 0x00, @@ -202,7 +204,7 @@ static void send_last(struct mg_connection *conn) u = field(conn, "user"); d = field(conn, "device"); - if ((user_array = last_users(u, d)) != NULL) { + if ((user_array = last_users(u, d, NULL)) != NULL) { json_foreach(one, user_array) { JsonNode *f; @@ -282,7 +284,6 @@ static int xml_response(struct mg_connection *conn, JsonNode *obj) * /users/ or /list */ -#define MAXPARTS 40 #define CLEANUP do {\ int k; \ @@ -347,12 +348,21 @@ static int dispatch(struct mg_connection *conn, const char *uri) #endif /* WITH_KILL */ if (nparts == 1 && !strcmp(uparts[0], "last")) { - JsonNode *user_array; + JsonNode *user_array, *fields = NULL; + char *flds = field(conn, "fields"); - if ((user_array = last_users(u, d)) != NULL) { + if (flds != NULL) { + fields = json_splitter(flds, ","); + free(flds); + } + + if ((user_array = last_users(u, d, fields)) != NULL) { CLEANUP; + json_delete(fields); + return (json_response(conn, user_array)); - } + } + json_delete(fields); } if ((ret = mg_get_var(conn, "limit", buf, sizeof(buf))) > 0) { @@ -396,11 +406,11 @@ static int dispatch(struct mg_connection *conn, const char *uri) /* /locations [[]] */ if (nparts == 1 && !strcmp(uparts[0], "locations")) { - /* + /* * Obtain a list of .rec files from lister(), possibly limited * by s_lo/s_hi times, process each and build the JSON `obj' * with an array of locations. - */ + */ obj = json_mkobject(); locs = json_mkarray(); diff --git a/ocat.c b/ocat.c index cc468ef..9d6250e 100644 --- a/ocat.c +++ b/ocat.c @@ -433,7 +433,7 @@ int main(int argc, char **argv) if (last) { JsonNode *user_array; - if ((user_array = last_users(username, device)) != NULL) { + if ((user_array = last_users(username, device, fields)) != NULL) { if (otype == JSON) { char *js; diff --git a/storage.c b/storage.c index 8ebbefc..08abfd0 100644 --- a/storage.c +++ b/storage.c @@ -181,10 +181,11 @@ void append_device_details(JsonNode *userlist, char *user, char *device) /* * Return an array of users gleaned from LAST with merged details. * If user and device are specified, limit to those; either may be - * NULL. + * NULL. If `fields' is not NULL, it's a JSON array of fields to + * be returned. */ -JsonNode *last_users(char *in_user, char *in_device) +JsonNode *last_users(char *in_user, char *in_device, JsonNode *fields) { JsonNode *obj = json_mkobject(); JsonNode *un, *dn, *userlist = json_mkarray(); @@ -225,6 +226,35 @@ JsonNode *last_users(char *in_user, char *in_device) } json_delete(obj); + /* + * userlist now is an array of user objects. If fields were + * specified, re-create that array with object which have + * only the requested fields. It's a shame we have to re-do + * this here, but I can't think of an alternative way at + * the moment. + */ + + if (fields) { + JsonNode *new_userlist = json_mkarray(), *user; + + json_foreach(user, userlist) { + JsonNode *o = json_mkobject(), *f, *j; + + json_foreach(f, fields) { + char *field_name = f->string_; + + if ((j = json_find_member(user, field_name)) != NULL) { + json_copy_element_to_object(o, field_name, j); + } + } + json_append_element(new_userlist, o); + } + + + json_delete(userlist); + return (new_userlist); + } + return (userlist); } diff --git a/storage.h b/storage.h index 7849d93..ab9d532 100644 --- a/storage.h +++ b/storage.h @@ -43,7 +43,7 @@ int make_times(char *time_from, time_t *s_lo, char *time_to, time_t *s_to); JsonNode *geo_json(JsonNode *json); JsonNode *geo_linestring(JsonNode *location_array); JsonNode *kill_datastore(char *username, char *device); -JsonNode *last_users(char *user, char *device); +JsonNode *last_users(char *user, char *device, JsonNode *fields); char *gpx_string(JsonNode *json); void storage_init(int revgeo); void storage_gcache_dump(char *lmdbname);