Compare commits

...

6 Commits

Author SHA1 Message Date
brother-戎 2b4104d252
[BUG FIX] fix up naming signData && url encoding (#139)
* 1. fix naming signData
2. fix url encoding

* rollback CURLOPT_POSTFIELDS

* fix up
2024-01-16 17:05:17 +08:00
brother-戎 f58d97ab21
fix (#138) 2024-01-16 11:39:31 +08:00
Visual Ten 21ee34dbf1
feature 支持指定endpoint时携带参数,去除编译警告 (#135)
* feature 支持指定endpoint时携带参数,去除编译警告

* fix 编码风格统一

* Update PropertyKeyConst.cpp

* feature 支持查询endpoint和查询配置时的contextPath差异,支持传入AppName

* fix 新增endpointQueryParam,支持与namespace同步设置
2023-11-23 11:39:10 +08:00
HakureiGenei 60dc0fb86c
Merge pull request #111 from nacos-group/develop
issue #85 and NacosConfigService::getConfig behavior change
2022-04-10 23:40:19 +08:00
TTTTTAAAAAKKKKEEEENNNN 707be611f0 issue #85 fix, getConfig behavior polish
issue #85 fix:
If the client fails to login to nacos server at initialization stage, it will crash
If the server's password is changed when the client is running, the client will try to login the server every 30 seconds and put this issue to log

NacosConfigService::getConfig behavior change:
When the server returns 403(no permission), the client will try to get local snapshot, if there is no snapshot, the getConfig() will throw an exception with errorcode = 403 and the user is to decide failback strategy
2022-04-10 23:38:00 +08:00
TTTTTAAAAAKKKKEEEENNNN e145b91061 compatible for linux 2022-01-26 16:48:58 +08:00
20 changed files with 137 additions and 40 deletions

View File

@ -1,5 +1,6 @@
#include <iostream>
#include "Nacos.h"
#include <stdio.h>
using namespace std;
using namespace nacos;

View File

@ -1,5 +1,6 @@
#include <iostream>
#include "Nacos.h"
#include <stdio.h>
using namespace std;
using namespace nacos;

View File

@ -14,16 +14,22 @@ public:
static const NacosString NAMESPACE;
static const NacosString ENDPOINT_QUERY_PARAMS;
static const NacosString ACCESS_KEY;
static const NacosString SECRET_KEY;
static const NacosString APP_NAME;
static const NacosString RAM_ROLE_NAME;
static const NacosString SERVER_ADDR;
static const NacosString CONTEXT_PATH;
static const NacosString ENDPOINT_CONTEXT_PATH;
static const NacosString CLUSTER_NAME;
static const NacosString ENCODE;

View File

@ -10,6 +10,7 @@
#include <stdlib.h>
#include "src/log/Logger.h"
#include "src/utils/ConfigParserUtils.h"
#include "src/utils/Env.h"
using namespace std;
@ -49,7 +50,7 @@ void AppConfigManager::clearConfig() {
appConfig.clear();
}
const NacosString &AppConfigManager::get(const NacosString &key) {
const NacosString& AppConfigManager::get(const NacosString &key) {
if (appConfig.count(key) == 0) {
return NULLSTR;
}
@ -59,7 +60,13 @@ const NacosString &AppConfigManager::get(const NacosString &key) {
{
return NULLSTR;
}
return appConfig[key];
Properties::iterator iter = appConfig.find(key);
if (iter == appConfig.end()) {
return NULLSTR;
}
return iter->second;
}
void AppConfigManager::set(const NacosString &key, const NacosString &value) {
@ -87,6 +94,15 @@ AppConfigManager::AppConfigManager(const NacosString &_configFile) {
configFile = _configFile;
}
NacosString getAppNameFromEnv() {
const char* env = getEnv("APP_NAME");
if (env != NULL && std::char_traits<char>::length(env) > 0) {
return NacosString(env);
}
return NacosStringOps::nullstr;
}
void AppConfigManager::initDefaults() {
appConfig.clear();
//appConfig[PropertyKeyConst::NAMESPACE] = "public";
@ -100,6 +116,11 @@ void AppConfigManager::initDefaults() {
set(PropertyKeyConst::LOCAL_IP, NetUtils::getHostIp());
set(PropertyKeyConst::UDP_RECEIVER_PORT, "30620");
NacosString appName = getAppNameFromEnv();
if (!NacosStringOps::isNullStr(appName)) {
set(PropertyKeyConst::APP_NAME, appName);
}
NacosString homedir = DirUtils::getHome();
set(PropertyKeyConst::INSTANCE_ID_PREFIX, NetUtils::getHostName());

View File

@ -47,7 +47,7 @@ public:
bool contains(const NacosString &key) const;
Properties getAllConfig() const { return appConfig; };
const Properties& getAllConfig() { return appConfig; };
const NacosString & getContextPath() const { return _contextPath; };

View File

@ -26,7 +26,7 @@ ConcurrentDiskUtil::getFileContent(const NacosString &file, const NacosString &c
FILE *fp = fopen(file.c_str(), "rb");
if (fp == NULL) {
char errbuf[100];
sprintf(errbuf, "Failed to open file for read, errno: %d", errno);
snprintf(errbuf, sizeof(errbuf), "Failed to open file for read, errno: %d", errno);
//TODO:add errorcode
throw IOException(NacosException::UNABLE_TO_OPEN_FILE, errbuf);
}
@ -57,7 +57,7 @@ bool ConcurrentDiskUtil::writeFileContent
FILE *fp = fopen(path.c_str(), "wb");
if (fp == NULL) {
char errbuf[100];
sprintf(errbuf, "Failed to open file for write, errno: %d", errno);
snprintf(errbuf, sizeof(errbuf), "Failed to open file for write, errno: %d", errno);
//TODO:add errorcode
throw IOException(NacosException::UNABLE_TO_OPEN_FILE, errbuf);
}

View File

@ -44,8 +44,9 @@ HttpResult ConfigProxy::reqAPI
HttpDelegate *_httpDelegate = _objectConfigData->_httpDelegate;
//TODO: refactor to a common procedure
NacosString secretKey = _objectConfigData->_appConfigManager->get(PropertyKeyConst::SECRET_KEY);
NacosString accessKey = _objectConfigData->_appConfigManager->get(PropertyKeyConst::ACCESS_KEY);
const NacosString& secretKey = _objectConfigData->_appConfigManager->get(PropertyKeyConst::SECRET_KEY);
const NacosString& accessKey = _objectConfigData->_appConfigManager->get(PropertyKeyConst::ACCESS_KEY);
const NacosString& appName = _objectConfigData->_appConfigManager->get(PropertyKeyConst::APP_NAME);
//If SPAS security credentials are set, SPAS is enabled
if (!ParamUtils::isBlank(secretKey) && !ParamUtils::isBlank(accessKey)) {
@ -57,6 +58,11 @@ HttpResult ConfigProxy::reqAPI
ParamUtils::addKV(headers, "Spas-AccessKey", accessKey);
}
if (!NacosStringOps::isNullStr(appName)) {
ParamUtils::addKV(headers, "Client-AppName", appName);
}
switch (method) {
case IHttpCli::GET:
return _httpDelegate->httpGet(path, headers, paramValues, encoding, readTimeoutMs);

View File

@ -74,11 +74,14 @@ NacosString NacosConfigService::getConfigInner
result = _objectConfigData->_clientWorker->getServerConfig(tenant, dataId, group, timeoutMs);
} catch (NacosException &e) {
if (e.errorcode() == NacosException::NO_RIGHT) {
throw e;
log_error("Invalid credential, e: %d = %s\n", e.errorcode(), e.what());
}
const NacosString &clientName = _appConfigManager->get(PropertyKeyConst::CLIENT_NAME);
result = _localSnapshotManager->getSnapshot(clientName, dataId, group, tenant);
if (e.errorcode() == NacosException::NO_RIGHT && NacosStringOps::isNullStr(result)) {
//permission denied and no failback, let user decide what to do
throw e;
}
}
return result;
}

View File

@ -9,16 +9,22 @@ const NacosString PropertyKeyConst::ENDPOINT_PORT = "endpointPort";
const NacosString PropertyKeyConst::NAMESPACE = "namespace";
const NacosString PropertyKeyConst::ENDPOINT_QUERY_PARAMS = "endpointQueryParams";
const NacosString PropertyKeyConst::ACCESS_KEY = "accessKey";
const NacosString PropertyKeyConst::SECRET_KEY = "secretKey";
const NacosString PropertyKeyConst::APP_NAME = "appName";
const NacosString PropertyKeyConst::RAM_ROLE_NAME = "ramRoleName";
const NacosString PropertyKeyConst::SERVER_ADDR = "serverAddr";
const NacosString PropertyKeyConst::CONTEXT_PATH = "nacos.server.contextpath";
const NacosString PropertyKeyConst::ENDPOINT_CONTEXT_PATH = "endpointContextPath";
const NacosString PropertyKeyConst::CLUSTER_NAME = "clusterName";
const NacosString PropertyKeyConst::ENCODE = "encode";

View File

@ -5,6 +5,7 @@
#include "config/ConfigService.h"
#include "NacosExceptions.h"
#include "Compatibility.h"
#include <stdint.h>
namespace nacos{
class HttpDelegate;

View File

@ -4,6 +4,7 @@
#include "constant/UtilAndComs.h"
#include "src/utils/UuidUtils.h"
#include "src/utils/ParamUtils.h"
#include "src/utils/url.h"
#include "src/utils/RandomUtils.h"
#include "src/json/JSON.h"
#include "src/http/HttpStatus.h"
@ -151,13 +152,14 @@ NacosString NamingProxy::callServer
NacosString NamingProxy::getDataToSign(const std::list <NacosString> &paramValues, NacosString &nowTimeMs) {
const NacosString &serviceName = ParamUtils::findByKey(paramValues, NamingConstant::SERVICE_NAME);
const NacosString &groupName = ParamUtils::findByKey(paramValues, NamingConstant::GROUP_NAME);
NacosString dataToSign = "";
if (!ParamUtils::isBlank(serviceName)) {
dataToSign = serviceName + "@@";
if ((!ParamUtils::isBlank(serviceName) && serviceName.find(NamingConstant::SPLITER) != std::string::npos) || ParamUtils::isBlank(groupName)) {
dataToSign = nowTimeMs + NamingConstant::SPLITER + serviceName;
} else {
dataToSign = nowTimeMs + NamingConstant::SPLITER + groupName + NamingConstant::SPLITER + serviceName;
}
dataToSign += nowTimeMs;
return dataToSign;
}
@ -198,7 +200,7 @@ NacosString NamingProxy::callServer
ParamUtils::addKV(params, "data", dataToSign);
ParamUtils::addKV(params, "ak", accessKey);
} else {
requestUrl = requestUrl + "?signature=" + signature + "&data=" + dataToSign + "&ak=" + accessKey;
requestUrl = requestUrl + "?signature=" + urlencode(signature) + "&data=" + dataToSign + "&ak=" + accessKey;
}
}

View File

@ -18,7 +18,7 @@ SecurityManager::SecurityManager(ObjectConfigData *objectConfigData) {
}
void SecurityManager::doLogin(const NacosString &serverAddr) NACOS_THROW(NacosException, NetworkException) {
//TODO:refactor string constants
NacosString url = serverAddr + "/" + ConfigConstant::DEFAULT_CONTEXT_PATH + "/v1/auth/users/login";
NacosString url = serverAddr + "/" + _objectConfigData->_appConfigManager->getContextPath() + "/v1/auth/users/login";
list <NacosString> headers;
list <NacosString> paramValues;
@ -62,8 +62,17 @@ void SecurityManager::login() NACOS_THROW (NacosException) {
//for some cases, e.g.:invalid username/password,
//we should throw exception directly since retry on another node will not correct this problem
if (e.errorcode() == NacosException::INVALID_LOGIN_CREDENTIAL) {
/**
* Here we don't need to keep log for it, because there are 3 situations where we will call this login() routine:
* 1. Initialization stage of NamingService
* 2. Initialization stage of ConfigService
* 3. tokenRefreshThreadFunc's invocation of this routine to refresh the credentials
* In case 1 and case 2, the program will crash, because these situations are considered as a config error of the program, so let it crash
* In case 3, the log is printed by tokenRefreshThreadFunc to remind the dev-ops to correct the config
*/
throw e;
}
log_error("Unknown error while login to server, e:%d = %s\n", e.errorcode(), e.what());
continue;
}
//login succeeded
@ -116,8 +125,14 @@ void *SecurityManager::tokenRefreshThreadFunc(void *param) {
thisObj->login();
} catch (NacosException &e) {
if (e.errorcode() == NacosException::INVALID_LOGIN_CREDENTIAL) {
log_error("Invalid credential!\n");
throw e;//Invalid login credential, let it crash
/**
* invalid credential while the application is running, wait for a moment and retry
* since the existing data in the nacos client is still usable for the application
* we should keep the application alive for the Availability, but the Consistency, in this case, is NOT guaranteed
* the error log reminds the dev-ops to check the config
*/
log_error("Invalid credential, please check your server settings!\n");
sleep(30);
} else if (e.errorcode() == NacosException::ALL_SERVERS_TRIED_AND_FAILED) {
log_warn("Network down, sleep for 30 secs and retry\n");
sleep(30);//network down, wait for a moment

View File

@ -104,22 +104,44 @@ void ServerListManager::initAll() NACOS_THROW(NacosException) {
}
isFixed = false;
NacosString endpoint = getEndpoint();
const NacosString& endpoint = getEndpoint();
NacosString endpoint_lc = ParamUtils::toLower(endpoint);
//endpoint doesn't start with http or https prefix, consider it as http
if (!(endpoint_lc.find("http://") == 0) && !(endpoint_lc.find("https://") == 0)) {
endpoint = "http://" + endpoint;
if (endpoint_lc.find("http://") == NacosString::npos && endpoint_lc.find("https://") == NacosString::npos) {
endpoint_lc = "http://" + endpoint_lc;
}
if (NacosStringOps::isNullStr(getNamespace())) {
addressServerUrl = endpoint + ":" + NacosStringOps::valueOf(getEndpointPort()) + "/" +
getContextPath() + "/" + getClusterName();
} else {
addressServerUrl = endpoint + ":" + NacosStringOps::valueOf(getEndpointPort()) + "/" +
getContextPath() + "/" + getClusterName() + "?namespace=" + getNamespace();
addressServerUrl = endpoint_lc + ":" + NacosStringOps::valueOf(getEndpointPort());
const NacosString& endpointContextPath = getEndpointContextPath();
const NacosString& contextPath = endpointContextPath.empty() ? getContextPath() : endpointContextPath;
if (!contextPath.empty()) {
if (contextPath[0] != '/') {
// not start by /
addressServerUrl += ("/" + contextPath);
} else {
addressServerUrl += contextPath;
}
}
const NacosString& clusterName = getClusterName();
if (!clusterName.empty()) {
if (clusterName[0] != '/') {
addressServerUrl += ("/" + clusterName);
} else {
addressServerUrl += clusterName;
}
}
const NacosString& namespaceInfo = getNamespace();
if (!namespaceInfo.empty()) {
addressServerUrl += ("?namespace=" + namespaceInfo);
}
const NacosString& endpointQueryParams = getEndpointQueryParams();
if (!endpointQueryParams.empty()) {
addressServerUrl += ((namespaceInfo.empty() ? "?" : "&") + endpointQueryParams);
}
log_debug("Assembled addressServerUrl:%s\n", addressServerUrl.c_str());
serverList = pullServerList();
start();
}
@ -152,7 +174,7 @@ list <NacosServerInfo> ServerListManager::tryPullServerListFromNacosServer() NAC
log_debug("Trying to access server:%s\n", server.getCompleteAddress().c_str());
try {
HttpResult serverRes = _objectConfigData->_httpDelegate->httpGet(
server.getCompleteAddress() + "/" + ConfigConstant::DEFAULT_CONTEXT_PATH + "/"
server.getCompleteAddress() + "/" + _objectConfigData->_appConfigManager->getContextPath() + "/"
+ ConfigConstant::PROTOCOL_VERSION + "/" + ConfigConstant::GET_SERVERS_PATH,
headers, paramValues, NULLSTR, _read_timeout);
return JSON::Json2NacosServerInfo(serverRes.content);

View File

@ -49,15 +49,19 @@ private:
public:
//Cluster info
inline NacosString getClusterName() const { return _objectConfigData->_appConfigManager->get(PropertyKeyConst::CLUSTER_NAME); };
inline const NacosString& getClusterName() { return _objectConfigData->_appConfigManager->get(PropertyKeyConst::CLUSTER_NAME); };
inline NacosString getEndpoint() const { return _objectConfigData->_appConfigManager->get(PropertyKeyConst::ENDPOINT); };
inline const NacosString& getEndpoint() { return _objectConfigData->_appConfigManager->get(PropertyKeyConst::ENDPOINT); };
inline int getEndpointPort() const { return atoi(_objectConfigData->_appConfigManager->get(PropertyKeyConst::ENDPOINT_PORT).c_str()); };
inline int getEndpointPort() { return atoi(_objectConfigData->_appConfigManager->get(PropertyKeyConst::ENDPOINT_PORT).c_str()); };
inline const NacosString &getContextPath() const;
inline NacosString getNamespace() const { return _objectConfigData->_appConfigManager->get(PropertyKeyConst::NAMESPACE); };
inline const NacosString& getEndpointContextPath() { return _objectConfigData->_appConfigManager->get(PropertyKeyConst::ENDPOINT_CONTEXT_PATH); }
inline const NacosString& getNamespace() { return _objectConfigData->_appConfigManager->get(PropertyKeyConst::NAMESPACE); };
inline const NacosString& getEndpointQueryParams() { return _objectConfigData->_appConfigManager->get(PropertyKeyConst::ENDPOINT_QUERY_PARAMS); }
std::list <NacosServerInfo> __debug();//DO NOT use, may be changed without prior notification

9
src/utils/Env.h Normal file
View File

@ -0,0 +1,9 @@
#include <stdlib.h>
const char* getEnv(const char* env) {
if (env == NULL) {
return NULL;
}
char* var = getenv(env);
return var;
}

View File

@ -21,7 +21,7 @@ NacosString UuidUtils::generateUuid() {
RandomUtils::getRandomBuffer(random_num, UUID_LEN_BYTES);
int32_t *val_ptr = (int32_t *) random_num;
sprintf(str_buffer, "%08X%08X%08X%08X", val_ptr[0], val_ptr[1], val_ptr[2], val_ptr[3]);
snprintf(str_buffer, sizeof(str_buffer), "%08X%08X%08X%08X", val_ptr[0], val_ptr[1], val_ptr[2], val_ptr[3]);
NacosString uuid = str_buffer;
return uuid;

View File

@ -29,7 +29,7 @@ public:
if (executor == NULL) {
throw NacosException(NacosException::INVALID_CONFIG_PARAM, "no executor");
}
printf(">>>>>>>>>>>>>>>>>>Task %s triggered, time =%ld (%ld), interval = %ld\n", getTaskName().c_str(), now_ms/1000, now_ms, interval_calc);
printf(">>>>>>>>>>>>>>>>>>Task %s triggered, time =%llu (%llu), interval = %llu\n", getTaskName().c_str(), now_ms/1000, now_ms, interval_calc);
sleep(1);
}

View File

@ -22,8 +22,8 @@ bool testDeleteConfig() {
for (int i = 5; i < 50; i++) {
char key_s[200];
char val_s[200];
sprintf(key_s, "Key%d", i);
sprintf(val_s, "v__%d", i);
snprintf(key_s, sizeof(key_s), "Key%d", i);
snprintf(val_s, sizeof(val_s), "v__%d", i);
try {
bSucc = n->removeConfig(key_s, NULLSTR);

View File

@ -25,8 +25,8 @@ bool testPublishConfig() {
for (int i = 0; i < 50; i++) {
char key_s[200];
char val_s[200];
sprintf(key_s, "Key%d", i);
sprintf(val_s, "v__%d", i);
snprintf(key_s, sizeof(key_s), "Key%d", i);
snprintf(val_s, sizeof(val_s), "v__%d", i);
NacosString ss = "";
try {

View File

@ -25,8 +25,8 @@ bool testPublishConfigWithHttpPrefix() {
for (int i = 0; i < 50; i++) {
char key_s[200];
char val_s[200];
sprintf(key_s, "Key%d", i);
sprintf(val_s, "v__%d", i);
snprintf(key_s, sizeof(key_s), "Key%d", i);
snprintf(val_s, sizeof(val_s), "v__%d", i);
NacosString ss = "";
try {