mirror of
https://github.com/oatpp/oatpp.git
synced 2025-03-13 18:06:47 +08:00
Better client error handling, better url mapping
This commit is contained in:
parent
204e8cce2a
commit
248452893a
@ -57,11 +57,11 @@ public:
|
||||
: oatpp::data::mapping::type::ObjectWrapper<oatpp::base::StrBuffer, __class::String>(oatpp::base::StrBuffer::createShared(size))
|
||||
{}
|
||||
|
||||
String(const void* data, v_int32 size, bool copyAsOwnData = true)
|
||||
String(const char* data, v_int32 size, bool copyAsOwnData = true)
|
||||
: oatpp::data::mapping::type::ObjectWrapper<oatpp::base::StrBuffer, __class::String>(oatpp::base::StrBuffer::createShared(data, size, copyAsOwnData))
|
||||
{}
|
||||
|
||||
String(const void* data1, v_int32 size1, const void* data2, v_int32 size2)
|
||||
String(const char* data1, v_int32 size1, const char* data2, v_int32 size2)
|
||||
: oatpp::data::mapping::type::ObjectWrapper<oatpp::base::StrBuffer, __class::String>(oatpp::base::StrBuffer::createSharedConcatenated(data1, size1, data2, size2))
|
||||
{}
|
||||
|
||||
|
@ -277,7 +277,7 @@ namespace oatpp { namespace parser {
|
||||
|
||||
if(len > 0){
|
||||
|
||||
auto str = oatpp::String(&m_data[ipos], len, true);
|
||||
auto str = oatpp::String((const char*)&m_data[ipos], len, true);
|
||||
v_int32 result = atoi((const char*)str->getData());
|
||||
|
||||
if(negative){
|
||||
@ -455,7 +455,7 @@ namespace oatpp { namespace parser {
|
||||
if(m_data[m_pos] == escapeChar){
|
||||
m_pos++;
|
||||
}else if(m_data[m_pos] == closeChar){
|
||||
oatpp::String result = oatpp::String(&m_data[ipos], m_pos - ipos, saveAsOwnData);
|
||||
oatpp::String result = oatpp::String((const char*)&m_data[ipos], m_pos - ipos, saveAsOwnData);
|
||||
m_pos++;
|
||||
return result;
|
||||
}
|
||||
@ -488,7 +488,7 @@ namespace oatpp { namespace parser {
|
||||
}else{
|
||||
|
||||
if(ipos < m_pos){
|
||||
return oatpp::String(&m_data[ipos], m_pos - ipos, saveAsOwnData);
|
||||
return oatpp::String((const char*)&m_data[ipos], m_pos - ipos, saveAsOwnData);
|
||||
}else{
|
||||
m_error = ERROR_NAME_EXPECTED;
|
||||
return nullptr;
|
||||
@ -499,7 +499,7 @@ namespace oatpp { namespace parser {
|
||||
}
|
||||
|
||||
if(ipos < m_pos){
|
||||
return oatpp::String(&m_data[ipos], m_pos - ipos, saveAsOwnData);
|
||||
return oatpp::String((const char*)&m_data[ipos], m_pos - ipos, saveAsOwnData);
|
||||
}else{
|
||||
m_error = ERROR_NAME_EXPECTED;
|
||||
return nullptr;
|
||||
|
@ -69,7 +69,7 @@ public:
|
||||
if(end == -1){
|
||||
end = m_caret.m_pos;
|
||||
}
|
||||
return oatpp::String(&m_caret.m_data[m_start], end - m_start, saveAsOwnData);
|
||||
return oatpp::String((const char*)&m_caret.m_data[m_start], end - m_start, saveAsOwnData);
|
||||
}
|
||||
|
||||
oatpp::String toString(){
|
||||
|
@ -64,7 +64,7 @@ namespace oatpp { namespace utils { namespace conversion {
|
||||
v_char8 buff [100];
|
||||
v_int32 size = int32ToCharSequence(value, &buff[0]);
|
||||
if(size > 0){
|
||||
return oatpp::String(&buff[0], size, true);
|
||||
return oatpp::String((const char*)&buff[0], size, true);
|
||||
}
|
||||
return oatpp::String::empty();
|
||||
}
|
||||
@ -73,7 +73,7 @@ namespace oatpp { namespace utils { namespace conversion {
|
||||
v_char8 buff [100];
|
||||
v_int32 size = int64ToCharSequence(value, &buff[0]);
|
||||
if(size > 0){
|
||||
return oatpp::String(&buff[0], size, true);
|
||||
return oatpp::String((const char*)&buff[0], size, true);
|
||||
}
|
||||
return oatpp::String::empty();
|
||||
}
|
||||
@ -132,7 +132,7 @@ namespace oatpp { namespace utils { namespace conversion {
|
||||
v_char8 buff [100];
|
||||
v_int32 size = float32ToCharSequence(value, &buff[0]);
|
||||
if(size > 0){
|
||||
return oatpp::String(&buff[0], size, true);
|
||||
return oatpp::String((const char*)&buff[0], size, true);
|
||||
}
|
||||
return oatpp::String::empty();
|
||||
}
|
||||
@ -141,16 +141,16 @@ namespace oatpp { namespace utils { namespace conversion {
|
||||
v_char8 buff [100];
|
||||
v_int32 size = float32ToCharSequence(value, &buff[0]);
|
||||
if(size > 0){
|
||||
return oatpp::String(&buff[0], size, true);
|
||||
return oatpp::String((const char*)&buff[0], size, true);
|
||||
}
|
||||
return oatpp::String::empty();
|
||||
}
|
||||
|
||||
oatpp::String boolToStr(bool value) {
|
||||
if(value){
|
||||
return oatpp::String((p_char8)"true", 4, false);
|
||||
return oatpp::String("true", 4, false);
|
||||
} else {
|
||||
return oatpp::String((p_char8)"false", 5, false);
|
||||
return oatpp::String("false", 5, false);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -60,7 +60,7 @@ namespace oatpp { namespace utils { namespace conversion {
|
||||
v_char8 buff [100];
|
||||
v_int32 size = primitiveToCharSequence(value, &buff[0], pattern);
|
||||
if(size > 0){
|
||||
return oatpp::String(&buff[0], size, true);
|
||||
return oatpp::String((const char*)&buff[0], size, true);
|
||||
}
|
||||
return oatpp::String::empty();
|
||||
}
|
||||
|
@ -66,7 +66,7 @@ Connection::Library::v_size Connection::read(void *buff, Library::v_size count){
|
||||
return ERROR_IO_WAIT_RETRY; // For async io. In case socket is non_blocking
|
||||
} else if(e == EINTR) {
|
||||
return ERROR_IO_RETRY;
|
||||
} else if(e == EPIPE) {
|
||||
} else if(e == ECONNRESET) {
|
||||
return ERROR_IO_PIPE;
|
||||
} else {
|
||||
//OATPP_LOGD("Connection", "write errno=%d", e);
|
||||
|
@ -204,7 +204,7 @@ oatpp::String Utils::escapeString(p_char8 data, v_int32 size) {
|
||||
v_int32 safeSize;
|
||||
v_int32 escapedSize = calcEscapedStringSize(data, size, safeSize);
|
||||
if(escapedSize == size) {
|
||||
return String(data, size, true);
|
||||
return String((const char*)data, size, true);
|
||||
}
|
||||
auto result = String(escapedSize);
|
||||
v_int32 i = 0;
|
||||
|
@ -78,10 +78,10 @@ void ApiClient::formatPath(oatpp::data::stream::OutputStream* stream,
|
||||
if(seg.type == PathSegment::SEG_PATH) {
|
||||
stream->write(seg.text.data(), seg.text.size());
|
||||
} else {
|
||||
auto key = oatpp::String((p_char8) seg.text.data(), (v_int32) seg.text.length(), false);
|
||||
auto key = oatpp::String(seg.text.data(), (v_int32) seg.text.length(), false);
|
||||
auto& param = params->get(key, oatpp::data::mapping::type::AbstractObjectWrapper::empty());
|
||||
if(!param){
|
||||
OATPP_LOGD(TAG, "Path parameter '%s' not provided in the api call", (const char*) seg.text.c_str());
|
||||
OATPP_LOGD(TAG, "Path parameter '%s' not provided in the api call", seg.text.c_str());
|
||||
throw std::runtime_error("[oatpp::web::client::ApiClient]: Path parameter missing");
|
||||
}
|
||||
auto value = oatpp::utils::conversion::primitiveToStr(param);
|
||||
|
@ -46,14 +46,11 @@ HttpRequestExecutor::execute(const String& method,
|
||||
const std::shared_ptr<Headers>& headers,
|
||||
const std::shared_ptr<Body>& body) {
|
||||
|
||||
//auto stream = oatpp::data::stream::ChunkedBuffer::createShared();
|
||||
//stream << "/" << path;
|
||||
//ENV::log("HTTP_EXECUTOR", "Execute: '%s'", (const char*) stream->toStringAsString()->getData());
|
||||
|
||||
auto connection = m_connectionProvider->getConnection();
|
||||
|
||||
if(!connection){
|
||||
return nullptr; // TODO ERROR HERE
|
||||
throw RequestExecutionError(RequestExecutionError::ERROR_CODE_CANT_CONNECT,
|
||||
"[oatpp::web::client::HttpRequestExecutor::execute()]: ConnectionProvider failed to provide Connection");
|
||||
}
|
||||
|
||||
auto request = oatpp::web::protocol::http::outgoing::Request::createShared(method, path, headers, body);
|
||||
@ -65,41 +62,37 @@ HttpRequestExecutor::execute(const String& method,
|
||||
request->send(upStream);
|
||||
upStream->flush();
|
||||
|
||||
//auto upStream = oatpp::data::stream::ChunkedBuffer::createShared();
|
||||
//request->send(upStream);
|
||||
//ENV::log("request", "request:'%s'\n", (const char*) upStream->toStringAsString()->getData());
|
||||
//upStream->flushToStream(connection);
|
||||
|
||||
auto readCount = connection->read(ioBuffer->getData(), ioBuffer->getSize());
|
||||
|
||||
//((p_char8) ioBuffer->getData())[readCount] = 0;
|
||||
//ENV::log("asd", "response='%s'", (const char*) ioBuffer->getData());
|
||||
|
||||
if(readCount > 0) {
|
||||
|
||||
oatpp::parser::ParsingCaret caret((p_char8) ioBuffer->getData(), ioBuffer->getSize());
|
||||
auto line = protocol::http::Protocol::parseResponseStartingLine(caret);
|
||||
if(!line){
|
||||
return nullptr; // TODO ERROR HERE
|
||||
}
|
||||
|
||||
oatpp::web::protocol::http::Status error;
|
||||
auto headers = protocol::http::Protocol::parseHeaders(caret, error);
|
||||
|
||||
if(error.code != 0){
|
||||
return nullptr; // TODO ERROR HERE
|
||||
}
|
||||
|
||||
auto bodyStream = oatpp::data::stream::InputStreamBufferedProxy::createShared(connection,
|
||||
ioBuffer,
|
||||
caret.getPosition(),
|
||||
(v_int32) readCount);
|
||||
|
||||
return Response::createShared(line->statusCode, line->description, headers, bodyStream);
|
||||
if(readCount == 0) {
|
||||
throw RequestExecutionError(RequestExecutionError::ERROR_CODE_NO_RESPONSE,
|
||||
"[oatpp::web::client::HttpRequestExecutor::execute()]: No response from server");
|
||||
} else if(readCount < 0) {
|
||||
throw RequestExecutionError(RequestExecutionError::ERROR_CODE_CANT_READ_RESPONSE,
|
||||
"[oatpp::web::client::HttpRequestExecutor::execute()]: Failed to read response. Check out the RequestExecutionError::getReadErrorCode() for more information", (v_int32) readCount);
|
||||
}
|
||||
|
||||
oatpp::parser::ParsingCaret caret((p_char8) ioBuffer->getData(), ioBuffer->getSize());
|
||||
auto line = protocol::http::Protocol::parseResponseStartingLine(caret);
|
||||
if(!line){
|
||||
throw RequestExecutionError(RequestExecutionError::ERROR_CODE_CANT_PARSE_STARTING_LINE,
|
||||
"[oatpp::web::client::HttpRequestExecutor::execute()]: Failed to parse response. Invalid starting line");
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
oatpp::web::protocol::http::Status error;
|
||||
auto responseHeaders = protocol::http::Protocol::parseHeaders(caret, error);
|
||||
|
||||
if(error.code != 0){
|
||||
throw RequestExecutionError(RequestExecutionError::ERROR_CODE_CANT_PARSE_HEADERS,
|
||||
"[oatpp::web::client::HttpRequestExecutor::execute()]: Failed to parse response. Invalid headers section");
|
||||
}
|
||||
|
||||
auto bodyStream = oatpp::data::stream::InputStreamBufferedProxy::createShared(connection,
|
||||
ioBuffer,
|
||||
caret.getPosition(),
|
||||
(v_int32) readCount);
|
||||
|
||||
return Response::createShared(line->statusCode, line->description, responseHeaders, bodyStream);
|
||||
|
||||
}
|
||||
|
||||
|
@ -44,6 +44,9 @@ public:
|
||||
return std::shared_ptr<HttpRequestExecutor>(new HttpRequestExecutor(connectionProvider));
|
||||
}
|
||||
|
||||
/**
|
||||
* throws RequestExecutionError
|
||||
*/
|
||||
std::shared_ptr<Response> execute(const String& method,
|
||||
const String& path,
|
||||
const std::shared_ptr<Headers>& headers,
|
||||
|
@ -41,6 +41,48 @@ public:
|
||||
typedef oatpp::web::protocol::http::outgoing::Body Body;
|
||||
public:
|
||||
typedef Action (oatpp::async::AbstractCoroutine::*AsyncCallback)(const std::shared_ptr<Response>&);
|
||||
public:
|
||||
|
||||
class RequestExecutionError : public std::runtime_error {
|
||||
public:
|
||||
constexpr static const v_int32 ERROR_CODE_CANT_CONNECT = 1;
|
||||
constexpr static const v_int32 ERROR_CODE_CANT_PARSE_STARTING_LINE = 2;
|
||||
constexpr static const v_int32 ERROR_CODE_CANT_PARSE_HEADERS = 3;
|
||||
constexpr static const v_int32 ERROR_CODE_CANT_READ_RESPONSE = 4;
|
||||
constexpr static const v_int32 ERROR_CODE_NO_RESPONSE = 5;
|
||||
private:
|
||||
v_int32 m_errorCode;
|
||||
v_int32 m_readErrorCode;
|
||||
const char* m_message;
|
||||
public:
|
||||
|
||||
RequestExecutionError(v_int32 errorCode, const char* message, v_int32 readErrorCode = 0)
|
||||
:std::runtime_error(message)
|
||||
, m_errorCode(errorCode)
|
||||
, m_message(message)
|
||||
, m_readErrorCode(readErrorCode)
|
||||
{}
|
||||
|
||||
v_int32 getErrorCode() const {
|
||||
return m_errorCode;
|
||||
}
|
||||
|
||||
const char* getMessage() const {
|
||||
return m_message;
|
||||
}
|
||||
|
||||
/**
|
||||
* This value is valid if errorCode == ERROR_CODE_CANT_READ_RESPONSE
|
||||
* For more information about the read error you get check out:
|
||||
* - oatpp::data::stream::IOStream for possible error codes
|
||||
* - implementation of Connection provided by your ConnectionProvider for implementation-specific behaviour
|
||||
*/
|
||||
v_int32 getReadErrorCode() const {
|
||||
return m_readErrorCode;
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
public:
|
||||
|
||||
virtual std::shared_ptr<Response> execute(const String& method,
|
||||
|
@ -77,7 +77,7 @@ HttpProcessor::processRequest(HttpRouter* router,
|
||||
|
||||
auto route = router->getRoute(line->method, line->path);
|
||||
|
||||
if(!route.isNull()) {
|
||||
if(route) {
|
||||
|
||||
oatpp::web::protocol::http::Status error;
|
||||
auto headers = protocol::http::Protocol::parseHeaders(caret, error);
|
||||
@ -143,7 +143,7 @@ HttpProcessor::Coroutine::Action HttpProcessor::Coroutine::parseRequest(v_int32
|
||||
|
||||
m_currentRoute = m_router->getRoute(line->method, line->path);
|
||||
|
||||
if(m_currentRoute.isNull()) {
|
||||
if(!m_currentRoute) {
|
||||
m_currentResponse = m_errorHandler->handleError(protocol::http::Status::CODE_404, "Current url has no mapping");
|
||||
return yieldTo(&HttpProcessor::Coroutine::onResponseFormed);
|
||||
}
|
||||
|
@ -72,7 +72,7 @@ TYPE NAME = __request;
|
||||
|
||||
#define OATPP_MACRO_API_CONTROLLER_HEADER_0(TYPE, NAME, PARAM_LIST) \
|
||||
auto __param_str_val_##NAME = __request->getHeader(#NAME); \
|
||||
if(__param_str_val_##NAME.isNull()){ \
|
||||
if(!__param_str_val_##NAME){ \
|
||||
return ApiController::handleError(Status::CODE_400, "Missing HEADER parameter '" #NAME "'"); \
|
||||
} \
|
||||
bool __param_validation_check_##NAME; \
|
||||
@ -83,7 +83,7 @@ if(!__param_validation_check_##NAME){ \
|
||||
|
||||
#define OATPP_MACRO_API_CONTROLLER_HEADER_1(TYPE, NAME, PARAM_LIST) \
|
||||
auto __param_str_val_##NAME = __request->getHeader(OATPP_MACRO_FIRSTARG PARAM_LIST); \
|
||||
if(__param_str_val_##NAME.isNull()){ \
|
||||
if(!__param_str_val_##NAME){ \
|
||||
return ApiController::handleError(Status::CODE_400, \
|
||||
oatpp::String("Missing HEADER parameter '") + OATPP_MACRO_FIRSTARG PARAM_LIST + "'"); \
|
||||
} \
|
||||
@ -126,7 +126,7 @@ OATPP_MACRO_API_CONTROLLER_HEADER_INFO_CHOOSER_EXP(TYPE, NAME, PARAM_LIST, OATPP
|
||||
|
||||
#define OATPP_MACRO_API_CONTROLLER_PATH_0(TYPE, NAME, PARAM_LIST) \
|
||||
auto __param_str_val_##NAME = __request->getPathVariable(#NAME); \
|
||||
if(__param_str_val_##NAME.isNull()){ \
|
||||
if(!__param_str_val_##NAME){ \
|
||||
return ApiController::handleError(Status::CODE_400, "Missing PATH parameter '" #NAME "'"); \
|
||||
} \
|
||||
bool __param_validation_check_##NAME; \
|
||||
@ -137,7 +137,7 @@ if(!__param_validation_check_##NAME){ \
|
||||
|
||||
#define OATPP_MACRO_API_CONTROLLER_PATH_1(TYPE, NAME, PARAM_LIST) \
|
||||
auto __param_str_val_##NAME = __request->getPathVariable(OATPP_MACRO_FIRSTARG PARAM_LIST); \
|
||||
if(__param_str_val_##NAME.isNull()){ \
|
||||
if(!__param_str_val_##NAME){ \
|
||||
return ApiController::handleError(Status::CODE_400, \
|
||||
oatpp::String("Missing PATH parameter '") + OATPP_MACRO_FIRSTARG PARAM_LIST + "'"); \
|
||||
} \
|
||||
@ -192,7 +192,7 @@ info->body.type = oatpp::data::mapping::type::__class::String::getType();
|
||||
#define OATPP_MACRO_API_CONTROLLER_BODY_DTO(TYPE, NAME, PARAM_LIST) \
|
||||
TYPE NAME; \
|
||||
__request->readBodyToDto(NAME, getDefaultObjectMapper()); \
|
||||
if(NAME.isNull()) { \
|
||||
if(!NAME) { \
|
||||
return ApiController::handleError(Status::CODE_400, "Missing valid body parameter '" #NAME "'"); \
|
||||
}
|
||||
|
||||
|
@ -50,7 +50,7 @@ std::shared_ptr<Pattern> Pattern::parse(p_char8 data, v_int32 size){
|
||||
if(a == '/'){
|
||||
|
||||
if(i - lastPos > 0){
|
||||
auto part = Part::createShared(Part::FUNCTION_CONST, oatpp::String(&data[lastPos], i - lastPos, true));
|
||||
auto part = Part::createShared(Part::FUNCTION_CONST, oatpp::String((const char*)&data[lastPos], i - lastPos, true));
|
||||
result->m_parts->pushBack(part);
|
||||
}
|
||||
|
||||
@ -59,7 +59,7 @@ std::shared_ptr<Pattern> Pattern::parse(p_char8 data, v_int32 size){
|
||||
} else if(a == '*'){
|
||||
lastPos = i + 1;
|
||||
if(size > lastPos){
|
||||
auto part = Part::createShared(Part::FUNCTION_ANY_END, oatpp::String(&data[lastPos], size - lastPos, true));
|
||||
auto part = Part::createShared(Part::FUNCTION_ANY_END, oatpp::String((const char*)&data[lastPos], size - lastPos, true));
|
||||
result->m_parts->pushBack(part);
|
||||
}else{
|
||||
auto part = Part::createShared(Part::FUNCTION_ANY_END, oatpp::String(0));
|
||||
@ -75,7 +75,7 @@ std::shared_ptr<Pattern> Pattern::parse(p_char8 data, v_int32 size){
|
||||
}
|
||||
|
||||
if(i > lastPos){
|
||||
auto part = Part::createShared(Part::FUNCTION_VAR, oatpp::String(&data[lastPos], i - lastPos, true));
|
||||
auto part = Part::createShared(Part::FUNCTION_VAR, oatpp::String((const char*)&data[lastPos], i - lastPos, true));
|
||||
result->m_parts->pushBack(part);
|
||||
}else{
|
||||
auto part = Part::createShared(Part::FUNCTION_VAR, oatpp::String(0));
|
||||
@ -91,7 +91,7 @@ std::shared_ptr<Pattern> Pattern::parse(p_char8 data, v_int32 size){
|
||||
}
|
||||
|
||||
if(i - lastPos > 0){
|
||||
auto part = Part::createShared(Part::FUNCTION_CONST, oatpp::String(&data[lastPos], i - lastPos, true));
|
||||
auto part = Part::createShared(Part::FUNCTION_CONST, oatpp::String((const char*)&data[lastPos], i - lastPos, true));
|
||||
result->m_parts->pushBack(part);
|
||||
}
|
||||
|
||||
@ -151,7 +151,7 @@ std::shared_ptr<Pattern::MatchMap> Pattern::match(p_char8 url, v_int32 size){
|
||||
|
||||
if(caret.canContinue() && !caret.isAtChar('/')){
|
||||
if(caret.isAtChar('?') && (curr == nullptr || curr->getData()->function == Part::FUNCTION_ANY_END)) {
|
||||
tail = oatpp::String(caret.getCurrData(), size - caret.getPosition(), true);
|
||||
tail = oatpp::String((const char*)caret.getCurrData(), size - caret.getPosition(), true);
|
||||
return MatchMap::createShared(vars, tail);
|
||||
}
|
||||
return nullptr;
|
||||
@ -159,7 +159,7 @@ std::shared_ptr<Pattern::MatchMap> Pattern::match(p_char8 url, v_int32 size){
|
||||
|
||||
}else if(part->function == Part::FUNCTION_ANY_END){
|
||||
if(size > caret.getPosition()){
|
||||
tail = oatpp::String(caret.getCurrData(), size - caret.getPosition(), true);
|
||||
tail = oatpp::String((const char*)caret.getCurrData(), size - caret.getPosition(), true);
|
||||
}
|
||||
return MatchMap::createShared(vars, tail);
|
||||
}else if(part->function == Part::FUNCTION_VAR){
|
||||
@ -172,14 +172,14 @@ std::shared_ptr<Pattern::MatchMap> Pattern::match(p_char8 url, v_int32 size){
|
||||
v_char8 a = findSysChar(caret);
|
||||
if(a == '?') {
|
||||
if(curr == nullptr || curr->getData()->function == Part::FUNCTION_ANY_END) {
|
||||
vars->put(oatpp::String(part->text.get(), true), label.toString());
|
||||
tail = oatpp::String(caret.getCurrData(), size - caret.getPosition(), true);
|
||||
vars->put(oatpp::String(part->text), label.toString());
|
||||
tail = oatpp::String((const char*)caret.getCurrData(), size - caret.getPosition(), true);
|
||||
return MatchMap::createShared(vars, tail);
|
||||
}
|
||||
caret.findChar('/');
|
||||
}
|
||||
|
||||
vars->put(oatpp::String(part->text.get(), true), label.toString());
|
||||
vars->put(oatpp::String(part->text), label.toString());
|
||||
|
||||
}
|
||||
|
||||
|
@ -69,8 +69,8 @@ public:
|
||||
return m_subscriber->processUrlAsync(parentCoroutine, callback, param);
|
||||
}
|
||||
|
||||
bool isNull() const {
|
||||
return m_subscriber == nullptr;
|
||||
explicit operator bool() const {
|
||||
return m_subscriber != nullptr;
|
||||
}
|
||||
|
||||
std::shared_ptr<Pattern::MatchMap> matchMap;
|
||||
|
Loading…
x
Reference in New Issue
Block a user