Skip to content

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

@rayinengineer

Description

@rayinengineer

像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);
}

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions