mirror of
https://github.com/Relintai/pandemonium_engine.git
synced 2025-04-13 23:30:47 +02:00
Implemented range requests for the HTTPServerSimple. It does work in fiefox, however wget seems to choke on it. This will be fixed later.
This commit is contained in:
parent
4d6b2f6f55
commit
978e49a289
@ -281,11 +281,124 @@ void HTTPServerConnection::send_file(Ref<WebServerRequest> request, const String
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
//String range = request->get_htt
|
_file_start = 0;
|
||||||
|
_file_length = r->_sending_file_fa->get_len();
|
||||||
|
_file_end = _file_length;
|
||||||
|
uint64_t content_length = _file_length;
|
||||||
|
String result_content_range_header;
|
||||||
|
|
||||||
|
String range_header = request->get_header_parameter("range");
|
||||||
|
|
||||||
|
if (!range_header.empty()) {
|
||||||
|
//Range: <unit>=<range-start>-
|
||||||
|
//Range: <unit>=<range-start>-<range-end>
|
||||||
|
//Range: <unit>=<range-start>-<range-end>, <range-start>-<range-end>
|
||||||
|
//Range: <unit>=<range-start>-<range-end>, <range-start>-<range-end>, <range-start>-<range-end>
|
||||||
|
//Range: <unit>=-<suffix-length>
|
||||||
|
|
||||||
|
//Range: bytes=200-999, 2000-2499, 9500-
|
||||||
|
//range_header -> "bytes=200-999, 2000-2499, 9500-"
|
||||||
|
|
||||||
|
//Currently only bytes units are registered which are offsets (zero-indexed & inclusive). If the requested data has a content coding applied, each byte range represents the encoded sequence of bytes, not the bytes that would be obtained after decoding.
|
||||||
|
|
||||||
|
if (!range_header.begins_with("bytes=")) {
|
||||||
|
//If the ranges are invalid, the server returns the 416 Range Not Satisfiable error.
|
||||||
|
close_file(request);
|
||||||
|
request->send_error(HTTPServerEnums::HTTP_STATUS_CODE_416_REQUESTED_RANGE_NOT_SATISFIABLE);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
//range_noprefix -> "200-999, 2000-2499, 9500-"
|
||||||
|
String range_noprefix = range_header.substr_index(5, range_header.size() - 1);
|
||||||
|
|
||||||
|
Vector<String> ranges = range_header.split(",");
|
||||||
|
|
||||||
|
if (ranges.size() == 0) {
|
||||||
|
//If the ranges are invalid, the server returns the 416 Range Not Satisfiable error.
|
||||||
|
close_file(request);
|
||||||
|
request->send_error(HTTPServerEnums::HTTP_STATUS_CODE_416_REQUESTED_RANGE_NOT_SATISFIABLE);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// only handle the first one. Handling more creates extreme amounts of unnecessary complexity.
|
||||||
|
|
||||||
|
//range -> "200-999"
|
||||||
|
String range = ranges[0].strip_edges();
|
||||||
|
|
||||||
|
Vector<String> range_values = range.split("-");
|
||||||
|
|
||||||
|
if (range_values.size() != 2) {
|
||||||
|
//If the ranges are invalid, the server returns the 416 Range Not Satisfiable error.
|
||||||
|
close_file(request);
|
||||||
|
request->send_error(HTTPServerEnums::HTTP_STATUS_CODE_416_REQUESTED_RANGE_NOT_SATISFIABLE);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
//9500-
|
||||||
|
|
||||||
|
bool error = false;
|
||||||
|
uint64_t start_value = 0;
|
||||||
|
|
||||||
|
if (!range_values[0].empty() && !range_values[0].is_valid_unsigned_integer()) {
|
||||||
|
start_value = range_values[0].to_int64();
|
||||||
|
} else {
|
||||||
|
error = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!error && start_value >= _file_length) {
|
||||||
|
error = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!error) {
|
||||||
|
_file_start = start_value;
|
||||||
|
|
||||||
|
r->_sending_file_fa->seek(_file_start);
|
||||||
|
|
||||||
|
if (!range_values[1].empty()) {
|
||||||
|
//200-999
|
||||||
|
|
||||||
|
uint64_t end_value = 0;
|
||||||
|
|
||||||
|
if (!range_values[1].is_valid_unsigned_integer()) {
|
||||||
|
end_value = range_values[1].to_int64();
|
||||||
|
} else {
|
||||||
|
error = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!error && end_value > _file_length) {
|
||||||
|
error = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!error) {
|
||||||
|
_file_end = end_value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (error) {
|
||||||
|
//If the ranges are invalid, the server returns the 416 Range Not Satisfiable error.
|
||||||
|
close_file(request);
|
||||||
|
request->send_error(HTTPServerEnums::HTTP_STATUS_CODE_416_REQUESTED_RANGE_NOT_SATISFIABLE);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (request->get_status_code() == 200) {
|
||||||
|
request->set_status_code(HTTPServerEnums::HTTP_STATUS_CODE_206_PARTIAL_CONTENT);
|
||||||
|
}
|
||||||
|
|
||||||
|
content_length = _file_end - _file_start;
|
||||||
|
|
||||||
|
//Content-Range: <unit> <range-start>-<range-end>/<size> (<size> = The total length of the document (or '*' if unknown).)
|
||||||
|
|
||||||
|
result_content_range_header = "Content-Range: bytes " + itos(_file_start) + "-" + itos(_file_end) + "/" + itos(_file_length) + +"\r\n";
|
||||||
|
}
|
||||||
|
|
||||||
String s = "HTTP/1.1 " + HTTPServerEnums::get_status_code_header_string(request->get_status_code()) + "\r\n";
|
String s = "HTTP/1.1 " + HTTPServerEnums::get_status_code_header_string(request->get_status_code()) + "\r\n";
|
||||||
|
|
||||||
|
if (!result_content_range_header.empty()) {
|
||||||
|
s += result_content_range_header;
|
||||||
|
}
|
||||||
|
|
||||||
if (!custom_headers.has("Connection")) {
|
if (!custom_headers.has("Connection")) {
|
||||||
if (has_more_messages()) {
|
if (has_more_messages()) {
|
||||||
s += "Connection: keep-alive\r\n";
|
s += "Connection: keep-alive\r\n";
|
||||||
@ -307,9 +420,7 @@ void HTTPServerConnection::send_file(Ref<WebServerRequest> request, const String
|
|||||||
s += "Content-Type: " + ctype + "\r\n";
|
s += "Content-Type: " + ctype + "\r\n";
|
||||||
}
|
}
|
||||||
|
|
||||||
uint64_t file_length = r->_sending_file_fa->get_len();
|
s += "Content-Length: " + itos(content_length) + "\r\n";
|
||||||
|
|
||||||
s += "Content-Length: " + itos(file_length) + "\r\n";
|
|
||||||
|
|
||||||
for (int i = 0; i < request->response_get_cookie_count(); ++i) {
|
for (int i = 0; i < request->response_get_cookie_count(); ++i) {
|
||||||
Ref<WebServerCookie> cookie = request->response_get_cookie(i);
|
Ref<WebServerCookie> cookie = request->response_get_cookie(i);
|
||||||
@ -355,7 +466,10 @@ void HTTPServerConnection::update_send_file(Ref<SimpleWebServerRequest> request)
|
|||||||
if (_file_buffer_start == _file_buffer_end) {
|
if (_file_buffer_start == _file_buffer_end) {
|
||||||
_file_buffer_start = 0;
|
_file_buffer_start = 0;
|
||||||
|
|
||||||
_file_buffer_end = request->_sending_file_fa->get_buffer(_file_send_buffer, 4096);
|
uint64_t remaining = _file_end - request->_sending_file_fa->get_position();
|
||||||
|
uint64_t read_length = MIN(remaining, 4096);
|
||||||
|
|
||||||
|
_file_buffer_end = request->_sending_file_fa->get_buffer(_file_send_buffer, read_length);
|
||||||
|
|
||||||
if (_file_buffer_end == 0) {
|
if (_file_buffer_end == 0) {
|
||||||
//finished
|
//finished
|
||||||
@ -378,9 +492,8 @@ void HTTPServerConnection::update_send_file(Ref<SimpleWebServerRequest> request)
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (err != OK) {
|
if (err != OK) {
|
||||||
|
close_file(request);
|
||||||
close();
|
close();
|
||||||
memdelete(request->_sending_file_fa);
|
|
||||||
request->_sending_file_fa = NULL;
|
|
||||||
_file_buffer_start = 0;
|
_file_buffer_start = 0;
|
||||||
_file_buffer_end = 0;
|
_file_buffer_end = 0;
|
||||||
return;
|
return;
|
||||||
@ -394,8 +507,7 @@ void HTTPServerConnection::update_send_file(Ref<SimpleWebServerRequest> request)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
memdelete(request->_sending_file_fa);
|
close_file(request);
|
||||||
request->_sending_file_fa = NULL;
|
|
||||||
|
|
||||||
_file_buffer_start = 0;
|
_file_buffer_start = 0;
|
||||||
_file_buffer_end = 0;
|
_file_buffer_end = 0;
|
||||||
@ -432,6 +544,13 @@ bool HTTPServerConnection::has_more_messages() {
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void HTTPServerConnection::close_file(Ref<SimpleWebServerRequest> request) {
|
||||||
|
if (request.is_valid() && request->_sending_file_fa) {
|
||||||
|
memdelete(request->_sending_file_fa);
|
||||||
|
request->_sending_file_fa = NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
HTTPServerConnection::HTTPServerConnection() {
|
HTTPServerConnection::HTTPServerConnection() {
|
||||||
_web_server = nullptr;
|
_web_server = nullptr;
|
||||||
_http_server = nullptr;
|
_http_server = nullptr;
|
||||||
@ -452,6 +571,9 @@ HTTPServerConnection::HTTPServerConnection() {
|
|||||||
|
|
||||||
_file_buffer_start = 0;
|
_file_buffer_start = 0;
|
||||||
_file_buffer_end = 0;
|
_file_buffer_end = 0;
|
||||||
|
_file_start = 0;
|
||||||
|
_file_end = 0;
|
||||||
|
_file_length = 0;
|
||||||
}
|
}
|
||||||
HTTPServerConnection::~HTTPServerConnection() {
|
HTTPServerConnection::~HTTPServerConnection() {
|
||||||
}
|
}
|
||||||
|
@ -69,6 +69,8 @@ public:
|
|||||||
|
|
||||||
bool has_more_messages();
|
bool has_more_messages();
|
||||||
|
|
||||||
|
void close_file(Ref<SimpleWebServerRequest> request);
|
||||||
|
|
||||||
HTTPServerConnection();
|
HTTPServerConnection();
|
||||||
~HTTPServerConnection();
|
~HTTPServerConnection();
|
||||||
|
|
||||||
@ -92,6 +94,11 @@ public:
|
|||||||
uint8_t _file_send_buffer[4096];
|
uint8_t _file_send_buffer[4096];
|
||||||
uint64_t _file_buffer_start;
|
uint64_t _file_buffer_start;
|
||||||
uint64_t _file_buffer_end;
|
uint64_t _file_buffer_end;
|
||||||
|
|
||||||
|
uint64_t _file_start;
|
||||||
|
uint64_t _file_end;
|
||||||
|
uint64_t _file_length;
|
||||||
|
|
||||||
int _file_buffer_send_max_consecutive_loops;
|
int _file_buffer_send_max_consecutive_loops;
|
||||||
|
|
||||||
uint64_t _timeout_usec;
|
uint64_t _timeout_usec;
|
||||||
|
Loading…
Reference in New Issue
Block a user