Skip to content
Merged
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
37 changes: 31 additions & 6 deletions src/majordomo/include/majordomo/RestServer.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -252,6 +252,7 @@ inline std::expected<SSL_CTX_Ptr, std::string> create_ssl_ctx(EVP_PKEY *key, X50
using Message = mdp::BasicMessage<mdp::MessageFormat::WithSourceId>;

enum class RestMethod {
Options,
Get,
LongPoll,
Post,
Expand All @@ -260,7 +261,8 @@ enum class RestMethod {

inline RestMethod parseMethod(std::string_view methodString) {
using enum RestMethod;
return methodString == "PUT" ? Post
return methodString == "OPTIONS" ? Options
: methodString == "PUT" ? Post
: methodString == "POST" ? Post
: methodString == "GET" ? Get
: Invalid;
Expand Down Expand Up @@ -508,6 +510,17 @@ struct SessionBase {
#endif
}

void respondToCorsPreflight(TStreamId streamId) {
majordomo::rest::Response r;
r.code = 204;
r.headers.emplace_back("access-control-allow-methods", "GET, POST, OPTIONS");
r.headers.emplace_back("access-control-allow-headers", "content-type, accept");
r.headers.emplace_back("access-control-max-age", "86400");
r.headers.emplace_back("content-length", "0");

self().sendResponse(streamId, std::move(r));
}

void respondToLongPoll(TStreamId streamId, std::uint64_t index, Message &&msg) {
auto timestamp = std::to_string(opencmw::load_test::timestamp().count());
self().sendResponse(streamId, kHttpOk, std::move(msg), { nv(u8span("x-opencmw-long-polling-idx"), u8span(std::to_string(index))), nv(u8span("x-timestamp"), u8span(timestamp)) });
Expand Down Expand Up @@ -621,7 +634,6 @@ struct SessionBase {
bool haveSubscriptionContext = false;
for (const auto &[qkey, qvalue] : pathUri.queryParamMap()) {
if (qkey == "LongPollingIdx") {
request.method = RestMethod::LongPoll;
request.longPollIndex = qvalue.value_or("");
} else if (qkey == "SubscriptionContext") {
request.topic = mdp::Topic::fromMdpTopic(URI<>(qvalue.value_or("")));
Expand All @@ -646,8 +658,10 @@ struct SessionBase {
return;
}

if (request.method == RestMethod::Invalid) {
request.method = parseMethod(method);
request.method = parseMethod(method);
// Only GET + longPollIndex => LongPoll
if (request.method == RestMethod::Get && !request.longPollIndex.empty()) {
request.method = RestMethod::LongPoll;
}

// Set completed for getMessages() to collect
Expand All @@ -664,6 +678,9 @@ struct SessionBase {
auto &[streamId, request] = *it;

switch (request.method) {
case RestMethod::Options:
respondToCorsPreflight(streamId);
break;
case RestMethod::Get:
case RestMethod::Post:
if (auto m = processGetSetRequest(streamId, request, idGenerator); m.has_value()) {
Expand Down Expand Up @@ -885,7 +902,11 @@ struct Http2Session : public SessionBase<Http2Session, std::int32_t> {
HTTP_DBG("Server::respondWithRedirect: streamId={} location={}", streamId, location);
// :status must go first
constexpr auto noCopy = NGHTTP2_NV_FLAG_NO_COPY_NAME | NGHTTP2_NV_FLAG_NO_COPY_VALUE;
auto headers = std::vector{ nv(u8span(":status"), u8span("302"), noCopy), nv(u8span("location"), u8span(location)) };
auto headers = std::vector{
nv(u8span(":status"), u8span("302"), noCopy),
nv(u8span("location"), u8span(location)),
nv(u8span("access-control-allow-origin"), u8span("*"), noCopy)};

if (!_sharedData->_altSvcHeaderValue.empty()) {
headers.push_back(_sharedData->_altSvcHeader);
}
Expand Down Expand Up @@ -1172,7 +1193,11 @@ struct Http3Session : public SessionBase<Http3Session<TServer>, std::int64_t>, p
HTTP_DBG("Server::H3::respondWithRedirect: streamId={} location={}", streamId, location);
// :status must go first
constexpr auto noCopy = NGHTTP3_NV_FLAG_NO_COPY_NAME | NGHTTP3_NV_FLAG_NO_COPY_VALUE;
const auto headers = std::array{ nv3(u8span(":status"), u8span("302"), noCopy), nv3(u8span("location"), u8span(location)) };
const auto headers = std::array{
nv3(u8span(":status"), u8span("302"), noCopy),
nv3(u8span("location"), u8span(location)),
nv3(u8span("access-control-allow-origin"), u8span("*"), noCopy) };

nghttp3_conn_submit_response(_httpconn, streamId, headers.data(), headers.size(), nullptr);
}

Expand Down