From 5ca45a54d936a56e36e4563bd76cb0ff28d05a38 Mon Sep 17 00:00:00 2001 From: Nicolas Favre-Felix Date: Mon, 3 Jan 2011 20:45:53 +0100 Subject: [PATCH] Working custom handler. --- Makefile | 2 +- README.markdown | 4 +++- cmd.c | 9 +++++---- formats/custom-type.c | 26 ++++++++++++++++++++++---- 4 files changed, 31 insertions(+), 10 deletions(-) diff --git a/Makefile b/Makefile index 617acbf..69d2706 100644 --- a/Makefile +++ b/Makefile @@ -3,7 +3,7 @@ HIREDIS_OBJ=hiredis/hiredis.o hiredis/sds.o hiredis/net.o hiredis/async.o hiredi JANSSON_OBJ=jansson/src/dump.o jansson/src/error.o jansson/src/hashtable.o jansson/src/load.o jansson/src/strbuffer.o jansson/src/utf.o jansson/src/value.o jansson/src/variadic.o FORMAT_OBJS=formats/json.o formats/raw.o formats/common.o formats/custom-type.o OBJS=webdis.o conf.o $(FORMAT_OBJS) cmd.o server.o $(HIREDIS_OBJ) $(JANSSON_OBJ) libb64/cencode.o acl.o -CFLAGS=-O3 -Wall -Wextra -I. -Ijansson/src +CFLAGS=-O0 -ggdb -Wall -Wextra -I. -Ijansson/src LDFLAGS=-levent all: $(OUT) Makefile diff --git a/README.markdown b/README.markdown index be4f894..73a1434 100644 --- a/README.markdown +++ b/README.markdown @@ -25,7 +25,9 @@ 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. -* For `GET` commands, MIME type in a second key with `?format=custom&typeKey=` or custom MIME type with `format=custom&type=something/here`. +* For `GET` commands: + * MIME type in a second key with `/GET/k?typeKey=type-k`. This will transform the `GET` request into `MGET` and fetch both `k` and `type-k`. If `type-k` is a string, it will be used as Content-Type in the response. If the key doesn't exist or isn't a string, `binary/octet-stream` is used instead. + * Custom MIME type with `?type=text/plain` (or any other MIME type). * URL-encoded parameters for binary data or slashes. For instance, `%2f` is decoded as `/` but not used as a command separator. # Ideas, TODO... diff --git a/cmd.c b/cmd.c index 8bb37ce..a1c9ab5 100644 --- a/cmd.c +++ b/cmd.c @@ -155,12 +155,12 @@ cmd_run(struct server *s, struct evhttp_request *rq, const char *arg = p; int arg_len; char *next = strchr(arg, '/'); - if(next) { /* found a slash */ + if(!next || next > uri + uri_len) { /* last argument */ + p = uri + uri_len; + arg_len = p - arg; + } else { /* found a slash */ arg_len = next - arg; p = next + 1; - } else { /* last argument */ - arg_len = uri + uri_len - arg; - p = uri + uri_len; } /* record argument */ @@ -204,6 +204,7 @@ get_functions(struct cmd *cmd, formatting_fun *f_format, transform_fun *f_transf *f_format = custom_type_reply; } else if(strcmp(kv->key, "type") == 0) { /* MIME type in parameter */ cmd->mime = strdup(kv->value); + *f_format = custom_type_reply; } } } diff --git a/formats/custom-type.c b/formats/custom-type.c index 54d4182..b78e167 100644 --- a/formats/custom-type.c +++ b/formats/custom-type.c @@ -21,15 +21,25 @@ custom_type_reply(redisAsyncContext *c, void *r, void *privdata) { return; } + if(cmd->mime) { /* use the given content-type */ + if(reply->type != REDIS_REPLY_STRING) { + goto fail; + } + format_send_reply(cmd, reply->str, reply->len, cmd->mime); + return; + } + + if(!cmd->mimeKey) { /* how did we get here? */ + goto fail; + } + /* we expect array(string, string) */ if(reply->type != REDIS_REPLY_ARRAY || reply->elements != 2) { - evhttp_send_reply(cmd->rq, 400, "Bad request", NULL); - return; + goto fail; } if(reply->element[0]->type != REDIS_REPLY_STRING) { - evhttp_send_reply(cmd->rq, 400, "Bad request", NULL); - return; + goto fail; } if(reply->element[1]->type == REDIS_REPLY_STRING) { @@ -40,8 +50,16 @@ custom_type_reply(redisAsyncContext *c, void *r, void *privdata) { /* send reply */ format_send_reply(cmd, reply->element[0]->str, reply->element[0]->len, ct); + + cmd_free(cmd); + return; + +fail: + evhttp_send_reply(cmd->rq, 400, "Bad request", NULL); + cmd_free(cmd); } +/* 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” */