Skip to content
Browse files

File uploads using HTTP PUT.

  • Loading branch information...
1 parent 4abc4fc commit a3ee623c6943bf74c5c91248c351d86b3f583aa3 @nicolasff committed Jan 9, 2011
Showing with 71 additions and 4 deletions.
  1. +49 −1 README.markdown
  2. +10 −1 cmd.c
  3. +2 −1 cmd.h
  4. +10 −1 server.c
View
50 README.markdown
@@ -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.
View
11 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);
View
3 cmd.h
@@ -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);
View
11 server.c
@@ -132,15 +132,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
default:
slog(s, WEBDIS_DEBUG, "405");

0 comments on commit a3ee623

Please sign in to comment.
Something went wrong with that request. Please try again.