Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(http): Add DELETE method support #1442

Merged
merged 2 commits into from
Oct 25, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 0 additions & 8 deletions docs/source/tutorials/http_upload.rst
Original file line number Diff line number Diff line change
Expand Up @@ -101,14 +101,6 @@ Backlog
Please note the HTTP upload feature still lacks some features
probably important for production. Contributions are welcome!

HTTP DELETE
===========
Nothing has be done to support this yet:

Packager supports removing old segments automatically.
See ``preserved_segments_outside_live_window`` option in
DASH_ options or HLS_ options for details.

Software tests
==============
We should do some minimal QA, check whether the test
Expand Down
12 changes: 10 additions & 2 deletions packager/file/file.cc
Original file line number Diff line number Diff line change
Expand Up @@ -111,6 +111,10 @@ File* CreateHttpsFile(const char* file_name, const char* mode) {
return new HttpFile(method, std::string("https://") + file_name);
}

bool DeleteHttpsFile(const char* file_name) {
return HttpFile::Delete(std::string("https://") + file_name);
}

File* CreateHttpFile(const char* file_name, const char* mode) {
HttpMethod method = HttpMethod::kGet;
if (strcmp(mode, "r") != 0) {
Expand All @@ -119,6 +123,10 @@ File* CreateHttpFile(const char* file_name, const char* mode) {
return new HttpFile(method, std::string("http://") + file_name);
}

bool DeleteHttpFile(const char* file_name) {
return HttpFile::Delete(std::string("http://") + file_name);
}

File* CreateMemoryFile(const char* file_name, const char* mode) {
return new MemoryFile(file_name, mode);
}
Expand All @@ -138,8 +146,8 @@ static const FileTypeInfo kFileTypeInfo[] = {
{kUdpFilePrefix, &CreateUdpFile, nullptr, nullptr},
{kMemoryFilePrefix, &CreateMemoryFile, &DeleteMemoryFile, nullptr},
{kCallbackFilePrefix, &CreateCallbackFile, nullptr, nullptr},
{kHttpFilePrefix, &CreateHttpFile, nullptr, nullptr},
{kHttpsFilePrefix, &CreateHttpsFile, nullptr, nullptr},
{kHttpFilePrefix, &CreateHttpFile, &DeleteHttpFile, nullptr},
{kHttpsFilePrefix, &CreateHttpsFile, &DeleteHttpsFile, nullptr},
};

std::string_view GetFileTypePrefix(std::string_view file_name) {
Expand Down
20 changes: 17 additions & 3 deletions packager/file/http_file.cc
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
#include <absl/strings/str_format.h>
#include <curl/curl.h>

#include <packager/file/file_closer.h>
#include <packager/file/thread_pool.h>
#include <packager/macros/compiler.h>
#include <packager/macros/logging.h>
Expand Down Expand Up @@ -174,6 +175,7 @@ HttpFile::HttpFile(HttpMethod method,
upload_content_type_(upload_content_type),
timeout_in_seconds_(timeout_in_seconds),
method_(method),
isUpload_(method == HttpMethod::kPut || method == HttpMethod::kPost),
download_cache_(absl::GetFlag(FLAGS_io_cache_size)),
upload_cache_(absl::GetFlag(FLAGS_io_cache_size)),
curl_(curl_easy_init()),
Expand Down Expand Up @@ -201,8 +203,7 @@ HttpFile::HttpFile(HttpMethod method,
!AppendHeader("Content-Type: " + upload_content_type_, &temp_headers)) {
return;
}
if (method != HttpMethod::kGet &&
!AppendHeader("Transfer-Encoding: chunked", &temp_headers)) {
if (isUpload_ && !AppendHeader("Transfer-Encoding: chunked", &temp_headers)) {
return;
}
for (const auto& item : headers) {
Expand All @@ -215,6 +216,16 @@ HttpFile::HttpFile(HttpMethod method,

HttpFile::~HttpFile() {}

// static
bool HttpFile::Delete(const std::string& url) {
std::unique_ptr<HttpFile, FileCloser> file(
new HttpFile(HttpMethod::kDelete, url));
if (!file->Open()) {
return false;
}
return file.release()->Close();
}

bool HttpFile::Open() {
VLOG(2) << "Opening " << url_;

Expand Down Expand Up @@ -313,6 +324,9 @@ void HttpFile::SetupRequest() {
case HttpMethod::kPut:
curl_easy_setopt(curl, CURLOPT_PUT, 1L);
break;
case HttpMethod::kDelete:
curl_easy_setopt(curl, CURLOPT_CUSTOMREQUEST, "DELETE");
break;
}

curl_easy_setopt(curl, CURLOPT_URL, url_.c_str());
Expand All @@ -322,7 +336,7 @@ void HttpFile::SetupRequest() {
curl_easy_setopt(curl, CURLOPT_FOLLOWLOCATION, 1L);
curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, &CurlWriteCallback);
curl_easy_setopt(curl, CURLOPT_WRITEDATA, &download_cache_);
if (method_ != HttpMethod::kGet) {
if (isUpload_) {
curl_easy_setopt(curl, CURLOPT_READFUNCTION, &CurlReadCallback);
curl_easy_setopt(curl, CURLOPT_READDATA, &upload_cache_);
}
Expand Down
4 changes: 4 additions & 0 deletions packager/file/http_file.h
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ enum class HttpMethod {
kGet,
kPost,
kPut,
kDelete,
};

/// HttpFile reads or writes network requests.
Expand All @@ -47,6 +48,8 @@ class HttpFile : public File {
HttpFile(const HttpFile&) = delete;
HttpFile& operator=(const HttpFile&) = delete;

static bool Delete(const std::string& url);

Status CloseWithStatus();

/// @name File implementation overrides.
Expand Down Expand Up @@ -78,6 +81,7 @@ class HttpFile : public File {
const std::string upload_content_type_;
const int32_t timeout_in_seconds_;
const HttpMethod method_;
const bool isUpload_;
IoCache download_cache_;
IoCache upload_cache_;
std::unique_ptr<CURL, CurlDelete> curl_;
Expand Down
12 changes: 12 additions & 0 deletions packager/file/http_file_unittest.cc
Original file line number Diff line number Diff line change
Expand Up @@ -273,6 +273,18 @@ TEST_F(HttpFileTest, MultipleChunks) {
ASSERT_JSON_STRING(json, "headers.Transfer-Encoding", "chunked");
}

TEST_F(HttpFileTest, BasicDelete) {
FilePtr file(new HttpFile(HttpMethod::kDelete, server_.ReflectUrl(),
kNoContentType, kNoHeaders, kDefaultTestTimeout));
ASSERT_TRUE(file);
ASSERT_TRUE(file->Open());

auto json = HandleResponse(file);
ASSERT_TRUE(json.is_object());
ASSERT_TRUE(file.release()->Close());
ASSERT_JSON_STRING(json, "method", "DELETE");
}

TEST_F(HttpFileTest, Error404) {
FilePtr file(new HttpFile(HttpMethod::kGet, server_.StatusCodeUrl(404),
kNoContentType, kNoHeaders, kDefaultTestTimeout));
Expand Down
Loading