Skip to content

Commit

Permalink
Merge pull request #330 from BigVan/ua
Browse files Browse the repository at this point in the history
Customized HTTP useragent support:
  • Loading branch information
liulanzheng authored Jun 12, 2024
2 parents 73f9008 + a19cbcf commit 0edcc6b
Show file tree
Hide file tree
Showing 11 changed files with 86 additions and 14 deletions.
2 changes: 1 addition & 1 deletion CMake/Findphoton.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ set(PHOTON_ENABLE_EXTFS ON)
FetchContent_Declare(
photon
GIT_REPOSITORY https://github.com/alibaba/PhotonLibOS.git
GIT_TAG v0.6.16
GIT_TAG v0.6.17
)

if(BUILD_TESTING)
Expand Down
2 changes: 2 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -209,6 +209,8 @@ Default configure file `overlaybd.json` is installed to `/etc/overlaybd/`.
| prefetchConfig.concurrency | Prefetch concurrency for reloading trace, `16` is default |
| certConfig.certFile | The path for SSL/TLS client certificate file |
| certConfig.keyFile | The path for SSL/TLS client key file |
| userAgent | customized userAgent to identify HTTP request. default value is package version like 'overlaybd/1.1.14-6c449832' |


> NOTE: `download` is the config for background downloading. After an overlaybd device is lauched, a background task will be running to fetch the whole blobs into local directories. After downloading, I/O requests are directed to local files. Unlike other options, download config is reloaded when a device launching.
Expand Down
6 changes: 2 additions & 4 deletions src/config.h
Original file line number Diff line number Diff line change
Expand Up @@ -17,12 +17,9 @@

#include <string>
#include <vector>
#include "version.h"
#include "overlaybd/config_util.h"

#define MACROTOSTR(x) #x
#define PRINTMACRO(x) MACROTOSTR(x)
static const char OVERLAYBD_VERSION[] = PRINTMACRO(OVERLAYBD_VER);

namespace ImageConfigNS {
const int MAX_LAYER_CNT = 256;

Expand Down Expand Up @@ -157,6 +154,7 @@ struct GlobalConfig : public ConfigUtils::Config {
APPCFG_PARA(logConfig, LogConfig);
APPCFG_PARA(prefetchConfig, PrefetchConfig);
APPCFG_PARA(certConfig, CertConfig);
APPCFG_PARA(userAgent, std::string, OVERLAYBD_VERSION);
};

struct AuthConfig : public ConfigUtils::Config {
Expand Down
3 changes: 2 additions & 1 deletion src/example_config/overlaybd.json
Original file line number Diff line number Diff line change
Expand Up @@ -35,5 +35,6 @@
"updateInterval": 60000000
},
"enableAudit": true,
"auditPath": "/var/log/overlaybd-audit.log"
"auditPath": "/var/log/overlaybd-audit.log",
"registryFsVersion": "v2"
}
2 changes: 1 addition & 1 deletion src/image_service.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -349,7 +349,7 @@ int ImageService::init() {

global_fs.underlay_registryfs = registryfs_creator(
{this, &ImageService::reload_auth}, cafile, 30UL * 1000000,
global_conf.certConfig().certFile().c_str(), global_conf.certConfig().keyFile().c_str());
global_conf.certConfig().certFile().c_str(), global_conf.certConfig().keyFile().c_str(), global_conf.userAgent().c_str());
if (global_fs.underlay_registryfs == nullptr) {
LOG_ERROR_RETURN(0, -1, "create registryfs failed.");
}
Expand Down
1 change: 1 addition & 0 deletions src/main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
See the License for the specific language governing permissions and
limitations under the License.
*/
#include "version.h"
#include "image_file.h"
#include "image_service.h"
#include <photon/common/alog.h>
Expand Down
5 changes: 4 additions & 1 deletion src/overlaybd/registryfs/registryfs.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -528,9 +528,12 @@ inline IFile *RegistryFSImpl::open(const char *pathname, int) {
}

IFileSystem *new_registryfs_v1(PasswordCB callback, const char *caFile, uint64_t timeout,
const char *cert_file, const char *key_file) {
const char *cert_file, const char *key_file, const char *__) {
if (!callback)
LOG_ERROR_RETURN(EINVAL, nullptr, "password callback not set");
if (__ != nullptr) {
LOG_WARN("customized UA is unsupported");
}
return new RegistryFSImpl(callback, caFile ? caFile : "", timeout,
cert_file ? cert_file : "", key_file ? key_file : "");
}
6 changes: 4 additions & 2 deletions src/overlaybd/registryfs/registryfs.h
Original file line number Diff line number Diff line change
Expand Up @@ -32,13 +32,15 @@ photon::fs::IFileSystem *new_registryfs_v1(PasswordCB callback,
const char *caFile = nullptr,
uint64_t timeout = -1,
const char *cert_file = nullptr,
const char *key_file = nullptr);
const char *key_file = nullptr,
const char *__ = nullptr);

photon::fs::IFileSystem *new_registryfs_v2(PasswordCB callback,
const char *caFile = nullptr,
uint64_t timeout = -1,
const char *cert_file = nullptr,
const char *key_file = nullptr);
const char *key_file = nullptr,
const char *customized_ua = nullptr);

