Range Responses

This commit is contained in:
2020-12-28 19:11:56 +01:00
parent 3663a6064b
commit 6fa62aeb4d
3 changed files with 60 additions and 8 deletions

View File

@ -198,7 +198,50 @@ int client_request_handler(sock *client, unsigned long client_num, unsigned int
goto respond; goto respond;
} }
// TODO Ranges char *range = http_get_header_field(&req.hdr, "Range");
if (range != NULL) {
if (strlen(range) <= 6 || strncmp(range, "bytes=", 6) != 0) {
res.status = http_get_status(416);
http_remove_header_field(&res.hdr, "Content-Type", HTTP_REMOVE_ALL);
http_remove_header_field(&res.hdr, "Last-Modified", HTTP_REMOVE_ALL);
http_remove_header_field(&res.hdr, "ETag", HTTP_REMOVE_ALL);
http_remove_header_field(&res.hdr, "Cache-Control", HTTP_REMOVE_ALL);
goto respond;
}
range += 6;
char *ptr = strchr(range, '-');
if (ptr == NULL) {
res.status = http_get_status(416);
goto respond;
}
file = fopen(uri.filename, "rb");
fseek(file, 0, SEEK_END);
unsigned long file_len = ftell(file);
fseek(file, 0, SEEK_SET);
if (file_len == 0) {
content_length = 0;
goto respond;
}
long num1 = 0;
long num2 = (long) file_len - 1;
if (ptr != range) num1 = (long) strtoul(range, NULL, 10);
if (ptr[1] != 0) num2 = (long) strtoul(ptr + 1, NULL, 10);
if (num1 >= file_len || num2 >= file_len || num1 > num2) {
res.status = http_get_status(416);
goto respond;
}
sprintf(buf0, "bytes %li-%li/%li", num1, num2, file_len);
http_add_header_field(&res.hdr, "Content-Range", buf0);
res.status = http_get_status(206);
fseek(file, num1, SEEK_SET);
content_length = num2 - num1 + 1;
goto respond;
}
char *accept_encoding = http_get_header_field(&req.hdr, "Accept-Encoding"); char *accept_encoding = http_get_header_field(&req.hdr, "Accept-Encoding");
if (uri.meta->filename_comp[0] != 0 && accept_encoding != NULL && strstr(accept_encoding, "deflate") != NULL) { if (uri.meta->filename_comp[0] != 0 && accept_encoding != NULL && strstr(accept_encoding, "deflate") != NULL) {
file = fopen(uri.meta->filename_comp, "rb"); file = fopen(uri.meta->filename_comp, "rb");
@ -340,6 +383,9 @@ int client_request_handler(sock *client, unsigned long client_num, unsigned int
} else if (file != NULL) { } else if (file != NULL) {
while (snd_len < content_length) { while (snd_len < content_length) {
len = fread(&buffer, 1, CHUNK_SIZE, file); len = fread(&buffer, 1, CHUNK_SIZE, file);
if (snd_len + len > content_length) {
len = content_length - snd_len;
}
if (client->enc) { if (client->enc) {
ret = SSL_write(client->ssl, buffer, (int) len); ret = SSL_write(client->ssl, buffer, (int) len);
if (ret <= 0) { if (ret <= 0) {

View File

@ -45,11 +45,11 @@ int http_parse_header_field(http_hdr *hdr, const char *buf, const char *end_ptr)
char *pos1 = memchr(buf, ':', end_ptr - buf); char *pos1 = memchr(buf, ':', end_ptr - buf);
char *pos2; char *pos2;
if (pos1 == NULL) { if (pos1 == NULL) {
print(ERR_STR "Unable to parse header: Invalid version" CLR_STR); print(ERR_STR "Unable to parse header" CLR_STR);
return 3; return 3;
} }
unsigned long len = pos1 - buf; long len = pos1 - buf;
hdr->fields[hdr->field_num][0] = malloc(len + 1); hdr->fields[hdr->field_num][0] = malloc(len + 1);
sprintf(hdr->fields[hdr->field_num][0], "%.*s", (int) len, buf); sprintf(hdr->fields[hdr->field_num][0], "%.*s", (int) len, buf);
http_to_camel_case(hdr->fields[hdr->field_num][0], HTTP_CAMEL); http_to_camel_case(hdr->fields[hdr->field_num][0], HTTP_CAMEL);
@ -59,10 +59,15 @@ int http_parse_header_field(http_hdr *hdr, const char *buf, const char *end_ptr)
while (pos1[0] == ' ') pos1++; while (pos1[0] == ' ') pos1++;
while (pos2[0] == ' ') pos2--; while (pos2[0] == ' ') pos2--;
len = pos2 - pos1 + 1; len = pos2 - pos1 + 1;
hdr->fields[hdr->field_num][1] = malloc(len + 1);
sprintf(hdr->fields[hdr->field_num][1], "%.*s", (int) len, pos1);
hdr->field_num++;
if (len <= 0) {
hdr->fields[hdr->field_num][1] = malloc(1);
hdr->fields[hdr->field_num][1][0] = 0;
} else {
hdr->fields[hdr->field_num][1] = malloc(len + 1);
sprintf(hdr->fields[hdr->field_num][1], "%.*s", (int) len, pos1);
}
hdr->field_num++;
return 0; return 0;
} }
@ -247,7 +252,7 @@ http_status *http_get_status(unsigned short status_code) {
} }
http_error_msg *http_get_error_msg(unsigned short status_code) { http_error_msg *http_get_error_msg(unsigned short status_code) {
for (int i = 0; i < sizeof(http_error_messages) / sizeof(http_get_error_msg); i++) { for (int i = 0; i < sizeof(http_error_messages) / sizeof(http_error_msg); i++) {
if (http_error_messages[i].code == status_code) { if (http_error_messages[i].code == status_code) {
return &http_error_messages[i]; return &http_error_messages[i];
} }

View File

@ -81,7 +81,7 @@ http_status http_statuses[] = {
{413, "Client Error", "Request Entity Too Large"}, {413, "Client Error", "Request Entity Too Large"},
{414, "Client Error", "Request-URI Too Long"}, {414, "Client Error", "Request-URI Too Long"},
{415, "Client Error", "Unsupported Media Type"}, {415, "Client Error", "Unsupported Media Type"},
{416, "Client Error", "Requested Range Not Satisfiable"}, {416, "Client Error", "Range Not Satisfiable"},
{417, "Client Error", "Expectation Failed"}, {417, "Client Error", "Expectation Failed"},
{500, "Server Error", "Internal Server Error"}, {500, "Server Error", "Internal Server Error"},
@ -108,6 +108,7 @@ http_error_msg http_error_messages[] = {
{413, "The server is refusing to process a request because the request entity is larger than the server is willing or able to process."}, {413, "The server is refusing to process a request because the request entity is larger than the server is willing or able to process."},
{414, "The server is refusing to service the request because the Request-URI is longer than the server is willing to interpret."}, {414, "The server is refusing to service the request because the Request-URI is longer than the server is willing to interpret."},
{415, "The server is refusing to service the request because the entity of the request is in a format not supported by the requested resource for the requested method."}, {415, "The server is refusing to service the request because the entity of the request is in a format not supported by the requested resource for the requested method."},
{416, "None of the ranges in the request's Range header field overlap the current extent of the selected resource or that the set of ranges requested has been rejected due to invalid ranges or an excessive request of small or overlapping ranges."},
{417, "The expectation given in an Expect request-header field could not be met by this server, or, if the server is a proxy, the server has unambiguous evidence that the request could not be met by the next-hop server."}, {417, "The expectation given in an Expect request-header field could not be met by this server, or, if the server is a proxy, the server has unambiguous evidence that the request could not be met by the next-hop server."},
{500, "The server encountered an unexpected condition which prevented it from fulfilling the request."}, {500, "The server encountered an unexpected condition which prevented it from fulfilling the request."},