summaryrefslogtreecommitdiff
path: root/core/protocol.c
diff options
context:
space:
mode:
authorSokolov Yura aka funny_falcon <funny.falcon@gmail.com>2016-04-06 21:11:10 +0300
committerSokolov Yura aka funny_falcon <funny.falcon@gmail.com>2016-04-06 21:11:10 +0300
commit6d1535f910d188c07289ab7ddee5df9d4b85d462 (patch)
tree9a940df187799066474f594fc122a3a369c4f5ed /core/protocol.c
parent122be0e224fcc04f3d2d51398eebcd1f3094ae8b (diff)
downloaduwsgi-6d1535f910d188c07289ab7ddee5df9d4b85d462.tar.gz
improve handling http byte range requests
refactor to make range fixing algorithm reusable. add flag field for parsed/not parsed/valid/invalid state of range header. properly handle suffix-range request. send 416 when range is not satisfable.
Diffstat (limited to 'core/protocol.c')
-rw-r--r--core/protocol.c34
1 files changed, 27 insertions, 7 deletions
diff --git a/core/protocol.c b/core/protocol.c
index e56ccc30..55ab1633 100644
--- a/core/protocol.c
+++ b/core/protocol.c
@@ -228,7 +228,8 @@ static int uwsgi_proto_check_9(struct wsgi_request *wsgi_req, char *key, char *b
return 0;
}
-static void uwsgi_parse_http_range(char *buf, uint16_t len, size_t *from, size_t *to) {
+static void uwsgi_parse_http_range(char *buf, uint16_t len, enum uwsgi_range *parsed, int64_t *from, int64_t *to) {
+ *parsed = UWSGI_RANGE_INVALID;
*from = 0;
*to = 0;
uint16_t rlen = 0;
@@ -248,18 +249,37 @@ static void uwsgi_parse_http_range(char *buf, uint16_t len, size_t *from, size_t
rlen -= 6;
char *dash = memchr(range, '-', rlen);
if (!dash) return;
- *from = uwsgi_str_num(range, dash-range);
- *to = uwsgi_str_num(dash+1, rlen - ((dash+1)-range));
- if (*to > 0 && *from > *to) {
- *from = 0;
- *to = 0;
+ if (dash != range) {
+ *from = uwsgi_str_num(range, dash-range);
+ if (dash == range+(rlen-1)) {
+ /* RFC7233 prefix range
+ * `bytes=start-` is a same as `byte=start-0x7ffffffffffffff`
+ */
+ *to = INT64_MAX;
+ } else {
+ *to = uwsgi_str_num(dash+1, rlen - ((dash+1)-range));
+ }
+ if (*to >= *from) {
+ *parsed = UWSGI_RANGE_PARSED;
+ } else {
+ *from = 0;
+ *to = 0;
+ }
+ } else {
+ /* RFC7233 suffix-byte-range-spec: `bytes=-500` */
+ *from = -(int64_t)uwsgi_str_num(dash+1, rlen - ((dash+1)-range));
+ if (*from < 0) {
+ *to = INT64_MAX;
+ *parsed = UWSGI_RANGE_PARSED;
+ }
}
}
static int uwsgi_proto_check_10(struct wsgi_request *wsgi_req, char *key, char *buf, uint16_t len) {
if (uwsgi.honour_range && !uwsgi_proto_key("HTTP_RANGE", 10)) {
- uwsgi_parse_http_range(buf, len, &wsgi_req->range_from, &wsgi_req->range_to);
+ uwsgi_parse_http_range(buf, len, &wsgi_req->range_parsed,
+ &wsgi_req->range_from, &wsgi_req->range_to);
return 0;
}