mirror of
https://github.com/Relintai/pandemonium_engine.git
synced 2025-01-11 05:19:50 +01: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;
|
||||
}
|
||||
|
||||
//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";
|
||||
|
||||
if (!result_content_range_header.empty()) {
|
||||
s += result_content_range_header;
|
||||
}
|
||||
|
||||
if (!custom_headers.has("Connection")) {
|
||||
if (has_more_messages()) {
|
||||
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";
|
||||
}
|
||||
|
||||
uint64_t file_length = r->_sending_file_fa->get_len();
|
||||
|
||||
s += "Content-Length: " + itos(file_length) + "\r\n";
|
||||
s += "Content-Length: " + itos(content_length) + "\r\n";
|
||||
|
||||
for (int i = 0; i < request->response_get_cookie_count(); ++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) {
|
||||
_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) {
|
||||
//finished
|
||||
@ -378,9 +492,8 @@ void HTTPServerConnection::update_send_file(Ref<SimpleWebServerRequest> request)
|
||||
}
|
||||
|
||||
if (err != OK) {
|
||||
close_file(request);
|
||||
close();
|
||||
memdelete(request->_sending_file_fa);
|
||||
request->_sending_file_fa = NULL;
|
||||
_file_buffer_start = 0;
|
||||
_file_buffer_end = 0;
|
||||
return;
|
||||
@ -394,8 +507,7 @@ void HTTPServerConnection::update_send_file(Ref<SimpleWebServerRequest> request)
|
||||
}
|
||||
}
|
||||
|
||||
memdelete(request->_sending_file_fa);
|
||||
request->_sending_file_fa = NULL;
|
||||
close_file(request);
|
||||
|
||||
_file_buffer_start = 0;
|
||||
_file_buffer_end = 0;
|
||||
@ -432,6 +544,13 @@ bool HTTPServerConnection::has_more_messages() {
|
||||
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() {
|
||||
_web_server = nullptr;
|
||||
_http_server = nullptr;
|
||||
@ -452,6 +571,9 @@ HTTPServerConnection::HTTPServerConnection() {
|
||||
|
||||
_file_buffer_start = 0;
|
||||
_file_buffer_end = 0;
|
||||
_file_start = 0;
|
||||
_file_end = 0;
|
||||
_file_length = 0;
|
||||
}
|
||||
HTTPServerConnection::~HTTPServerConnection() {
|
||||
}
|
||||
|
@ -69,6 +69,8 @@ public:
|
||||
|
||||
bool has_more_messages();
|
||||
|
||||
void close_file(Ref<SimpleWebServerRequest> request);
|
||||
|
||||
HTTPServerConnection();
|
||||
~HTTPServerConnection();
|
||||
|
||||
@ -92,6 +94,11 @@ public:
|
||||
uint8_t _file_send_buffer[4096];
|
||||
uint64_t _file_buffer_start;
|
||||
uint64_t _file_buffer_end;
|
||||
|
||||
uint64_t _file_start;
|
||||
uint64_t _file_end;
|
||||
uint64_t _file_length;
|
||||
|
||||
int _file_buffer_send_max_consecutive_loops;
|
||||
|
||||
uint64_t _timeout_usec;
|
||||
|
Loading…
Reference in New Issue
Block a user