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. * 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. * Pub/Sub using `Transfer-Encoding: chunked`, works with JSONP as well. Webdis can be used as a Comet server.
* Drop privileges on startup. * 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. * URL-encoded parameters for binary data or slashes. For instance, `%2f` is decoded as `/` but not used as a command separator.
# Ideas, TODO... # Ideas, TODO...

46
cmd.c

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

@ -9,8 +9,10 @@
struct evhttp_request; struct evhttp_request;
struct server; struct server;
struct cmd;
typedef void (*formatting_fun)(redisAsyncContext *, void *, void *); typedef void (*formatting_fun)(redisAsyncContext *, void *, void *);
typedef void (*transform_fun)(struct cmd *);
struct cmd { struct cmd {
@ -22,6 +24,9 @@ struct cmd {
struct evkeyvalq uri_params; struct evkeyvalq uri_params;
int started_responding; int started_responding;
char *mime;
char *mimeKey;
}; };
struct pubsub_client { struct pubsub_client {
@ -39,8 +44,8 @@ int
cmd_run(struct server *s, struct evhttp_request *rq, cmd_run(struct server *s, struct evhttp_request *rq,
const char *uri, size_t uri_len); const char *uri, size_t uri_len);
formatting_fun void
get_formatting_function(struct evkeyvalq *params); get_functions(struct cmd *cmd, formatting_fun *f_format, transform_fun *f_transform);
int int
cmd_is_subscribe(struct cmd *cmd); 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 */ /* send reply */
body = evbuffer_new(); body = evbuffer_new();
evbuffer_add(body, p, sz); 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)) { if(cmd_is_subscribe(cmd)) {
free_cmd = 0; free_cmd = 0;

@ -32,7 +32,7 @@ custom_type_reply(redisAsyncContext *c, void *r, void *privdata) {
return; return;
} }
if(reply->element[1]->type != REDIS_REPLY_STRING) { if(reply->element[1]->type == REDIS_REPLY_STRING) {
ct = reply->element[1]->str; ct = reply->element[1]->str;
} else { } else {
ct = "binary/octet-stream"; 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); 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 void
custom_type_reply(redisAsyncContext *c, void *r, void *privdata); custom_type_reply(redisAsyncContext *c, void *r, void *privdata);
void
custom_type_process_cmd(struct cmd *cmd);
#endif #endif

Loading…
Cancel
Save