File uploads using HTTP PUT.

master
Nicolas Favre-Felix 14 years ago
parent 4abc4fc4f8
commit a3ee623c69

@ -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. * 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. * Logs, with a configurable verbosity.
* Cross-origin XHR, if compiled with libevent2 (for `OPTIONS` support). * Cross-origin XHR, if compiled with libevent2 (for `OPTIONS` support).
* File upload with PUT, if compiled with libevent2 (for `PUT` support).
# Ideas, TODO... # Ideas, TODO...
* Support PUT, DELETE, HEAD, OPTIONS? How? For which commands? * 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.) * Provide timeout (this needs to be added to hiredis first.)
* Multi-server support, using consistent hashing. * Multi-server support, using consistent hashing.
* Add WebSocket support (with which protocol?) * 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. * 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 # HTTP error codes
@ -196,3 +196,51 @@ curl -v "http://127.0.0.1:7379/GET/big-file?type=application/pdf"
[...] [...]
</pre> </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.

11
cmd.c

@ -88,7 +88,7 @@ decode_uri(const char *uri, size_t length, size_t *out_len, int always_decode_pl
int int
cmd_run(struct server *s, struct evhttp_request *rq, 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 *qmark = strchr(uri, '?');
char *slash; char *slash;
@ -108,6 +108,10 @@ cmd_run(struct server *s, struct evhttp_request *rq,
p = strchr(p+1, '/'); p = strchr(p+1, '/');
} }
if(body && body_len) { /* PUT request */
param_count++;
}
cmd = cmd_new(rq, param_count); cmd = cmd_new(rq, param_count);
/* parse URI parameters */ /* parse URI parameters */
@ -169,6 +173,11 @@ cmd_run(struct server *s, struct evhttp_request *rq,
cur_param++; cur_param++;
} }
if(body && body_len) { /* PUT request */
cmd->argv[cur_param] = body;
cmd->argv_len[cur_param] = body_len;
}
/* push command to Redis. */ /* push command to Redis. */
redisAsyncCommandArgv(s->ac, f_format, cmd, cmd->count, cmd->argv, cmd->argv_len); redisAsyncCommandArgv(s->ac, f_format, cmd, cmd->count, cmd->argv, cmd->argv_len);

@ -44,7 +44,8 @@ cmd_free(struct cmd *c);
int int
cmd_run(struct server *s, struct evhttp_request *rq, 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 int
cmd_select_format(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);

@ -132,15 +132,24 @@ on_request(struct evhttp_request *rq, void *ctx) {
switch(rq->type) { switch(rq->type) {
case EVHTTP_REQ_GET: case EVHTTP_REQ_GET:
slog(s, WEBDIS_DEBUG, uri); 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; break;
case EVHTTP_REQ_POST: case EVHTTP_REQ_POST:
slog(s, WEBDIS_DEBUG, uri); slog(s, WEBDIS_DEBUG, uri);
ret = cmd_run(s, rq, 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), (const char*)EVBUFFER_DATA(rq->input_buffer),
EVBUFFER_LENGTH(rq->input_buffer)); EVBUFFER_LENGTH(rq->input_buffer));
break; break;
#endif
default: default:
slog(s, WEBDIS_DEBUG, "405"); slog(s, WEBDIS_DEBUG, "405");

Loading…
Cancel
Save