master
Nicolas Favre-Felix 14 years ago
parent 75cbbc2064
commit 6e3c4240ee

21
cmd.c

@ -112,7 +112,7 @@ cmd_run(struct server *s, struct evhttp_request *rq,
evhttp_parse_query(uri, &cmd->uri_params);
/* get output formatting function */
uri_len = cmd_read_params(cmd, uri, uri_len, &f_format);
uri_len = cmd_select_format(cmd, uri, uri_len, &f_format);
/* check if we only have one command or more. */
slash = memchr(uri, '/', uri_len);
@ -135,9 +135,9 @@ cmd_run(struct server *s, struct evhttp_request *rq,
/* check if we have to split the connection */
if(cmd_is_subscribe(cmd)) {
struct pubsub_client *ps;
ps = calloc(1, sizeof(struct pubsub_client));
ps->s = s = server_copy(s);
ps->rq = rq;
evhttp_connection_set_closecb(rq->evcon, on_http_disconnect, ps);
@ -177,17 +177,24 @@ cmd_run(struct server *s, struct evhttp_request *rq,
return 0;
}
/**
* Return 2 functions, one to format the reply and
* one to transform the command before processing it.
* Select Content-Type and processing function.
*/
int
cmd_read_params(struct cmd *cmd, const char *uri, size_t uri_len, formatting_fun *f_format) {
cmd_select_format(struct cmd *cmd, const char *uri, size_t uri_len, formatting_fun *f_format) {
const char *ext;
int ext_len = -1;
unsigned int i;
/* those are the available reply formats */
struct reply_format {
const char *s;
size_t sz;
formatting_fun f;
const char *ct;
};
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"},
@ -196,7 +203,7 @@ cmd_read_params(struct cmd *cmd, const char *uri, size_t uri_len, formatting_fun
{.s = "png", .sz = 3, .f = custom_type_reply, .ct = "image/png"},
};
/* defaults */
/* default */
*f_format = json_reply;
/* find extension */
@ -207,7 +214,7 @@ cmd_read_params(struct cmd *cmd, const char *uri, size_t uri_len, formatting_fun
break;
}
}
if(!ext_len) return uri_len;
if(!ext_len) return uri_len; /* nothing found */
/* find function for the given extension */
for(i = 0; i < sizeof(funs)/sizeof(funs[0]); ++i) {

@ -35,13 +35,6 @@ 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);
@ -53,7 +46,7 @@ cmd_run(struct server *s, struct evhttp_request *rq,
const char *uri, size_t uri_len);
int
cmd_read_params(struct cmd *cmd, const char *uri, size_t uri_len, formatting_fun *f_format);
cmd_select_format(struct cmd *cmd, const char *uri, size_t uri_len, formatting_fun *f_format);
int
cmd_is_subscribe(struct cmd *cmd);

@ -6,59 +6,35 @@
#include <hiredis/hiredis.h>
#include <hiredis/async.h>
static void
custom_400(struct cmd *cmd) {
evhttp_send_reply(cmd->rq, 400, "Bad request", NULL);
cmd_free(cmd);
}
void
custom_type_reply(redisAsyncContext *c, void *r, void *privdata) {
redisReply *reply = r;
struct cmd *cmd = privdata;
char *ct;
(void)c;
evhttp_clear_headers(&cmd->uri_params);
if (reply == NULL) {
if(reply == NULL) {
evhttp_send_reply(cmd->rq, 404, "Not Found", NULL);
return;
}
if(cmd->mime) { /* use the given content-type */
if(cmd->mime) { /* use the given content-type, but only for strings */
switch(reply->type) {
case REDIS_REPLY_NIL:
case REDIS_REPLY_NIL: /* or nil values */
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(reply->type != REDIS_REPLY_ARRAY || reply->elements != 2 || reply->element[0]->type != REDIS_REPLY_STRING) {
custom_400(cmd);
return;
}
/* case of MGET, we need to have a string for content-type in element[1] */
if(reply->element[1]->type == REDIS_REPLY_STRING) {
ct = reply->element[1]->str;
} else {
ct = "binary/octet-stream";
}
/* send reply */
format_send_reply(cmd, reply->element[0]->str, reply->element[0]->len, ct);
return;
/* couldn't make sense of what the client wanted. */
evhttp_send_reply(cmd->rq, 400, "Bad request", NULL);
cmd_free(cmd);
}

@ -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, cmd->mime?cmd->mime:"binary/octet-stream");
format_send_reply(cmd, raw_out, sz, "binary/octet-stream");
/* cleanup */
free(raw_out);

Loading…
Cancel
Save