photon::fs::IFile* new_registry_uploader(photon::fs::IFile *lfile,
std::string &upload_url,
Expand Down
18 changes: 14 additions & 4 deletions src/overlaybd/registryfs/registryfs_v2.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,10 @@
See the License for the specific language governing permissions and
limitations under the License.
*/
#include "../../version.h"
#include "registryfs.h"


#include <sys/stat.h>
#include <sys/types.h>
#include <unistd.h>
Expand Down Expand Up @@ -124,12 +126,17 @@ class RegistryFSImpl_v2 : public RegistryFS {
}

RegistryFSImpl_v2(PasswordCB callback, const char *caFile, uint64_t timeout,
photon::net::TLSContext *ctx)
photon::net::TLSContext *ctx, const char *ua)
: m_callback(callback), m_caFile(caFile), m_timeout(timeout), m_tls_ctx(ctx),
m_meta_size(kMinimalMetaLife), m_scope_token(kMinimalTokenLife),
m_url_info(kMinimalAUrlLife) {

m_client = nullptr;
if (ua == nullptr) {
m_useragent = OVERLAYBD_VERSION;
} else {
m_useragent = ua;
}
this->refresh_client();
}

Expand Down Expand Up @@ -286,6 +293,8 @@ class RegistryFSImpl_v2 : public RegistryFS {
delete m_client;
}
m_client = new_http_client(nullptr, m_tls_ctx);
LOG_INFO("set user agent: `", m_useragent);
m_client->set_user_agent(m_useragent);
}

int refresh_token(const estring &url, estring &token) {
Expand All @@ -309,6 +318,7 @@ class RegistryFSImpl_v2 : public RegistryFS {
PasswordCB m_callback;
estring m_accelerate;
estring m_caFile;
estring m_useragent;
uint64_t m_timeout;
photon::net::TLSContext *m_tls_ctx;
photon::net::http::Client *m_client;
Expand Down Expand Up @@ -523,14 +533,14 @@ inline IFile *RegistryFSImpl_v2::open(const char *pathname, int) {
}

IFileSystem *new_registryfs_v2(PasswordCB callback, const char *caFile, uint64_t timeout,
const char *cert_file, const char *key_file) {
const char *cert_file, const char *key_file, const char *customized_ua) {
if (!callback)
LOG_ERROR_RETURN(EINVAL, nullptr, "password callback not set");
auto ctx = new_tls_context_from_file(cert_file, key_file);
if (!ctx) {
LOG_ERRNO_RETURN(0, nullptr, "failed to new tls context");
}
return new RegistryFSImpl_v2(callback, caFile ? caFile : "", timeout, ctx);
return new RegistryFSImpl_v2(callback, caFile ? caFile : "", timeout, ctx, customized_ua);
}

class RegistryUploader : public VirtualFile {
Expand Down Expand Up @@ -727,7 +737,7 @@ class RegistryUploader : public VirtualFile {
photon::init(photon::INIT_EVENT_DEFAULT, photon::INIT_IO_NONE);
DEFER(photon::fini());
m_upload_fs = new RegistryFSImpl_v2({this, &RegistryUploader::load_auth},
"", m_timeout, m_tls_ctx);
"", m_timeout, m_tls_ctx, nullptr);
DEFER({ delete m_upload_fs; });
m_http_client_ts = photon::now;
::posix_memalign(&m_upload_buf, 4096, 1024 * 1024);
Expand Down
50 changes: 50 additions & 0 deletions src/test/image_service_test.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -24,11 +24,16 @@
#include "photon/net/socket.h"
#include "photon/io/fd-events.h"
#include "photon/net/curl.h"
#include "../version.h"
#include <photon/net/http/client.h>


#include <fcntl.h>

#include "../image_service.cpp"

char *test_ua = nullptr;

photon::net::ISocketServer *new_server(std::string ip, uint16_t port) {
auto server = photon::net::new_tcp_socket_server();
server->timeout(1000UL*1000);
Expand Down Expand Up @@ -112,6 +117,51 @@ TEST(ImageTest, enableMetrics) {
delete is;
}


int ua_check_handler(void*, photon::net::http::Request &req, photon::net::http::Response &resp, std::string_view) {
auto ua = req.headers["User-Agent"];
LOG_DEBUG(VALUE(ua));
EXPECT_EQ(ua, test_ua);
resp.set_result(200);
LOG_INFO("expected UA: `", test_ua);
std::string str = "success";
resp.headers.content_length(7);
resp.write((void*)str.data(), str.size());
return 0;
}


TEST(http_client, user_agent) {
auto tcpserver = photon::net::new_tcp_socket_server();
DEFER(delete tcpserver);
tcpserver->bind(18731);
tcpserver->listen();
auto server = photon::net::http::new_http_server();
DEFER(delete server);
server->add_handler({nullptr, &ua_check_handler});
tcpserver->set_handler(server->get_connection_handler());
tcpserver->start_loop();

test_ua = "mytestUA";

std::string target_get = "http://localhost:18731/file";
auto client = photon::net::http::new_http_client();
client->set_user_agent(test_ua);
DEFER(delete client);
auto op = client->new_operation(photon::net::http::Verb::GET, target_get);
DEFER(delete op);
op->req.headers.content_length(0);
client->call(op);
EXPECT_EQ(op->status_code, 200);
std::string buf;
buf.resize(op->resp.headers.content_length());
op->resp.read((void*)buf.data(), op->resp.headers.content_length());
LOG_DEBUG(VALUE(buf));
EXPECT_EQ(true, buf == "success");
}



int main(int argc, char** argv) {
photon::init(photon::INIT_EVENT_DEFAULT, photon::INIT_IO_DEFAULT);
DEFER(photon::fini(););
Expand Down
5 changes: 5 additions & 0 deletions src/version.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
#pragma once

#define MACROTOSTR(x) #x
#define PRINTMACRO(x) MACROTOSTR(x)
static const char OVERLAYBD_VERSION[] = PRINTMACRO(OVERLAYBD_VER);

0 comments on commit 0edcc6b

Please sign in to comment.