Special GET formatter for key + content-type key.

master
Nicolas Favre-Felix 14 years ago
parent 32a5b3c9cd
commit 1ea7cd0720

@ -25,7 +25,7 @@ curl -d "GET/hello" http://127.0.0.1:7379/
* Possible Redis authentication in the config file.
* Pub/Sub using `Transfer-Encoding: chunked`, works with JSONP as well. Webdis can be used as a Comet server.
* Drop privileges on startup.
* MIME type in a second key with `?format=custom&typeKey=`
* For `GET` commands, MIME type in a second key with `?format=custom&typeKey=` or custom MIME type with `format=custom&type=something/here`.
* URL-encoded parameters for binary data or slashes. For instance, `%2f` is decoded as `/` but not used as a command separator.
# Ideas, TODO...

46
cmd.c

@ -20,8 +20,8 @@ cmd_new(struct evhttp_request *rq, int count) {
c->rq = rq;
c->count = count;
c->argv = calloc(count, sizeof(char*));
c->argv_len = calloc(count, sizeof(size_t));
c->argv = calloc(1+count, sizeof(char*));
c->argv_len = calloc(1+count, sizeof(size_t));
return c;
}
@ -33,6 +33,9 @@ cmd_free(struct cmd *c) {
free(c->argv);
free(c->argv_len);
free(c->mime);
free(c->mimeKey);
free(c);
}
@ -95,7 +98,9 @@ cmd_run(struct server *s, struct evhttp_request *rq,
int param_count = 0, cur_param = 1, i;
struct cmd *cmd;
formatting_fun fun;
formatting_fun f_format;
transform_fun f_transform = NULL;
/* count arguments */
if(qmark) {
@ -117,7 +122,7 @@ cmd_run(struct server *s, struct evhttp_request *rq,
evhttp_parse_query(uri, &cmd->uri_params);
/* get output formatting function */
fun = get_formatting_function(&cmd->uri_params);
get_functions(cmd, &f_format, &f_transform);
/* there is always a first parameter, it's the command name */
cmd->argv[0] = uri;
@ -141,7 +146,7 @@ cmd_run(struct server *s, struct evhttp_request *rq,
}
if(!slash) {
redisAsyncCommandArgv(s->ac, fun, cmd, 1, cmd->argv, cmd->argv_len);
redisAsyncCommandArgv(s->ac, f_format, cmd, 1, cmd->argv, cmd->argv_len);
return 0;
}
p = slash + 1;
@ -163,10 +168,11 @@ cmd_run(struct server *s, struct evhttp_request *rq,
cur_param++;
}
/* MGET if */
// if(cmd->arg_len[0] == 3 && strncasecmp(cmd->argv[0], "GET", 3) == 0 && ) {
/* transform command if we need to. */
if(f_transform) f_transform(cmd);
redisAsyncCommandArgv(s->ac, f_format, cmd, cmd->count, cmd->argv, cmd->argv_len);
redisAsyncCommandArgv(s->ac, fun, cmd, param_count, cmd->argv, cmd->argv_len);
for(i = 1; i < cur_param; ++i) {
free((char*)cmd->argv[i]);
}
@ -174,26 +180,32 @@ cmd_run(struct server *s, struct evhttp_request *rq,
return 0;
}
formatting_fun
get_formatting_function(struct evkeyvalq *params) {
void
get_functions(struct cmd *cmd, formatting_fun *f_format, transform_fun *f_transform) {
struct evkeyval *kv;
/* defaults */
*f_format = json_reply;
*f_transform = NULL;
/* check for JSONP */
TAILQ_FOREACH(kv, params, next) {
TAILQ_FOREACH(kv, &cmd->uri_params, next) {
if(strcmp(kv->key, "format") == 0) {
if(strcmp(kv->value, "raw") == 0) {
return raw_reply;
*f_format = raw_reply;
} else if(strcmp(kv->value, "json") == 0) {
return json_reply;
} else if(strcmp(kv->value, "custom") == 0) {
return custom_type_reply;
*f_format = json_reply;
}
break;
} else if(strcmp(kv->key, "typeKey") == 0) { /* MIME type in 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 in parameter */
cmd->mime = strdup(kv->value);
}
}
return json_reply;
}
int

@ -9,8 +9,10 @@
struct evhttp_request;
struct server;
struct cmd;
typedef void (*formatting_fun)(redisAsyncContext *, void *, void *);
typedef void (*transform_fun)(struct cmd *);
struct cmd {
@ -22,6 +24,9 @@ struct cmd {
struct evkeyvalq uri_params;
int started_responding;
char *mime;
char *mimeKey;
};
struct pubsub_client {
@ -39,8 +44,8 @@ int
cmd_run(struct server *s, struct evhttp_request *rq,
const char *uri, size_t uri_len);
formatting_fun
get_formatting_function(struct evkeyvalq *params);
void
get_functions(struct cmd *cmd, formatting_fun *f_format, transform_fun *f_transform);
int
cmd_is_subscribe(struct cmd *cmd);

@ -12,7 +12,7 @@ format_send_reply(struct cmd *cmd, const char *p, size_t sz, const char *content
/* send reply */
body = evbuffer_new();
evbuffer_add(body, p, sz);
evhttp_add_header(cmd->rq->output_headers, "Content-Type", content_type);
evhttp_add_header(cmd->rq->output_headers, "Content-Type", cmd->mime?cmd->mime:content_type);
if(cmd_is_subscribe(cmd)) {
free_cmd = 0;

@ -32,7 +32,7 @@ custom_type_reply(redisAsyncContext *c, void *r, void *privdata) {
return;
}
if(reply->element[1]->type != REDIS_REPLY_STRING) {
if(reply->element[1]->type == REDIS_REPLY_STRING) {
ct = reply->element[1]->str;
} else {
ct = "binary/octet-stream";
@ -42,3 +42,19 @@ custom_type_reply(redisAsyncContext *c, void *r, void *privdata) {
format_send_reply(cmd, reply->element[0]->str, reply->element[0]->len, ct);
}
void
custom_type_process_cmd(struct cmd *cmd) {
/* MGET if mode is “custom” */
if(cmd->argv_len[0] == 3 && strncasecmp(cmd->argv[0], "GET", 3) == 0 && cmd->mimeKey) {
cmd->count++; /* space for content-type key */
/* replace command with MGET */
cmd->argv[0] = "MGET";
cmd->argv_len[0] = 4;
/* add mime key after the key. */
cmd->argv[2] = cmd->mimeKey;
cmd->argv_len[2] = strlen(cmd->mimeKey);
}
}

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

Loading…
Cancel
Save