Removed content-type in another key, added suffixes instead.

master
Nicolas Favre-Felix 14 years ago
parent 8c8954d25a
commit 469e51608b

69
cmd.c

@ -33,9 +33,6 @@ cmd_free(struct cmd *c) {
free(c->argv);
free(c->argv_len);
free(c->mime);
free(c->mimeKey);
free(c);
}
@ -100,7 +97,6 @@ cmd_run(struct server *s, struct evhttp_request *rq,
struct cmd *cmd;
formatting_fun f_format;
transform_fun f_transform = NULL;
/* count arguments */
if(qmark) {
@ -112,6 +108,13 @@ cmd_run(struct server *s, struct evhttp_request *rq,
cmd = cmd_new(rq, param_count);
/* parse URI parameters */
evhttp_parse_query(uri, &cmd->uri_params);
/* get output formatting function */
uri_len = cmd_read_params(cmd, uri, uri_len, &f_format);
/* check if we only have one command or more. */
slash = memchr(uri, '/', uri_len);
if(slash) {
cmd_len = slash - uri;
@ -119,12 +122,6 @@ cmd_run(struct server *s, struct evhttp_request *rq,
cmd_len = uri_len;
}
/* parse URI parameters */
evhttp_parse_query(uri, &cmd->uri_params);
/* get output formatting function */
cmd_read_params(cmd, &f_format, &f_transform);
/* there is always a first parameter, it's the command name */
cmd->argv[0] = uri;
cmd->argv_len[0] = cmd_len;
@ -170,9 +167,6 @@ cmd_run(struct server *s, struct evhttp_request *rq,
cur_param++;
}
/* transform command if we need to. */
if(f_transform) f_transform(cmd);
/* push command to Redis. */
redisAsyncCommandArgv(s->ac, f_format, cmd, cmd->count, cmd->argv, cmd->argv_len);
@ -187,33 +181,42 @@ cmd_run(struct server *s, struct evhttp_request *rq,
* Return 2 functions, one to format the reply and
* one to transform the command before processing it.
*/
void
cmd_read_params(struct cmd *cmd, formatting_fun *f_format, transform_fun *f_transform) {
int
cmd_read_params(struct cmd *cmd, const char *uri, size_t uri_len, formatting_fun *f_format) {
struct evkeyval *kv;
const char *ext;
int ext_len = -1;
unsigned int i;
struct reply_format funs[] = {
{.s = "json", .sz = 4, .f = json_reply, .ct = "application/json"},
{.s = "raw", .sz = 3, .f = raw_reply, .ct = "binary/octet-stream"},
{.s = "txt", .sz = 3, .f = custom_type_reply, .ct = "text/plain"},
{.s = "html", .sz = 4, .f = custom_type_reply, .ct = "text/html"},
{.s = "png", .sz = 3, .f = custom_type_reply, .ct = "image/png"},
};
/* defaults */
*f_format = json_reply;
*f_transform = NULL;
/* loop over the query string */
TAILQ_FOREACH(kv, &cmd->uri_params, next) {
if(strcmp(kv->key, "format") == 0) { /* output format */
if(strcmp(kv->value, "raw") == 0) {
*f_format = raw_reply;
} else if(strcmp(kv->value, "json") == 0) {
*f_format = json_reply;
}
/* find extension */
for(ext = uri + uri_len - 1; ext != uri && *ext != '/'; --ext) {
if(*ext == '.') {
ext++;
ext_len = uri + uri_len - ext;
break;
} else if(strcmp(kv->key, "typeKey") == 0) { /* MIME type in a key. */
cmd->mimeKey = strdup(kv->value);
*f_transform = custom_type_process_cmd;
*f_format = custom_type_reply;
} else if(strcmp(kv->key, "type") == 0) { /* MIME type directly in parameter */
cmd->mime = strdup(kv->value);
*f_format = custom_type_reply;
}
}
if(!ext_len) return uri_len;
/* find function for the given extension */
for(i = 0; i < sizeof(funs)/sizeof(funs[0]); ++i) {
if(ext_len == (int)funs[i].sz && strncmp(ext, funs[i].s, ext_len) == 0) {
*f_format = funs[i].f;
cmd->mime = funs[i].ct;
}
}
return uri_len - ext_len - 1;
}
int

15
cmd.h

@ -12,7 +12,6 @@ struct server;
struct cmd;
typedef void (*formatting_fun)(redisAsyncContext *, void *, void *);
typedef void (*transform_fun)(struct cmd *);
struct cmd {
@ -26,8 +25,7 @@ struct cmd {
int started_responding;
/* HTTP data */
char *mime;
char *mimeKey;
const char *mime;
char *if_none_match;
};
@ -37,6 +35,13 @@ struct pubsub_client {
struct evhttp_request *rq;
};
struct reply_format {
const char *s;
size_t sz;
formatting_fun f;
const char *ct;
};
struct cmd *
cmd_new(struct evhttp_request *rq, int count);
@ -47,8 +52,8 @@ int
cmd_run(struct server *s, struct evhttp_request *rq,
const char *uri, size_t uri_len);
void
cmd_read_params(struct cmd *cmd, formatting_fun *f_format, transform_fun *f_transform);
int
cmd_read_params(struct cmd *cmd, const char *uri, size_t uri_len, formatting_fun *f_format);
int
cmd_is_subscribe(struct cmd *cmd);

@ -28,16 +28,24 @@ custom_type_reply(redisAsyncContext *c, void *r, void *privdata) {
}
if(cmd->mime) { /* use the given content-type */
if(reply->type != REDIS_REPLY_STRING) {
custom_400(cmd);
switch(reply->type) {
case REDIS_REPLY_NIL:
format_send_reply(cmd, "", 0, cmd->mime);
return;
}
case REDIS_REPLY_STRING:
format_send_reply(cmd, reply->str, reply->len, cmd->mime);
return;
default:
custom_400(cmd);
return;
}
}
/* we expect array(string, string) */
if(!cmd->mimeKey || reply->type != REDIS_REPLY_ARRAY || reply->elements != 2 || reply->element[0]->type != REDIS_REPLY_STRING) {
if(reply->type != REDIS_REPLY_ARRAY || reply->elements != 2 || reply->element[0]->type != REDIS_REPLY_STRING) {
custom_400(cmd);
return;
}
@ -54,23 +62,3 @@ custom_type_reply(redisAsyncContext *c, void *r, void *privdata) {
return;
}
/* This will change a GET command into MGET if a key is provided to get the response MIME-type from. */
void
custom_type_process_cmd(struct cmd *cmd) {
/* MGET if mode is “custom” */
if(cmd->count == 2 && cmd->argv_len[0] == 3 &&
strncasecmp(cmd->argv[0], "GET", 3) == 0 && cmd->mimeKey) {
cmd->count++; /* space for content-type key */
cmd->argv = realloc(cmd->argv, cmd->count * sizeof(char*));
cmd->argv_len = realloc(cmd->argv_len, cmd->count * sizeof(size_t));
/* replace command with MGET */
cmd->argv[0] = "MGET";
cmd->argv_len[0] = 4;
/* add mime key after the key. */
cmd->argv[2] = strdup(cmd->mimeKey);
cmd->argv_len[2] = strlen(cmd->mimeKey);
}
}

@ -9,7 +9,4 @@ struct cmd;
void
custom_type_reply(redisAsyncContext *c, void *r, void *privdata);
void
custom_type_process_cmd(struct cmd *cmd);
#endif

@ -28,7 +28,7 @@ raw_reply(redisAsyncContext *c, void *r, void *privdata) {
raw_out = raw_wrap(r, &sz);
/* send reply */
format_send_reply(cmd, raw_out, sz, "binary/octet-stream");
format_send_reply(cmd, raw_out, sz, cmd->mime?cmd->mime:"binary/octet-stream");
/* cleanup */
free(raw_out);

Loading…
Cancel
Save