Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

SRPCHttpServer中不支持自定url映射方法 #404

Open
rayinengineer opened this issue Aug 20, 2024 · 3 comments
Open

SRPCHttpServer中不支持自定url映射方法 #404

rayinengineer opened this issue Aug 20, 2024 · 3 comments

Comments

@rayinengineer
Copy link

rayinengineer commented Aug 20, 2024

像BRPC的服务框架,支持自定义url的映射,如

if (server.AddService(&queue_svc,
                      brpc::SERVER_DOESNT_OWN_SERVICE,
                      "/v1/queue/start   => start,"
                      "/v1/queue/stop    => stop,"
                      "/v1/queue/stats/* => get_stats") != 0) {
    LOG(ERROR) << "Fail to add queue_svc";
    return -1;
}

目前这边修改了一个

srpc/src/rpc_client.h 中增加两个模板特例

static inline void __set_request_uri_by_uri(const ParsedURI *uri,std::string& request_uri)
{
	if (uri->path && uri->path[0])
		request_uri = uri->path;
	else
		return;

	if (uri->query && uri->query[0])
	{
		request_uri += "?";
		request_uri += uri->query;
	}
}

template<>
inline void RPCClient<RPCTYPESRPCHttp>::task_init(COMPLEXTASK *task) const
{
	__task_init(task);
	std::string header_host;

	if (this->has_addr_info)
		header_host += this->params.host + ":" + std::to_string(this->params.port);
	else
		__set_host_by_uri(task->get_current_uri(), this->params.is_ssl, header_host);

	task->get_req()->set_header_pair("Host", header_host.c_str());

	std::string request_uri;
	__set_request_uri_by_uri(task->get_current_uri(),request_uri);
	if (!request_uri.empty())
	{
		task->get_req()->set_request_uri(request_uri);
	}
}

template<>
inline void RPCClient<RPCTYPEThriftHttp>::task_init(COMPLEXTASK *task) const
{
	__task_init(task);
	std::string header_host;

	if (this->has_addr_info)
		header_host += this->params.host + ":" + std::to_string(this->params.port);
	else
		__set_host_by_uri(task->get_current_uri(), this->params.is_ssl, header_host);

	task->get_req()->set_header_pair("Host", header_host.c_str());

	std::string request_uri;
	__set_request_uri_by_uri(task->get_current_uri(),request_uri);
	if (!request_uri.empty())
	{
		task->get_req()->set_request_uri(request_uri);
	}
}

srpc/src/message/rpc_message_srpc.cc

bool SRPCHttpRequest::serialize_meta()
{
	if (this->buf->size() > 0x7FFFFFFF)
		return false;

	RPCMeta *meta = static_cast<RPCMeta *>(this->meta);
	int data_type = meta->data_type();
	int compress_type = meta->compress_type();

	set_http_version("HTTP/1.1");
	set_method("POST");
	
	if (NULL == get_request_uri())
	{
		set_request_uri("/" + meta->mutable_request()->service_name() +
						"/" + meta->mutable_request()->method_name());
	}
	
	...
	
}

srpc/src/rpc_server.h中增加该接口,该接口比add_service多了一个原来的路径映射到service 方法,如"Test/abc => Echo,Test/cde => Echo2"

int add_service(RPCService *service, const std::string& mapping);

template<class RPCTYPE>
inline int RPCServer<RPCTYPE>::add_service(RPCService* service,const std::string& mapping)
{
	size_t pos = 0;
	size_t equalPos;
	while ((equalPos = mapping.find("=>", pos)) != std::string::npos) 
	{
		size_t nextKeyPos = mapping.find(',', equalPos);
		if (nextKeyPos == std::string::npos) {
			nextKeyPos = mapping.length();
        	}
		if (equalPos - pos > 0 && nextKeyPos - equalPos - 2 > 0)//key value
        	{
			std::string key = mapping.substr(pos, equalPos - pos);
            		std::string value = "/" + service->get_name() +
							"/" + mapping.substr(equalPos + 2, nextKeyPos - equalPos - 2);
			this->path_map.emplace(key,value);
		}
		pos = nextKeyPos + 1;
	}

	return add_service(service);
}

增加特例实现,因为get_request_uri、set_request_uri只有在HTTP请求中才能获取到

template<>
void RPCServer<RPCTYPESRPCHttp>::server_process(NETWORKTASK *task) const
{
	auto *req = task->get_req();
	auto *resp = task->get_resp();
	int status_code;

	const auto it = this->path_map.find(req->get_request_uri());
	if (it != this->path_map.cend())
	{
		req->set_request_uri(it->second);
	}

	if (!req->deserialize_meta())
		status_code = RPCStatusMetaError;
	else
	{
		auto *server_task = static_cast<TASK *>(task);
		RPCModuleData *task_data = server_task->mutable_module_data();
		req->get_meta_module_data(*task_data);

		RPCTYPESRPCHttp::server_reply_init(req, resp);
		auto *service = this->find_service(req->get_service_name());

		if (!service)
			status_code = RPCStatusServiceNotFound;
		else
		{
			auto *rpc = service->find_method(req->get_method_name());

			if (!rpc)
				status_code = RPCStatusMethodNotFound;
			else
			{
				for (auto *module : this->modules)
				{
					if (module)
						module->server_task_begin(server_task, *task_data);
				}

				status_code = req->decompress();
				if (status_code == RPCStatusOK)
					status_code = (*rpc)(server_task->worker);
			}
		}

		SERIES *series = static_cast<SERIES *>(series_of(task));
		series->set_module_data(task_data);
	}

	resp->set_status_code(status_code);
}
@rayinengineer
Copy link
Author

rayinengineer commented Aug 20, 2024

上述的srpc/src/rpc_client.h 中可以自定义url,如果有,就使用自定义的,如果没有就采用默认的;

struct srpc::RPCClientParams params = srpc::RPC_CLIENT_PARAMS_DEFAULT;
params.url = "http://127.0.0.1:1415/Test/Echo";
Example::SRPCHttpClient client(&params);

srpc/src/rpc_server.h中加url映射,调用方式:

server.add_service(&impl,"/Test/Echo=>Echo," "/Test/xxx=>Test");

@Barenboim
Copy link
Contributor

感谢感谢!我们看一下。也可以发PR讨论。

@holmes1412
Copy link
Contributor

holmes1412 commented Sep 3, 2024

@rayinengineer hi,感谢你提的这个需求,感觉非常合理呀~ 参考了下其他rpc系统的trans coding做法,没有统一的规范,所以我们当前使用了json来表达。比如:

SRPCHttpServer server;
ExampleServiceImpl impl;
server.add_service(&impl, "{ \"/test/echo\": \"Echo\"," "\"/no/method/for/test\": \"Test\" }");

麻烦有空了看看这个格式是否方便呢?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants