Skip to content
Newer
Older
100644 254 lines (198 sloc) 5.49 KB
2507fce @nicolasff Added JSON output.
authored Dec 21, 2010
1 #include "cmd.h"
e2f2b36 @nicolasff Added RAW output.
authored Dec 26, 2010
2 #include "server.h"
de5c283 @nicolasff Added IP range restriction.
authored Dec 27, 2010
3 #include "conf.h"
a7bf6f7 @nicolasff ACL refactoring.
authored Jan 1, 2011
4 #include "acl.h"
7cfb80d @nicolasff Add client.{c,h}. Needs a lot more refactoring.
authored Jan 24, 2011
5 #include "client.h"
e2f2b36 @nicolasff Added RAW output.
authored Dec 26, 2010
6
7 #include "formats/json.h"
8 #include "formats/raw.h"
1ad059d @nicolasff Started adding support for a custom content-type in a second key.
authored Jan 3, 2011
9 #include "formats/custom-type.h"
2507fce @nicolasff Added JSON output.
authored Dec 21, 2010
10
11 #include <stdlib.h>
12 #include <string.h>
13 #include <hiredis/hiredis.h>
4448b0f @nicolasff Proper decoding of URL parameters.
authored Jan 3, 2011
14 #include <ctype.h>
2507fce @nicolasff Added JSON output.
authored Dec 21, 2010
15
16 struct cmd *
a298d3c @nicolasff Better client/cmd relationship.
authored Jan 25, 2011
17 cmd_new(int count) {
2507fce @nicolasff Added JSON output.
authored Dec 21, 2010
18
19 struct cmd *c = calloc(1, sizeof(struct cmd));
20
21 c->count = count;
22
1abb414 @nicolasff Final touch to content-type feature.
authored Jan 3, 2011
23 c->argv = calloc(count, sizeof(char*));
24 c->argv_len = calloc(count, sizeof(size_t));
2507fce @nicolasff Added JSON output.
authored Dec 21, 2010
25
26 return c;
27 }
28
29
30 void
31 cmd_free(struct cmd *c) {
32
a298d3c @nicolasff Better client/cmd relationship.
authored Jan 25, 2011
33 if(!c) return;
34
2507fce @nicolasff Added JSON output.
authored Dec 21, 2010
35 free(c->argv);
36 free(c->argv_len);
37
102f9fc @nicolasff Started adding Accept support.
authored Jan 5, 2011
38 if(c->mime_free) free(c->mime);
39
2507fce @nicolasff Added JSON output.
authored Dec 21, 2010
40 free(c);
41 }
42
4448b0f @nicolasff Proper decoding of URL parameters.
authored Jan 3, 2011
43 /* taken from libevent */
44 static char *
45 decode_uri(const char *uri, size_t length, size_t *out_len, int always_decode_plus) {
46 char c;
47 size_t i, j;
48 int in_query = always_decode_plus;
49
50 char *ret = malloc(length);
51
52 for (i = j = 0; i < length; i++) {
53 c = uri[i];
54 if (c == '?') {
55 in_query = 1;
56 } else if (c == '+' && in_query) {
57 c = ' ';
58 } else if (c == '%' && isxdigit((unsigned char)uri[i+1]) &&
59 isxdigit((unsigned char)uri[i+2])) {
60 char tmp[] = { uri[i+1], uri[i+2], '\0' };
61 c = (char)strtol(tmp, NULL, 16);
62 i += 2;
63 }
64 ret[j++] = c;
65 }
66 *out_len = (size_t)j;
67
68 return ret;
69 }
70
71
de5c283 @nicolasff Added IP range restriction.
authored Dec 27, 2010
72 int
89bb00f @nicolasff Start sending HTTP replies.
authored Jan 22, 2011
73 cmd_run(struct server *s, struct http_client *client,
74 const char *uri, size_t uri_len,
75 const char *body, size_t body_len) {
2507fce @nicolasff Added JSON output.
authored Dec 21, 2010
76
89bb00f @nicolasff Start sending HTTP replies.
authored Jan 22, 2011
77 char *qmark = memchr(uri, '?', uri_len);
a3aa1a9 @nicolasff Bugfix in RAW mode, more code doc.
authored Jan 3, 2011
78 char *slash;
e2f2b36 @nicolasff Added RAW output.
authored Dec 26, 2010
79 const char *p;
2507fce @nicolasff Added JSON output.
authored Dec 21, 2010
80 int cmd_len;
4448b0f @nicolasff Proper decoding of URL parameters.
authored Jan 3, 2011
81 int param_count = 0, cur_param = 1, i;
2507fce @nicolasff Added JSON output.
authored Dec 21, 2010
82
83 struct cmd *cmd;
1ea7cd0 @nicolasff Special GET formatter for key + content-type key.
authored Jan 3, 2011
84
85 formatting_fun f_format;
2507fce @nicolasff Added JSON output.
authored Dec 21, 2010
86
87 /* count arguments */
9d2beac @nicolasff Added JSONP.
authored Dec 22, 2010
88 if(qmark) {
89 uri_len = qmark - uri;
90 }
2507fce @nicolasff Added JSON output.
authored Dec 21, 2010
91 for(p = uri; p && p < uri + uri_len; param_count++) {
89bb00f @nicolasff Start sending HTTP replies.
authored Jan 22, 2011
92 p = memchr(p+1, '/', uri_len - (p+1-uri));
2507fce @nicolasff Added JSON output.
authored Dec 21, 2010
93 }
94
a3ee623 @nicolasff File uploads using HTTP PUT.
authored Jan 9, 2011
95 if(body && body_len) { /* PUT request */
96 param_count++;
97 }
98
a298d3c @nicolasff Better client/cmd relationship.
authored Jan 25, 2011
99 client->cmd = cmd = cmd_new(param_count);
2507fce @nicolasff Added JSON output.
authored Dec 21, 2010
100
469e516 @nicolasff Removed content-type in another key, added suffixes instead.
authored Jan 4, 2011
101 /* get output formatting function */
bbec5c6 @nicolasff Bugfix, restored forced content-type.
authored Jan 22, 2011
102 uri_len = cmd_select_format(client, cmd, uri, uri_len, &f_format);
469e516 @nicolasff Removed content-type in another key, added suffixes instead.
authored Jan 4, 2011
103
104 /* check if we only have one command or more. */
a3aa1a9 @nicolasff Bugfix in RAW mode, more code doc.
authored Jan 3, 2011
105 slash = memchr(uri, '/', uri_len);
2507fce @nicolasff Added JSON output.
authored Dec 21, 2010
106 if(slash) {
107 cmd_len = slash - uri;
108 } else {
109 cmd_len = uri_len;
110 }
111
112 /* there is always a first parameter, it's the command name */
113 cmd->argv[0] = uri;
114 cmd->argv_len[0] = cmd_len;
115
2f5454c @nicolasff Merge branch 'master' into pubsub
authored Dec 29, 2010
116
9ffc519 @nicolasff Fix ACLs
authored Jan 22, 2011
117 /* check that the client is able to run this command */
118 if(!acl_allow_command(cmd, s->cfg, client)) {
de5c283 @nicolasff Added IP range restriction.
authored Dec 27, 2010
119 return -1;
120 }
121
6026811 @nicolasff Fix pub/sub. Valgrind is happy.
authored Jan 23, 2011
122 /* check if we have to split the connection */
4676cfe @nicolasff Refactoring.
authored Dec 29, 2010
123 if(cmd_is_subscribe(cmd)) {
6e3c424 @nicolasff Cleanup.
authored Jan 4, 2011
124
6026811 @nicolasff Fix pub/sub. Valgrind is happy.
authored Jan 22, 2011
125 client->sub = malloc(sizeof(struct subscription));
126 client->sub->s = s = server_copy(s);
127 client->sub->cmd = cmd;
2c980a2 @nicolasff First try.
authored Dec 26, 2010
128 }
129
a3aa1a9 @nicolasff Bugfix in RAW mode, more code doc.
authored Jan 3, 2011
130 /* no args (e.g. INFO command) */
2507fce @nicolasff Added JSON output.
authored Dec 21, 2010
131 if(!slash) {
a298d3c @nicolasff Better client/cmd relationship.
authored Jan 25, 2011
132 redisAsyncCommandArgv(s->ac, f_format, client, 1, cmd->argv, cmd->argv_len);
de5c283 @nicolasff Added IP range restriction.
authored Dec 27, 2010
133 return 0;
2507fce @nicolasff Added JSON output.
authored Dec 21, 2010
134 }
135 p = slash + 1;
136 while(p < uri + uri_len) {
137
138 const char *arg = p;
139 int arg_len;
d9d85ca @nicolasff Fix realloc bug.
authored Jan 22, 2011
140 char *next = memchr(arg, '/', uri_len - (arg-uri));
5ca45a5 @nicolasff Working custom handler.
authored Jan 3, 2011
141 if(!next || next > uri + uri_len) { /* last argument */
142 p = uri + uri_len;
143 arg_len = p - arg;
144 } else { /* found a slash */
2507fce @nicolasff Added JSON output.
authored Dec 21, 2010
145 arg_len = next - arg;
146 p = next + 1;
147 }
148
149 /* record argument */
4448b0f @nicolasff Proper decoding of URL parameters.
authored Jan 3, 2011
150 cmd->argv[cur_param] = decode_uri(arg, arg_len, &cmd->argv_len[cur_param], 1);
2507fce @nicolasff Added JSON output.
authored Dec 21, 2010
151 cur_param++;
152 }
153
a3ee623 @nicolasff File uploads using HTTP PUT.
authored Jan 9, 2011
154 if(body && body_len) { /* PUT request */
155 cmd->argv[cur_param] = body;
156 cmd->argv_len[cur_param] = body_len;
157 }
158
a3aa1a9 @nicolasff Bugfix in RAW mode, more code doc.
authored Jan 3, 2011
159 /* push command to Redis. */
a298d3c @nicolasff Better client/cmd relationship.
authored Jan 25, 2011
160 redisAsyncCommandArgv(s->ac, f_format, client, cmd->count, cmd->argv, cmd->argv_len);
1ad059d @nicolasff Started adding support for a custom content-type in a second key.
authored Jan 3, 2011
161
71bc9e3 @nicolasff Added a few content types, added support for ?type.
authored Jan 5, 2011
162 for(i = 1; i < cur_param; ++i) {
4448b0f @nicolasff Proper decoding of URL parameters.
authored Jan 3, 2011
163 free((char*)cmd->argv[i]);
164 }
165
de5c283 @nicolasff Added IP range restriction.
authored Dec 27, 2010
166 return 0;
2507fce @nicolasff Added JSON output.
authored Dec 21, 2010
167 }
168
6e3c424 @nicolasff Cleanup.
authored Jan 4, 2011
169
a3aa1a9 @nicolasff Bugfix in RAW mode, more code doc.
authored Jan 3, 2011
170 /**
6e3c424 @nicolasff Cleanup.
authored Jan 4, 2011
171 * Select Content-Type and processing function.
a3aa1a9 @nicolasff Bugfix in RAW mode, more code doc.
authored Jan 3, 2011
172 */
469e516 @nicolasff Removed content-type in another key, added suffixes instead.
authored Jan 4, 2011
173 int
bbec5c6 @nicolasff Bugfix, restored forced content-type.
authored Jan 22, 2011
174 cmd_select_format(struct http_client *client, struct cmd *cmd,
175 const char *uri, size_t uri_len, formatting_fun *f_format) {
469e516 @nicolasff Removed content-type in another key, added suffixes instead.
authored Jan 4, 2011
176
71bc9e3 @nicolasff Added a few content types, added support for ?type.
authored Jan 5, 2011
177 const char *ext;
469e516 @nicolasff Removed content-type in another key, added suffixes instead.
authored Jan 4, 2011
178 int ext_len = -1;
179 unsigned int i;
e2f2b36 @nicolasff Added RAW output.
authored Dec 26, 2010
180
6e3c424 @nicolasff Cleanup.
authored Jan 4, 2011
181 /* those are the available reply formats */
182 struct reply_format {
183 const char *s;
184 size_t sz;
185 formatting_fun f;
186 const char *ct;
187 };
469e516 @nicolasff Removed content-type in another key, added suffixes instead.
authored Jan 4, 2011
188 struct reply_format funs[] = {
189 {.s = "json", .sz = 4, .f = json_reply, .ct = "application/json"},
190 {.s = "raw", .sz = 3, .f = raw_reply, .ct = "binary/octet-stream"},
4abc4fc @nicolasff Support for .bin as binary/octet-stream
authored Jan 9, 2011
191
192 {.s = "bin", .sz = 3, .f = custom_type_reply, .ct = "binary/octet-stream"},
469e516 @nicolasff Removed content-type in another key, added suffixes instead.
authored Jan 4, 2011
193 {.s = "txt", .sz = 3, .f = custom_type_reply, .ct = "text/plain"},
194 {.s = "html", .sz = 4, .f = custom_type_reply, .ct = "text/html"},
71bc9e3 @nicolasff Added a few content types, added support for ?type.
authored Jan 5, 2011
195 {.s = "xhtml", .sz = 5, .f = custom_type_reply, .ct = "application/xhtml+xml"},
196 {.s = "xml", .sz = 3, .f = custom_type_reply, .ct = "text/xml"},
197
469e516 @nicolasff Removed content-type in another key, added suffixes instead.
authored Jan 4, 2011
198 {.s = "png", .sz = 3, .f = custom_type_reply, .ct = "image/png"},
71bc9e3 @nicolasff Added a few content types, added support for ?type.
authored Jan 5, 2011
199 {.s = "jpg", .sz = 3, .f = custom_type_reply, .ct = "image/jpeg"},
200 {.s = "jpeg", .sz = 4, .f = custom_type_reply, .ct = "image/jpeg"},
469e516 @nicolasff Removed content-type in another key, added suffixes instead.
authored Jan 4, 2011
201 };
e2f2b36 @nicolasff Added RAW output.
authored Dec 26, 2010
202
6e3c424 @nicolasff Cleanup.
authored Jan 4, 2011
203 /* default */
1ea7cd0 @nicolasff Special GET formatter for key + content-type key.
authored Jan 3, 2011
204 *f_format = json_reply;
469e516 @nicolasff Removed content-type in another key, added suffixes instead.
authored Jan 4, 2011
205
206 /* find extension */
207 for(ext = uri + uri_len - 1; ext != uri && *ext != '/'; --ext) {
208 if(*ext == '.') {
209 ext++;
210 ext_len = uri + uri_len - ext;
e2f2b36 @nicolasff Added RAW output.
authored Dec 26, 2010
211 break;
212 }
213 }
6e3c424 @nicolasff Cleanup.
authored Jan 4, 2011
214 if(!ext_len) return uri_len; /* nothing found */
469e516 @nicolasff Removed content-type in another key, added suffixes instead.
authored Jan 4, 2011
215
216 /* find function for the given extension */
217 for(i = 0; i < sizeof(funs)/sizeof(funs[0]); ++i) {
218 if(ext_len == (int)funs[i].sz && strncmp(ext, funs[i].s, ext_len) == 0) {
102f9fc @nicolasff Started adding Accept support.
authored Jan 5, 2011
219
220 if(cmd->mime_free) free(cmd->mime);
221 cmd->mime = (char*)funs[i].ct;
222 cmd->mime_free = 0;
223
469e516 @nicolasff Removed content-type in another key, added suffixes instead.
authored Jan 4, 2011
224 *f_format = funs[i].f;
225 }
226 }
71bc9e3 @nicolasff Added a few content types, added support for ?type.
authored Jan 5, 2011
227
6026811 @nicolasff Fix pub/sub. Valgrind is happy.
authored Jan 22, 2011
228 /* the user can force it with ?type=some/thing */
b5b79c9 @nicolasff Cleanup.
authored Jan 25, 2011
229 if(client->query_string.type.s) {
bbec5c6 @nicolasff Bugfix, restored forced content-type.
authored Jan 22, 2011
230 *f_format = custom_type_reply;
b5b79c9 @nicolasff Cleanup.
authored Jan 25, 2011
231 cmd->mime = strdup(client->query_string.type.s);
bbec5c6 @nicolasff Bugfix, restored forced content-type.
authored Jan 22, 2011
232 cmd->mime_free = 1;
71bc9e3 @nicolasff Added a few content types, added support for ?type.
authored Jan 5, 2011
233 }
bbec5c6 @nicolasff Bugfix, restored forced content-type.
authored Jan 22, 2011
234
469e516 @nicolasff Removed content-type in another key, added suffixes instead.
authored Jan 4, 2011
235 return uri_len - ext_len - 1;
e2f2b36 @nicolasff Added RAW output.
authored Dec 26, 2010
236 }
4676cfe @nicolasff Refactoring.
authored Dec 29, 2010
237
238 int
239 cmd_is_subscribe(struct cmd *cmd) {
240
6026811 @nicolasff Fix pub/sub. Valgrind is happy.
authored Jan 22, 2011
241 /*
242 if(cmd->started_responding) {
243 return 1;
244 }
245 */
246
981fd54 @nicolasff Fix Keep-Alive.
authored Jan 22, 2011
247 if(cmd->count >= 1 &&
248 (strncasecmp(cmd->argv[0], "SUBSCRIBE", cmd->argv_len[0]) == 0 ||
249 strncasecmp(cmd->argv[0], "PSUBSCRIBE", cmd->argv_len[0]) == 0)) {
4676cfe @nicolasff Refactoring.
authored Dec 29, 2010
250 return 1;
251 }
252 return 0;
253 }
Something went wrong with that request. Please try again.