Skip to content

Commit a8e294f

Browse files
committed
Merge pull request #34 from cyshi/master
add interface to posting protobuf data
2 parents cd10b38 + c70ef1b commit a8e294f

8 files changed

Lines changed: 168 additions & 79 deletions

File tree

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
# -*- coding:UTF-8 -*-
2+
3+
# Copyright (c) 2014 Baidu.com, Inc. All rights reserved.
4+
# Use of this source code is governed by a BSD-style license that can be
5+
# found in the LICENSE file.
6+
7+
# This is a sample code to show how to use python client of sofa-pbrpc.
8+
#
9+
# Preconditions:
10+
# * The protobuf python lib has been installed.
11+
# * The sofa-pbrpc python lib has been installed.
12+
# * The server in ../../sample/echo has been started.
13+
#
14+
# For more, please refer to `./README'.
15+
16+
from sofa.pbrpc import client
17+
import echo_service_pb2
18+
import sys
19+
import urllib2
20+
21+
# Prepare post data
22+
echo_request = echo_service_pb2.EchoRequest()
23+
echo_request.message = 'Hello World'
24+
send_data = echo_request.SerializeToString()
25+
26+
# Prepare http request
27+
url = 'http://localhost:12321/sofa.pbrpc.test.EchoServer.Echo'
28+
accept = 'application/protobuf'
29+
headers = { 'Accept' : accept }
30+
request = urllib2.Request(url, send_data, headers)
31+
32+
# Send request
33+
try:
34+
response = urllib2.urlopen(request)
35+
except Exception as e:
36+
print "ERROR: Send fail: %s" % e.reason
37+
sys.exit(1)
38+
39+
# Read http body
40+
recv_data = response.read()
41+
42+
# check failure
43+
if response.info().getheader('Content-Type') != accept:
44+
print "ERROR: %s" % recv_data
45+
sys.exit(1)
46+
47+
# print response
48+
echo_response = echo_service_pb2.EchoResponse()
49+
echo_response.ParseFromString(recv_data)
50+
print "Response:\n%s" % echo_response.message

src/sofa/pbrpc/http_rpc_request.cc

Lines changed: 84 additions & 68 deletions
Original file line numberDiff line numberDiff line change
@@ -123,37 +123,6 @@ void HTTPRpcRequest::ProcessRequest(
123123
}
124124
}
125125

