Merge branch 'put-upload'

master
Nicolas Favre-Felix 14 years ago
commit 58b8ac2e3c

@ -32,6 +32,7 @@ curl -d "GET/hello" http://127.0.0.1:7379/
* URL-encoded parameters for binary data or slashes. For instance, `%2f` is decoded as `/` but not used as a command separator.
* Logs, with a configurable verbosity.
* Cross-origin XHR, if compiled with libevent2 (for `OPTIONS` support).
* File upload with PUT, if compiled with libevent2 (for `PUT` support).
# Ideas, TODO...
* Support PUT, DELETE, HEAD, OPTIONS? How? For which commands?
@ -41,7 +42,6 @@ curl -d "GET/hello" http://127.0.0.1:7379/
* Provide timeout (this needs to be added to hiredis first.)
* Multi-server support, using consistent hashing.
* Add WebSocket support (with which protocol?)
* Allow file upload with PUT? Saving a file in Redis using the `SET` command should be easy to do with cURL.
* Send your ideas using the github tracker, on twitter [@yowgi](http://twitter.com/yowgi) or by mail to n.favrefelix@gmail.com.
# HTTP error codes
@ -196,3 +196,51 @@ curl -v "http://127.0.0.1:7379/GET/big-file?type=application/pdf"
[...]
</pre>
# File upload (only with libevent 2)
Webdis supports file upload using HTTP PUT. The command URI is slightly different, as the last argument is taken from the HTTP body.
For example: instead of `/SET/key/value`, the URI becomes `/SET/key` and the value is the entirety of the body. This works for other commands such as LPUSH, etc.
**Uploading a binary file to webdis**:
<pre>
$ file redis-logo.png
redis-logo.png: PNG image, 513 x 197, 8-bit/color RGBA, non-interlaced
$ wc -c redis-logo.png
16744 redis-logo.png
$ curl -v --upload-file redis-logo.png http://127.0.0.1:7379/SET/logo
[...]
&gt; PUT /SET/logo HTTP/1.1
&gt; User-Agent: curl/7.19.7 (x86_64-pc-linux-gnu) libcurl/7.19.7 OpenSSL/0.9.8k zlib/1.2.3.3 libidn/1.15
&gt; Host: 127.0.0.1:7379
&gt; Accept: */*
&gt; Content-Length: 16744
&gt; Expect: 100-continue
&gt;
&lt; HTTP/1.1 100 Continue
&lt; HTTP/1.1 200 OK
&lt; Content-Type: application/json
&lt; ETag: "0db1124cf79ffeb80aff6d199d5822f8"
&lt; Date: Sun, 09 Jan 2011 16:48:19 GMT
&lt; Content-Length: 19
&lt;
{"SET":[true,"OK"]}
$ curl -vs http://127.0.0.1:7379/GET/logo.png -o out.png
&gt; GET /GET/logo.png HTTP/1.1
&gt; User-Agent: curl/7.19.7 (x86_64-pc-linux-gnu) libcurl/7.19.7 OpenSSL/0.9.8k zlib/1.2.3.3 libidn/1.15
&gt; Host: 127.0.0.1:7379
&gt; Accept: */*
&gt;
&lt; HTTP/1.1 200 OK
&lt; Content-Type: image/png
&lt; ETag: "1991df597267d70bf9066a7d11969da0"
&lt; Date: Sun, 09 Jan 2011 16:50:51 GMT
&lt; Content-Length: 16744
$ md5sum redis-logo.png out.png
1991df597267d70bf9066a7d11969da0 redis-logo.png
1991df597267d70bf9066a7d11969da0 out.png
</pre>
The file was uploaded and re-downloaded properly: it has the same hash and the content-type was set properly thanks to the `.png` extension.

13
cmd.c

@ -88,7 +88,7 @@ decode_uri(const char *uri, size_t length, size_t *out_len, int always_decode_pl
int
cmd_run(struct server *s, struct evhttp_request *rq,
const char *uri, size_t uri_len) {
const char *uri, size_t uri_len, const char *body, size_t body_len) {
char *qmark = strchr(uri, '?');
char *slash;
@ -108,6 +108,10 @@ cmd_run(struct server *s, struct evhttp_request *rq,
p = strchr(p+1, '/');
}
if(body && body_len) { /* PUT request */
param_count++;
}
cmd = cmd_new(rq, param_count);
/* parse URI parameters */
@ -169,6 +173,11 @@ cmd_run(struct server *s, struct evhttp_request *rq,
cur_param++;
}
if(body && body_len) { /* PUT request */
cmd->argv[cur_param] = body;
cmd->argv_len[cur_param] = body_len;
}
/* push command to Redis. */
redisAsyncCommandArgv(s->ac, f_format, cmd, cmd->count, cmd->argv, cmd->argv_len);
@ -201,6 +210,8 @@ cmd_select_format(struct cmd *cmd, const char *uri, size_t uri_len, formatting_f
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"},
{.s = "bin", .sz = 3, .f = custom_type_reply, .ct = "binary/octet-stream"},
{.s = "txt", .sz = 3, .f = custom_type_reply, .ct = "text/plain"},
{.s = "html", .sz = 4, .f = custom_type_reply, .ct = "text/html"},
{.s = "xhtml", .sz = 5, .f = custom_type_reply, .ct = "application/xhtml+xml"},

@ -44,7 +44,8 @@ cmd_free(struct cmd *c);
int
cmd_run(struct server *s, struct evhttp_request *rq,
const char *uri, size_t uri_len);
const char *uri, size_t uri_len,
const char *body, size_t body_len);
int
cmd_select_format(struct cmd *cmd, const char *uri, size_t uri_len, formatting_fun *f_format);

@ -148,15 +148,24 @@ on_request(struct evhttp_request *rq, void *ctx) {
switch(rq->type) {
case EVHTTP_REQ_GET:
slog(s, WEBDIS_DEBUG, uri);
ret = cmd_run(s, rq, 1+uri, strlen(uri)-1);
ret = cmd_run(s, rq, 1+uri, strlen(uri)-1, NULL, 0);
break;
case EVHTTP_REQ_POST:
slog(s, WEBDIS_DEBUG, uri);
ret = cmd_run(s, rq,
(const char*)EVBUFFER_DATA(rq->input_buffer),
EVBUFFER_LENGTH(rq->input_buffer), NULL, 0);
break;
#ifdef _EVENT2_HTTP_H_
case EVHTTP_REQ_PUT:
slog(s, WEBDIS_DEBUG, uri);
ret = cmd_run(s, rq, 1+uri, strlen(uri)-1,
(const char*)EVBUFFER_DATA(rq->input_buffer),
EVBUFFER_LENGTH(rq->input_buffer));
break;
#endif
#ifdef _EVENT2_HTTP_H_
case EVHTTP_REQ_OPTIONS:

Loading…
Cancel
Save