feature: http: allow override user,device for last_users() via X-Limit- headers

This commit is contained in:
Jan-Piet Mens 2015-09-09 18:31:41 +02:00
parent 260771ff25
commit 0e2527f43d
4 changed files with 74 additions and 48 deletions

95
http.c
View File

@ -71,6 +71,35 @@ static int send_reply(struct mg_connection *conn)
}
}
/*
* Return a copy of a GET/POST parameter or NULL. The parameter
* may be overriden by an HTTP header called X-Limit-<fieldname>.
* Caller must free if return is non-NULL.
*/
static char *field(struct mg_connection *conn, char *fieldname)
{
char buf[BUFSIZ];
int ret, n;
snprintf(buf, sizeof(buf), "X-Limit-%s", fieldname);
for (n = 0; n < conn->num_headers; n++) {
struct mg_header *hh;
hh = &conn->http_headers[n];
// fprintf(stderr, " %s=%s\n", hh->name, hh->value);
if (*hh->name == 'X' && strcasecmp(hh->name, buf) == 0) {
return (strdup(hh->value));
}
}
if ((ret = mg_get_var(conn, fieldname, buf, sizeof(buf))) > 0) {
return (strdup(buf));
}
return (NULL);
}
/*
* Push a list of LAST users down the Websocket. We send individual
* JSON objects (not an array of them) because these are what the
@ -81,10 +110,17 @@ static void send_last(struct mg_connection *conn)
{
struct udata *ud = (struct udata *)conn->server_param;
JsonNode *user_array, *o, *one;
char *u = NULL, *d = NULL;
if ((user_array = last_users()) != NULL) {
u = field(conn, "user");
d = field(conn, "device");
if ((user_array = last_users(u, d)) != NULL) {
char *js;
if (u) free(u);
if (d) free(d);
json_foreach(one, user_array) {
JsonNode *f;
@ -131,34 +167,6 @@ static int json_response(struct mg_connection *conn, JsonNode *json)
return (MG_TRUE);
}
/*
* Return a copy of a GET/POST parameter or NULL. The parameter
* may be overriden by an HTTP header called X-Limit-<fieldname>.
* Caller must free if return is non-NULL.
*/
static char *field(struct mg_connection *conn, char *fieldname)
{
char buf[BUFSIZ];
int ret, n;
snprintf(buf, sizeof(buf), "X-Limit-%s", fieldname);
for (n = 0; n < conn->num_headers; n++) {
struct mg_header *hh;
hh = &conn->http_headers[n];
// fprintf(stderr, " %s=%s\n", hh->name, hh->value);
if (*hh->name == 'X' && strcasecmp(hh->name, buf) == 0) {
return (strdup(hh->value));
}
}
if ((ret = mg_get_var(conn, fieldname, buf, sizeof(buf))) > 0) {
return (strdup(buf));
}
return (NULL);
}
/*
* We are being called with the portion behind /api/0/ as in
@ -196,19 +204,20 @@ static int dispatch(struct mg_connection *conn, const char *uri)
fprintf(stderr, "%d = %s\n", ret, uparts[ret]);
}
if (nparts == 1 && !strcmp(uparts[0], "last")) {
JsonNode *user_array;
if ((user_array = last_users()) != NULL) {
return (json_response(conn, user_array));
}
}
u = field(conn, "user");
d = field(conn, "device");
time_from = field(conn, "from");
time_to = field(conn, "to");
if (nparts == 1 && !strcmp(uparts[0], "last")) {
JsonNode *user_array;
if ((user_array = last_users(u, d)) != NULL) {
CLEANUP;
return (json_response(conn, user_array));
}
}
if ((ret = mg_get_var(conn, "limit", buf, sizeof(buf))) > 0) {
limit = atoi(buf);
}
@ -308,7 +317,12 @@ int ev_handler(struct mg_connection *conn, enum mg_event ev)
case MG_REQUEST:
#if 0
#if 1
fprintf(stderr, "------------------------------ %s (%ld) %.*s\n",
conn->uri,
conn->content_len,
(int)conn->content_len,
conn->content);
for (int n = 0; n < conn->num_headers; n++) {
struct mg_header *hh;
@ -316,11 +330,6 @@ int ev_handler(struct mg_connection *conn, enum mg_event ev)
fprintf(stderr, " %s=%s\n", hh->name, hh->value);
}
fprintf(stderr, "%s (%ld) %.*s\n",
conn->uri,
conn->content_len,
(int)conn->content_len,
conn->content);
#endif
/* Websockets URI ?*/
if (strcmp(conn->uri, "/ws/last") == 0) {

3
ocat.c
View File

@ -315,7 +315,8 @@ int main(int argc, char **argv)
if (last) {
JsonNode *user_array;
if ((user_array = last_users()) != NULL) {
// FIXME: allow last_users with username, device
if ((user_array = last_users(NULL, NULL)) != NULL) {
char *js;
if ((js = json_stringify(user_array, JSON_INDENT)) != NULL) {

View File

@ -146,10 +146,12 @@ void append_device_details(JsonNode *userlist, char *user, char *device)
}
/*
* Return an array of users gleaned from LAST with merged details
* Return an array of users gleaned from LAST with merged details.
* If user and device are specified, limit to those; either may be
* NULL.
*/
JsonNode *last_users()
JsonNode *last_users(char *in_user, char *in_device)
{
JsonNode *obj = json_mkobject();
JsonNode *un, *dn, *userlist = json_mkarray();
@ -157,6 +159,9 @@ JsonNode *last_users()
snprintf(path, BUFSIZ, "%s/last", STORAGEDIR);
fprintf(stderr, "last_users(%s, %s)\n", (in_user) ? in_user : "<nil>",
(in_device) ? in_device : "<nil>");
if (user_device_list(path, 0, obj) == 1)
return (obj);
@ -171,7 +176,18 @@ JsonNode *last_users()
} else if (dn->tag == JSON_NUMBER) { /* all digits? */
sprintf(device, "%.lf", dn->number_);
}
append_device_details(userlist, user, device);
if (!in_user && !in_device) {
append_device_details(userlist, user, device);
} else if (in_user && !in_device) {
if (strcmp(user, in_user) == 0) {
append_device_details(userlist, user, device);
}
} else if (in_user && in_device) {
if (strcmp(user, in_user) == 0 && strcmp(device, in_device) == 0) {
append_device_details(userlist, user, device);
}
}
}
}
json_delete(obj);

View File

@ -21,7 +21,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();
JsonNode *last_users(char *user, char *device);
char *gpx_string(JsonNode *json);
void storage_init(int revgeo);