126-
std::string json_str;
127-
if (_type == POST)
128-
{
129-
json_str = _req_body->ToString();
130-
}
131-
else
132-
{
133-
json_str = _query_params["request"];
134-
}
135-
if (json_str.empty())
136-
{
137-
// if null json str, set as null object
138-
json_str = "{}";
139-
}
140-
141-
std::string err;
142-
_req_json = ParseJson(json_str.c_str(), err);
143-
if (_req_json == NULL)
144-
{
145-
#if defined( LOG )
146-
LOG(ERROR) << "ProcessRequest(): " << RpcEndpointToString(_remote_endpoint)
147-
<< ": {" << SequenceId() << "}: parse json failed: " << err;
148-
#else
149-
SLOG(ERROR, "ProcessRequest(): %s: {%lu}: parse json failed: %s",
150-
RpcEndpointToString(_remote_endpoint).c_str(), SequenceId(), err.c_str());
151-
#endif
152-
SendFailedResponse(server_stream,
153-
RPC_ERROR_PARSE_REQUEST_MESSAGE, "parse json failed: " + err);
154-
return;
155-
}
156-
157126
MethodBoard* method_board = FindMethodBoard(service_pool, service_name, method_name);
158127
if (method_board == NULL)
159128
{
@@ -173,18 +142,57 @@ void HTTPRpcRequest::ProcessRequest(
173142
const google::protobuf::MethodDescriptor* method_desc = method_board->Descriptor();
174143

175144
google::protobuf::Message* request = service->GetRequestPrototype(method_desc).New();
176-
if (jsonobject2pb(_req_json, request, err) < 0)
145+
if (_type == POST_PB)
177146
{
147+
bool parse_request_return = request->ParseFromZeroCopyStream(_req_body.get());
148+
if (!parse_request_return)
149+
{
178150
#if defined( LOG )
179-
LOG(ERROR) << "ProcessRequest(): " << RpcEndpointToString(_remote_endpoint)
180-
<< ": {" << SequenceId() << "}: parse json to pb failed: " << err;
151+
LOG(ERROR) << "ProcessRequest(): " << RpcEndpointToString(_remote_endpoint)
152+
<< ": {" << SequenceId() << "}: parse pb body failed";
181153
#else
182-
SLOG(ERROR, "ProcessRequest(): %s: {%lu}: parse json to pb failed: %s",
183-
RpcEndpointToString(_remote_endpoint).c_str(), SequenceId(), err.c_str());
154+
SLOG(ERROR, "ProcessRequest(): %s: {%lu}: parse pb body failed",
155+
RpcEndpointToString(_remote_endpoint).c_str(), SequenceId());
184156
#endif
185-
SendFailedResponse(server_stream,
186-
RPC_ERROR_PARSE_REQUEST_MESSAGE, "parse json to pb failed: " + err);
187-
return;
157+
SendFailedResponse(server_stream,
158+
RPC_ERROR_PARSE_REQUEST_MESSAGE, "parse pb body failed");
159+
delete request;
160+
return;
161+
}
162+
}
163+
else
164+
{
165+
std::string json_str;
166+
if (_type == POST)
167+
{
168+
json_str = _req_body->ToString();
169+
}
170+
else
171+
{
172+
json_str = _query_params["request"];
173+
}
174+
if (json_str.empty())
175+
{
176+
// if null json str, set as null object
177+
json_str = "{}";
178+
}
179+
180+
std::string err;
181+
_req_json = ParseJson(json_str.c_str(), err);
182+
if (_req_json == NULL || jsonobject2pb(_req_json, request, err) < 0)
183+
{
184+
#if defined( LOG )
185+
LOG(ERROR) << "ProcessRequest(): " << RpcEndpointToString(_remote_endpoint)
186+
<< ": {" << SequenceId() << "}: parse json failed: " << err;
187+
#else
188+
SLOG(ERROR, "ProcessRequest(): %s: {%lu}: parse json failed: %s",
189+
RpcEndpointToString(_remote_endpoint).c_str(), SequenceId(), err.c_str());
190+
#endif
191+
SendFailedResponse(server_stream,
192+
RPC_ERROR_PARSE_REQUEST_MESSAGE, "parse json failed: " + err);
193+
delete request;
194+
return;
195+
}
188196
}
189197

190198
google::protobuf::Message* response = service->GetResponsePrototype(method_desc).New();
@@ -208,14 +216,24 @@ ReadBufferPtr HTTPRpcRequest::AssembleSucceedResponse(
208216
const google::protobuf::Message* response,
209217
std::string& err)
210218
{
211-
std::string json_str;
212-
pb2json(response, json_str);
213-
214219
WriteBuffer write_buffer;
215-
if (!RenderJsonResponse(&write_buffer, json_str))
220+
if (_type == POST_PB)
216221
{
217-
err = "render json response failed";
218-
return ReadBufferPtr();
222+
if (!RenderResponse(&write_buffer, PROTOBUF, response->SerializeAsString()))
223+
{
224+
err = "render protobuf response failed";
225+
return ReadBufferPtr();
226+
}
227+
}
228+
else
229+
{
230+
std::string json_str;
231+
pb2json(response, json_str);
232+
if (!RenderResponse(&write_buffer, JSON, json_str))
233+
{
234+
err = "render json response failed";
235+
return ReadBufferPtr();
236+
}
219237
}
220238

221239
ReadBufferPtr read_buffer(new ReadBuffer());
@@ -233,7 +251,7 @@ ReadBufferPtr HTTPRpcRequest::AssembleFailedResponse(
233251
<< StringUtils::replace_all(reason, "\"", "\\\"") << "\"";
234252

235253
WriteBuffer write_buffer;
236-
if (!RenderJsonResponse(&write_buffer, oss.str()))
254+
if (!RenderResponse(&write_buffer, JSON, oss.str()))
237255
{
238256
err = "render json response failed";
239257
return ReadBufferPtr();
@@ -385,7 +403,7 @@ void HTTPRpcRequest::SendPage(
385403
const std::string& page)
386404
{
387405
WriteBuffer write_buffer;
388-
if (!RenderHtmlResponse(&write_buffer, page))
406+
if (!RenderResponse(&write_buffer, HTML, page))
389407
{
390408
#if defined( LOG )
391409
LOG(ERROR) << "SendPage(): " << RpcEndpointToString(_remote_endpoint)
@@ -415,35 +433,33 @@ void HTTPRpcRequest::SendError(
415433
SendPage(server_stream, oss.str());
416434
}
417435

418-
bool HTTPRpcRequest::RenderJsonResponse(
436+
bool HTTPRpcRequest::RenderResponse(
419437
google::protobuf::io::ZeroCopyOutputStream* output,
420-
const std::string& json)
438+
const RenderType type,
439+
const std::string& body)
421440
{
422441
std::ostringstream oss;
423-
oss << json.size();
442+
oss << body.size();
424443
google::protobuf::io::Printer printer(output, '$');
425444
printer.Print("HTTP/1.1 200 OK\r\n");
426-
printer.Print("Content-Type: application/json\r\n");
427-
printer.Print("Access-Control-Allow-Origin: *\r\n");
428-
printer.Print("Content-Length: $LENGTH$\r\n", "LENGTH", oss.str());
429-
printer.Print("\r\n");
430-
printer.PrintRaw(json);
431-
return !printer.failed();
432-
}
433-
434-
bool HTTPRpcRequest::RenderHtmlResponse(
435-
google::protobuf::io::ZeroCopyOutputStream* output,
436-
const std::string& html)
437-
{
438-
std::ostringstream oss;
439-
oss << html.size();
440-
google::protobuf::io::Printer printer(output, '$');
441-
printer.Print("HTTP/1.1 200 OK\r\n");
442-
printer.Print("Content-Type: text/html; charset=UTF-8\r\n");
445+
switch (type)
446+
{
447+
case JSON:
448+
printer.Print("Content-Type: application/json\r\n");
449+
break;
450+
case PROTOBUF:
451+
printer.Print("Content-Type: application/protobuf\r\n");
452+
break;
453+
case HTML:
454+
printer.Print("Content-Type: text/html; charset=UTF-8\r\n");
455+
break;
456+
default:
457+
break;
458+
}
443459
printer.Print("Access-Control-Allow-Origin: *\r\n");
444460
printer.Print("Content-Length: $LENGTH$\r\n", "LENGTH", oss.str());
445461
printer.Print("\r\n");
446-
printer.PrintRaw(html);
462+
printer.PrintRaw(body);
447463
return !printer.failed();
448464
}
449465

src/sofa/pbrpc/http_rpc_request.h

Lines changed: 13 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,14 @@ class HTTPRpcRequest : public RpcRequest
4747
const std::string& reason,
4848
std::string& err);
4949

50+
private:
51+
enum RenderType
52+
{
53+
JSON = 1,
54+
PROTOBUF = 2,
55+
HTML = 3
56+
};
57+
5058
private:
5159
// Parse http path.
5260
// @return false if parse failed.
@@ -64,13 +72,10 @@ class HTTPRpcRequest : public RpcRequest
6472
const RpcServerStreamWPtr& server_stream,
6573
const std::string& error);
6674

67-
static bool RenderJsonResponse(
68-
google::protobuf::io::ZeroCopyOutputStream* output,
69-
const std::string& json);
70-
71-
static bool RenderHtmlResponse(
75+
static bool RenderResponse(
7276
google::protobuf::io::ZeroCopyOutputStream* output,
73-
const std::string& html);
77+
const RenderType type,
78+
const std::string& body);
7479

7580
static rapidjson::Document* ParseJson(
7681
const char* str,
@@ -106,7 +111,8 @@ class HTTPRpcRequest : public RpcRequest
106111
enum Type
107112
{
108113
GET = 0,
109-
POST = 1
114+
POST = 1,
115+
POST_PB = 2
110116
};
111117
Type _type;
112118
std::string _path;

src/sofa/pbrpc/http_rpc_request_parser.cc

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,10 @@
99
namespace sofa {
1010
namespace pbrpc {
1111

12+
const std::string HTTPRpcRequestParser::CONTENT_LENGTH = "Content-Length";
13+
const std::string HTTPRpcRequestParser::ACCEPT = "Accept";
14+
const std::string HTTPRpcRequestParser::ACCEPT_PROTOBUF = "application/protobuf";
15+
1216
HTTPRpcRequestParser::HTTPRpcRequestParser() :
1317
_state(PS_METHOD),
1418
_content_length(0),
@@ -199,7 +203,7 @@ int HTTPRpcRequestParser::ParseInternal(char c, std::string& err)
199203
if (c == '\n')
200204
{
201205
std::map<std::string, std::string>::const_iterator it =
202-
_req->_headers.find("Content-Length");
206+
_req->_headers.find(CONTENT_LENGTH);
203207
if (it != _req->_headers.end())
204208
{
205209
char* endptr = NULL;
@@ -210,6 +214,16 @@ int HTTPRpcRequestParser::ParseInternal(char c, std::string& err)
210214
return -1;
211215
}
212216
}
217+
218+
it = _req->_headers.find(ACCEPT);
219+
if (it != _req->_headers.end())
220+
{
221+
if (it->second == ACCEPT_PROTOBUF)
222+
{
223+
_req->_type = HTTPRpcRequest::POST_PB;
224+
}
225+
}
226+
213227
_state = PS_BODY;
214228
return 1;
215229
}

src/sofa/pbrpc/http_rpc_request_parser.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,9 @@ class HTTPRpcRequestParser : public RpcRequestParser
5656
std::string _header_value; // currrent parsing header value
5757
int64 _content_length; // body content length
5858
HTTPRpcRequestPtr _req;
59+
static const std::string CONTENT_LENGTH;
60+
static const std::string ACCEPT;
61+
static const std::string ACCEPT_PROTOBUF;
5962
}; // class HTTPRpcRequestParser
6063

6164
} // namespace pbrpc

test/perf_test/test_delay.sh

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
#!/bin/sh
1+
#!/bin/bash
22

33
#############################################
44
HOST=$HOSTNAME

test/perf_test/test_multi_server.sh

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
#!/bin/sh
1+
#!/bin/bash
22

33
#############################################
44
HOST=$HOSTNAME

test/perf_test/test_qps.sh

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
#!/bin/sh
1+
#!/bin/bash
22

33
#############################################
44
HOST=$HOSTNAME

0 commit comments

Comments
 (0)