void msgpack_reply(redisAsyncContext *c, void *r, void *privdata) { redisReply *reply = r; struct cmd *cmd = privdata; struct msg_out out; (void)c; if(cmd == NULL) { /* broken connection */ return; } if (reply == NULL) { /* broken Redis link */ format_send_error(cmd, 503, "Service Unavailable"); return; } /* prepare data structure for output */ out.p = NULL; out.sz = 0; /* encode redis reply */ msgpack_wrap_redis_reply(cmd, &out, r); /* send reply */ format_send_reply(cmd, out.p, out.sz, "application/x-msgpack"); /* cleanup */ free(out.p); }
void custom_type_reply(redisAsyncContext *c, void *r, void *privdata) { redisReply *reply = r; struct cmd *cmd = privdata; (void)c; char int_buffer[50]; int int_len; struct http_response resp; if (reply == NULL) { /* broken Redis link */ format_send_error(cmd, 503, "Service Unavailable"); return; } if(cmd->mime) { /* use the given content-type, but only for strings */ switch(reply->type) { 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; case REDIS_REPLY_INTEGER: int_len = sprintf(int_buffer, "%lld", reply->integer); format_send_reply(cmd, int_buffer, int_len, cmd->mime); return; case REDIS_REPLY_ARRAY: # TODO: Avoid assuming the command is BLPOP. format_send_reply(cmd, reply->element[1]->str, reply->element[1]->len, cmd->mime); return; } } /* couldn't make sense of what the client wanted. */ http_response_init(&resp, 401, "Bad Request"); http_response_set_header(&resp, "Content-Length", "0"); http_response_set_keep_alive(&resp, cmd->keep_alive); http_response_write(&resp, cmd->fd); cmd_free(cmd); }
void format_send_reply(struct cmd *cmd, const char *p, size_t sz, const char *content_type) { int free_cmd = 1; const char *ct = cmd->mime?cmd->mime:content_type; struct http_response *resp; if(cmd->is_websocket) { ws_reply(cmd, p, sz); /* If it's a subscribe command, there'll be more responses */ if(!cmd_is_subscribe(cmd)) cmd_free(cmd); return; } if(cmd_is_subscribe(cmd)) { free_cmd = 0; /* start streaming */ if(cmd->started_responding == 0) { cmd->started_responding = 1; resp = http_response_init(cmd->w, 200, "OK"); resp->http_version = cmd->http_version; if(cmd->filename) { http_response_set_header(resp, "Content-Disposition", cmd->filename); } http_response_set_header(resp, "Content-Type", ct); http_response_set_keep_alive(resp, 1); http_response_set_header(resp, "Transfer-Encoding", "chunked"); http_response_set_body(resp, p, sz); http_response_write(resp, cmd->fd); } else { /* Asynchronous chunk write. */ http_response_write_chunk(cmd->fd, cmd->w, p, sz); } } else { /* compute ETag */ char *etag = etag_new(p, sz); if(etag) { /* check If-None-Match */ if(cmd->if_none_match && strcmp(cmd->if_none_match, etag) == 0) { /* SAME! send 304. */ resp = http_response_init(cmd->w, 304, "Not Modified"); } else { resp = http_response_init(cmd->w, 200, "OK"); if(cmd->filename) { http_response_set_header(resp, "Content-Disposition", cmd->filename); } http_response_set_header(resp, "Content-Type", ct); http_response_set_header(resp, "ETag", etag); http_response_set_body(resp, p, sz); } resp->http_version = cmd->http_version; http_response_set_keep_alive(resp, cmd->keep_alive); http_response_write(resp, cmd->fd); free(etag); } else { format_send_error(cmd, 503, "Service Unavailable"); } } /* cleanup */ if(free_cmd) { cmd_free(cmd); } }