Permalink
Browse files

Special GET formatter for key + content-type key.

  • Loading branch information...
1 parent 32a5b3c commit 1ea7cd0720e0d35b28936c266b2b528ae5436e3c @nicolasff committed Jan 3, 2011
Showing with 58 additions and 22 deletions.
  1. +1 −1 README.markdown
  2. +29 −17 cmd.c
  3. +7 −2 cmd.h
  4. +1 −1 formats/common.c
  5. +17 −1 formats/custom-type.c
  6. +3 −0 formats/custom-type.h
View
@@ -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...
View
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,37 +168,44 @@ 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]);
}
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
View
9 cmd.h
@@ -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);
View
@@ -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;
View
@@ -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);
+ }
+}
View
@@ -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

0 comments on commit 1ea7cd0

Please sign in to comment.