* Copyright (c) Huawei Technologies Co., Ltd. 2025. All rights reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include "actor/actor.hpp"
#include "actor/buslog.hpp"
#include "async/future.hpp"
#include "httpd/http.hpp"
#include "utils/string_utils.hpp"
#include "httpd/http_actor.hpp"
using namespace std;
namespace litebus {
namespace http {
void HttpActor::Done(const std::string &name, const Request &request, HttpMessage *httpMessage)
{
auto iter = httphandles.find("/");
if (iter != httphandles.end()) {
Future<Response> response = httphandles[iter->first](request);
httpMessage->GetResponsePromise()->Associate(response);
return;
} else {
BUSLOG_WARN("Can not find this handle, name: {}", name);
httpMessage->GetResponsePromise()->Associate(NotFound());
}
return;
}
void HttpActor::AddRoute(const std::string &name, HttpActor::HttpRequestHandler &&handler)
{
BUSLOG_INFO("Add endpoint, name:{}", name);
httphandles[name] = handler;
}
string HttpActor::GetHttpFunctionName(const string &path) const
{
string name = path;
name = "/" + litebus::strings::Trim(name, litebus::strings::PREFIX, "/");
vector<string> tokens = litebus::strings::Tokenize(name, "/");
if (!tokens.empty()) {
name = litebus::strings::Remove(name, "/" + tokens[0], litebus::strings::PREFIX);
}
if (name.empty()) {
BUSLOG_INFO("Set default handle name as '/'.");
name = "/";
}
return name;
}
void HttpActor::HandleHttp(std::unique_ptr<MessageBase> message)
{
HttpMessage *httpMessage = nullptr;
httpMessage = dynamic_cast<HttpMessage *>(message.get());
if (httpMessage == nullptr) {
BUSLOG_WARN("Can't transform to HttpMessage.");
return;
}
const Request &request = httpMessage->GetRequest();
string name = GetHttpFunctionName(request.url.path);
BUSLOG_DEBUG("handle name, size={},name={},urlfrom={}", name.size(), name, request.url.path);
name = "/" + litebus::strings::Trim(name, litebus::strings::PREFIX, "/");
if (name.back() == '/') {
name = litebus::strings::Trim(name, litebus::strings::SUFFIX, "/");
auto iter = httphandles.find(name);
if (iter != httphandles.end()) {
Done(name, request, httpMessage);
return;
}
}
while (name != "/" && !name.empty()) {
if (name.back() == '/') {
name = litebus::strings::Trim(name, litebus::strings::SUFFIX, "/");
}
auto iter = httphandles.find(name);
if (iter != httphandles.end()) {
Future<Response> response = httphandles[iter->first](request);
httpMessage->GetResponsePromise()->Associate(response);
return;
}
vector<string> tokens = litebus::strings::Tokenize(name, "/");
if (tokens.empty()) {
break;
} else {
name = litebus::strings::Remove(name, "/" + tokens[tokens.size() - 1], litebus::strings::SUFFIX);
}
}
Done(name, request, httpMessage);
return;
}
}
}