Skip to content
Projects
Groups
Snippets
Help
Loading...
Sign in / Register
Toggle navigation
B
brpc
Project
Project
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Packages
Packages
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
submodule
brpc
Commits
48a0e323
Commit
48a0e323
authored
Aug 02, 2017
by
gejun
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
patch svn r34953
Change-Id: I5cf6ae18d3cf0826da2d5d4efa2939e0d6e7d6b7
parent
4be6565c
Hide whitespace changes
Inline
Side-by-side
Showing
6 changed files
with
184 additions
and
62 deletions
+184
-62
http_rpc_protocol.cpp
brpc/policy/http_rpc_protocol.cpp
+35
-39
restful.cpp
brpc/restful.cpp
+2
-0
restful.h
brpc/restful.h
+1
-0
server.cpp
brpc/server.cpp
+33
-7
server.h
brpc/server.h
+34
-13
brpc_server_unittest.cpp
test/brpc_server_unittest.cpp
+79
-3
No files found.
brpc/policy/http_rpc_protocol.cpp
View file @
48a0e323
...
@@ -390,7 +390,8 @@ void SerializeHttpRequest(base::IOBuf* /*not used*/,
...
@@ -390,7 +390,8 @@ void SerializeHttpRequest(base::IOBuf* /*not used*/,
// Serialize content as json
// Serialize content as json
std
::
string
err
;
std
::
string
err
;
json2pb
::
Pb2JsonOptions
opt
;
json2pb
::
Pb2JsonOptions
opt
;
opt
.
enum_option
=
(
FLAGS_pb_enum_as_number
?
json2pb
::
OUTPUT_ENUM_BY_NUMBER
opt
.
enum_option
=
(
FLAGS_pb_enum_as_number
?
json2pb
::
OUTPUT_ENUM_BY_NUMBER
:
json2pb
::
OUTPUT_ENUM_BY_NAME
);
:
json2pb
::
OUTPUT_ENUM_BY_NAME
);
if
(
!
json2pb
::
ProtoMessageToJson
(
*
request
,
&
wrapper
,
opt
,
&
err
))
{
if
(
!
json2pb
::
ProtoMessageToJson
(
*
request
,
&
wrapper
,
opt
,
&
err
))
{
cntl
->
request_attachment
().
clear
();
cntl
->
request_attachment
().
clear
();
...
@@ -574,49 +575,43 @@ static void SendHttpResponse(Controller *cntl,
...
@@ -574,49 +575,43 @@ static void SendHttpResponse(Controller *cntl,
// Notice: Not check res->IsInitialized() which should be checked in the
// Notice: Not check res->IsInitialized() which should be checked in the
// conversion function.
// conversion function.
if
(
res
!=
NULL
&&
if
(
res
!=
NULL
&&
cntl
->
response_attachment
().
empty
()
&&
// ^ user did not fill the body yet.
res
->
GetDescriptor
()
->
field_count
()
>
0
&&
res
->
GetDescriptor
()
->
field_count
()
>
0
&&
// ^ a pb service
must have fields in response.
// ^ a pb service
!
cntl
->
Failed
())
{
!
cntl
->
Failed
())
{
// ^ pb response in failed RPC is undefined, no need to convert.
// ^ pb response in failed RPC is undefined, no need to convert.
if
(
!
cntl
->
response_attachment
().
empty
())
{
base
::
IOBufAsZeroCopyOutputStream
wrapper
(
&
cntl
->
response_attachment
());
if
(
res
->
ByteSize
()
!=
0
)
{
// fields in `res' were set.
const
std
::
string
*
content_type_str
=
&
res_header
->
content_type
();
LOG
(
ERROR
)
<<
"Service on "
<<
req_header
->
uri
().
path
()
if
(
content_type_str
->
empty
())
{
<<
" sets both response_attachment and response(pb)"
content_type_str
=
&
req_header
->
content_type
();
", you can set only one of them."
;
}
}
// else no fields in `res' were set, user is intended to fill
const
HttpContentType
content_type
=
ParseContentType
(
*
content_type_str
);
// the http body by him/herself.
if
(
content_type
==
HTTP_CONTENT_PROTO
)
{
}
else
{
if
(
res
->
SerializeToZeroCopyStream
(
&
wrapper
))
{
base
::
IOBufAsZeroCopyOutputStream
wrapper
(
&
cntl
->
response_attachment
());
// Set content-type if user did not
const
std
::
string
*
content_type_str
=
&
res_header
->
content_type
();
if
(
res_header
->
content_type
().
empty
())
{
if
(
content_type_str
->
empty
())
{
res_header
->
set_content_type
(
common
->
CONTENT_TYPE_PROTO
);
content_type_str
=
&
req_header
->
content_type
();
}
const
HttpContentType
content_type
=
ParseContentType
(
*
content_type_str
);
if
(
content_type
==
HTTP_CONTENT_PROTO
)
{
if
(
res
->
SerializeToZeroCopyStream
(
&
wrapper
))
{
// Set content-type if user did not
if
(
res_header
->
content_type
().
empty
())
{
res_header
->
set_content_type
(
common
->
CONTENT_TYPE_PROTO
);
}
}
else
{
cntl
->
SetFailed
(
ERESPONSE
,
"Fail to serialize %s"
,
res
->
GetTypeName
().
c_str
());
}
}
}
else
{
}
else
{
std
::
string
err
;
cntl
->
SetFailed
(
ERESPONSE
,
"Fail to serialize %s"
,
json2pb
::
Pb2JsonOptions
opt
;
res
->
GetTypeName
().
c_str
());
opt
.
enum_option
=
(
FLAGS_pb_enum_as_number
?
json2pb
::
OUTPUT_ENUM_BY_NUMBER
}
:
json2pb
::
OUTPUT_ENUM_BY_NAME
);
}
else
{
if
(
json2pb
::
ProtoMessageToJson
(
*
res
,
&
wrapper
,
opt
,
&
err
))
{
std
::
string
err
;
// Set content-type if user did not
json2pb
::
Pb2JsonOptions
opt
;
if
(
res_header
->
content_type
().
empty
())
{
opt
.
enum_option
=
(
FLAGS_pb_enum_as_number
res_header
->
set_content_type
(
common
->
CONTENT_TYPE_JSON
);
?
json2pb
::
OUTPUT_ENUM_BY_NUMBER
}
:
json2pb
::
OUTPUT_ENUM_BY_NAME
);
}
else
{
if
(
json2pb
::
ProtoMessageToJson
(
*
res
,
&
wrapper
,
opt
,
&
err
))
{
cntl
->
SetFailed
(
ERESPONSE
,
"Fail to convert response to json, %s"
,
// Set content-type if user did not
err
.
c_str
());
if
(
res_header
->
content_type
().
empty
())
{
res_header
->
set_content_type
(
common
->
CONTENT_TYPE_JSON
);
}
}
}
else
{
cntl
->
SetFailed
(
ERESPONSE
,
"Fail to convert response to json, %s"
,
err
.
c_str
());
}
}
}
}
}
}
...
@@ -1220,7 +1215,8 @@ void ProcessHttpRequest(InputMessageBase *msg) {
...
@@ -1220,7 +1215,8 @@ void ProcessHttpRequest(InputMessageBase *msg) {
cntl
->
SetFailed
(
"Fail to new req or res"
);
cntl
->
SetFailed
(
"Fail to new req or res"
);
return
SendHttpResponse
(
cntl
.
release
(),
server
,
method_status
);
return
SendHttpResponse
(
cntl
.
release
(),
server
,
method_status
);
}
}
if
(
method
->
input_type
()
->
field_count
()
>
0
)
{
if
(
sp
->
allow_http_body_to_pb
&&
method
->
input_type
()
->
field_count
()
>
0
)
{
// A protobuf service. No matter if Content-type is set to
// A protobuf service. No matter if Content-type is set to
// applcation/json or body is empty, we have to treat body as a json
// applcation/json or body is empty, we have to treat body as a json
// and try to convert it to pb, which guarantees that a protobuf
// and try to convert it to pb, which guarantees that a protobuf
...
...
brpc/restful.cpp
View file @
48a0e323
...
@@ -247,6 +247,7 @@ RestfulMap::~RestfulMap() {
...
@@ -247,6 +247,7 @@ RestfulMap::~RestfulMap() {
bool
RestfulMap
::
AddMethod
(
const
RestfulMethodPath
&
path
,
bool
RestfulMap
::
AddMethod
(
const
RestfulMethodPath
&
path
,
google
::
protobuf
::
Service
*
service
,
google
::
protobuf
::
Service
*
service
,
bool
is_tabbed
,
bool
is_tabbed
,
bool
allow_http_body_to_pb
,
const
std
::
string
&
method_name
,
const
std
::
string
&
method_name
,
MethodStatus
*
status
)
{
MethodStatus
*
status
)
{
if
(
service
==
NULL
)
{
if
(
service
==
NULL
)
{
...
@@ -278,6 +279,7 @@ bool RestfulMap::AddMethod(const RestfulMethodPath& path,
...
@@ -278,6 +279,7 @@ bool RestfulMap::AddMethod(const RestfulMethodPath& path,
info
.
is_builtin_service
=
false
;
info
.
is_builtin_service
=
false
;
info
.
own_method_status
=
false
;
info
.
own_method_status
=
false
;
info
.
is_tabbed
=
is_tabbed
;
info
.
is_tabbed
=
is_tabbed
;
info
.
allow_http_body_to_pb
=
allow_http_body_to_pb
;
info
.
service
=
service
;
info
.
service
=
service
;
info
.
method
=
md
;
info
.
method
=
md
;
info
.
status
=
status
;
info
.
status
=
status
;
...
...
brpc/restful.h
View file @
48a0e323
...
@@ -61,6 +61,7 @@ public:
...
@@ -61,6 +61,7 @@ public:
bool
AddMethod
(
const
RestfulMethodPath
&
path
,
bool
AddMethod
(
const
RestfulMethodPath
&
path
,
google
::
protobuf
::
Service
*
service
,
google
::
protobuf
::
Service
*
service
,
bool
is_tabbed
,
bool
is_tabbed
,
bool
allow_http_body_to_pb
,
const
std
::
string
&
method_name
,
const
std
::
string
&
method_name
,
MethodStatus
*
status
);
MethodStatus
*
status
);
...
...
brpc/server.cpp
View file @
48a0e323
...
@@ -140,6 +140,7 @@ Server::MethodProperty::MethodProperty()
...
@@ -140,6 +140,7 @@ Server::MethodProperty::MethodProperty()
:
is_builtin_service
(
false
)
:
is_builtin_service
(
false
)
,
own_method_status
(
false
)
,
own_method_status
(
false
)
,
is_tabbed
(
false
)
,
is_tabbed
(
false
)
,
allow_http_body_to_pb
(
true
)
,
http_url
(
NULL
)
,
http_url
(
NULL
)
,
service
(
NULL
)
,
service
(
NULL
)
,
method
(
NULL
)
,
method
(
NULL
)
...
@@ -1061,9 +1062,8 @@ int Server::Join() {
...
@@ -1061,9 +1062,8 @@ int Server::Join() {
}
}
int
Server
::
AddServiceInternal
(
google
::
protobuf
::
Service
*
service
,
int
Server
::
AddServiceInternal
(
google
::
protobuf
::
Service
*
service
,
ServiceOwnership
ownership
,
bool
is_builtin_service
,
bool
is_builtin_service
,
base
::
StringPiece
restful_mappings
)
{
const
ServiceOptions
&
svc_opt
)
{
if
(
NULL
==
service
)
{
if
(
NULL
==
service
)
{
LOG
(
ERROR
)
<<
"Parameter[service] is NULL!"
;
LOG
(
ERROR
)
<<
"Parameter[service] is NULL!"
;
return
-
1
;
return
-
1
;
...
@@ -1108,6 +1108,7 @@ int Server::AddServiceInternal(google::protobuf::Service* service,
...
@@ -1108,6 +1108,7 @@ int Server::AddServiceInternal(google::protobuf::Service* service,
mp
.
is_builtin_service
=
is_builtin_service
;
mp
.
is_builtin_service
=
is_builtin_service
;
mp
.
own_method_status
=
true
;
mp
.
own_method_status
=
true
;
mp
.
is_tabbed
=
!!
tabbed
;
mp
.
is_tabbed
=
!!
tabbed
;
mp
.
allow_http_body_to_pb
=
svc_opt
.
allow_http_body_to_pb
;
mp
.
service
=
service
;
mp
.
service
=
service
;
mp
.
method
=
md
;
mp
.
method
=
md
;
mp
.
status
=
new
MethodStatus
;
mp
.
status
=
new
MethodStatus
;
...
@@ -1132,7 +1133,8 @@ int Server::AddServiceInternal(google::protobuf::Service* service,
...
@@ -1132,7 +1133,8 @@ int Server::AddServiceInternal(google::protobuf::Service* service,
}
}
}
}
const
ServiceProperty
ss
=
{
is_builtin_service
,
ownership
,
service
,
NULL
};
const
ServiceProperty
ss
=
{
is_builtin_service
,
svc_opt
.
ownership
,
service
,
NULL
};
_fullname_service_map
[
sd
->
full_name
()]
=
ss
;
_fullname_service_map
[
sd
->
full_name
()]
=
ss
;
_service_map
[
sd
->
name
()]
=
ss
;
_service_map
[
sd
->
name
()]
=
ss
;
if
(
is_builtin_service
)
{
if
(
is_builtin_service
)
{
...
@@ -1142,7 +1144,8 @@ int Server::AddServiceInternal(google::protobuf::Service* service,
...
@@ -1142,7 +1144,8 @@ int Server::AddServiceInternal(google::protobuf::Service* service,
_first_service
=
service
;
_first_service
=
service
;
}
}
}
}
base
::
StringPiece
restful_mappings
=
svc_opt
.
restful_mappings
;
restful_mappings
.
trim_spaces
();
restful_mappings
.
trim_spaces
();
if
(
!
restful_mappings
.
empty
())
{
if
(
!
restful_mappings
.
empty
())
{
// Parse the mappings.
// Parse the mappings.
...
@@ -1190,6 +1193,7 @@ int Server::AddServiceInternal(google::protobuf::Service* service,
...
@@ -1190,6 +1193,7 @@ int Server::AddServiceInternal(google::protobuf::Service* service,
}
}
if
(
!
_global_restful_map
->
AddMethod
(
if
(
!
_global_restful_map
->
AddMethod
(
mappings
[
i
].
path
,
service
,
!!
tabbed
,
mappings
[
i
].
path
,
service
,
!!
tabbed
,
svc_opt
.
allow_http_body_to_pb
,
mappings
[
i
].
method_name
,
mp
->
status
))
{
mappings
[
i
].
method_name
,
mp
->
status
))
{
LOG
(
ERROR
)
<<
"Fail to map `"
<<
mappings
[
i
].
path
LOG
(
ERROR
)
<<
"Fail to map `"
<<
mappings
[
i
].
path
<<
"' to `"
<<
full_method_name
<<
'\''
;
<<
"' to `"
<<
full_method_name
<<
'\''
;
...
@@ -1222,6 +1226,7 @@ int Server::AddServiceInternal(google::protobuf::Service* service,
...
@@ -1222,6 +1226,7 @@ int Server::AddServiceInternal(google::protobuf::Service* service,
m
=
sp
->
restful_map
;
m
=
sp
->
restful_map
;
}
}
if
(
!
m
->
AddMethod
(
mappings
[
i
].
path
,
service
,
!!
tabbed
,
if
(
!
m
->
AddMethod
(
mappings
[
i
].
path
,
service
,
!!
tabbed
,
svc_opt
.
allow_http_body_to_pb
,
mappings
[
i
].
method_name
,
mp
->
status
))
{
mappings
[
i
].
method_name
,
mp
->
status
))
{
LOG
(
ERROR
)
<<
"Fail to map `"
<<
mappings
[
i
].
path
<<
"' to `"
LOG
(
ERROR
)
<<
"Fail to map `"
<<
mappings
[
i
].
path
<<
"' to `"
<<
sd
->
full_name
()
<<
'.'
<<
mappings
[
i
].
method_name
<<
sd
->
full_name
()
<<
'.'
<<
mappings
[
i
].
method_name
...
@@ -1271,16 +1276,37 @@ int Server::AddServiceInternal(google::protobuf::Service* service,
...
@@ -1271,16 +1276,37 @@ int Server::AddServiceInternal(google::protobuf::Service* service,
return
0
;
return
0
;
}
}
ServiceOptions
::
ServiceOptions
()
:
ownership
(
SERVER_DOESNT_OWN_SERVICE
)
,
allow_http_body_to_pb
(
true
)
{
}
int
Server
::
AddService
(
google
::
protobuf
::
Service
*
service
,
int
Server
::
AddService
(
google
::
protobuf
::
Service
*
service
,
ServiceOwnership
ownership
)
{
ServiceOwnership
ownership
)
{
return
AddServiceInternal
(
service
,
ownership
,
false
/*non-builtin*/
,
""
);
ServiceOptions
options
;
options
.
ownership
=
ownership
;
return
AddServiceInternal
(
service
,
false
,
options
);
}
}
int
Server
::
AddService
(
google
::
protobuf
::
Service
*
service
,
int
Server
::
AddService
(
google
::
protobuf
::
Service
*
service
,
ServiceOwnership
ownership
,
ServiceOwnership
ownership
,
const
base
::
StringPiece
&
restful_mappings
)
{
const
base
::
StringPiece
&
restful_mappings
)
{
return
AddServiceInternal
(
service
,
ownership
,
false
/*non-builtin*/
,
ServiceOptions
options
;
restful_mappings
);
options
.
ownership
=
ownership
;
// TODO: This is weird
options
.
restful_mappings
=
restful_mappings
.
as_string
();
return
AddServiceInternal
(
service
,
false
,
options
);
}
int
Server
::
AddService
(
google
::
protobuf
::
Service
*
service
,
const
ServiceOptions
&
options
)
{
return
AddServiceInternal
(
service
,
false
,
options
);
}
int
Server
::
AddBuiltinService
(
google
::
protobuf
::
Service
*
service
)
{
ServiceOptions
options
;
options
.
ownership
=
SERVER_OWNS_SERVICE
;
return
AddServiceInternal
(
service
,
true
,
options
);
}
}
void
Server
::
RemoveMethodsOf
(
google
::
protobuf
::
Service
*
service
)
{
void
Server
::
RemoveMethodsOf
(
google
::
protobuf
::
Service
*
service
)
{
...
...
brpc/server.h
View file @
48a0e323
...
@@ -295,6 +295,34 @@ enum ServiceOwnership {
...
@@ -295,6 +295,34 @@ enum ServiceOwnership {
SERVER_DOESNT_OWN_SERVICE
SERVER_DOESNT_OWN_SERVICE
};
};
struct
ServiceOptions
{
ServiceOptions
();
// constructed with default options.
// SERVER_OWNS_SERVICE: the service will be deleted by the server.
// SERVER_DOESNT_OWN_SERVICE: the service shall be deleted by user after
// stopping the server.
// Default: SERVER_DOESNT_OWN_SERVICE
ServiceOwnership
ownership
;
// If this option is non-empty, methods in the service will be exposed
// on specified paths instead of default "/SERVICE/METHOD".
// Mappings are in form of: "PATH1 => NAME1, PATH2 => NAME2 ..." where
// PATHs are valid http paths, NAMEs are method names in the service.
// Default: empty
std
::
string
restful_mappings
;
// [ Not recommended to change this option ]
// If this flag is true, the service will convert http body to protobuf
// when the pb schema is non-empty in http servings. The body must be
// valid json or protobuf(wire-format) otherwise the request is rejected.
// This option does not affect pure-http services (pb schema is empty).
// Services that use older versions of baidu-rpc may need to turn this
// conversion off and handle http requests by their own to keep compatible
// with existing clients.
// Default: true
bool
allow_http_body_to_pb
;
};
// Represent ports inside [min_port, max_port]
// Represent ports inside [min_port, max_port]
struct
PortRange
{
struct
PortRange
{
int
min_port
;
int
min_port
;
...
@@ -336,6 +364,7 @@ public:
...
@@ -336,6 +364,7 @@ public:
bool
is_builtin_service
;
bool
is_builtin_service
;
bool
own_method_status
;
bool
own_method_status
;
bool
is_tabbed
;
bool
is_tabbed
;
bool
allow_http_body_to_pb
;
// NULL if service of the method was never added as restful.
// NULL if service of the method was never added as restful.
// "@path1 @path2 ..." if the method was mapped from paths.
// "@path1 @path2 ..." if the method was mapped from paths.
std
::
string
*
http_url
;
std
::
string
*
http_url
;
...
@@ -402,14 +431,7 @@ public:
...
@@ -402,14 +431,7 @@ public:
// function may block indefinitely.
// function may block indefinitely.
void
RunUntilAskedToQuit
();
void
RunUntilAskedToQuit
();
// Add a service.
// Add a service. Arguments are explained in ServiceOptions above.
// If `ownership' is SERVER_OWNS_SERVICE, the service will be deleted along
// with this server, otherwise user shall delete the service after stopping
// this server.
// If `restful_mappings' is not empty, the methods in the service will be
// exposed on the specified paths instead of fixed "/SERVICE/METHOD". The
// mapping should be in form of: "PATH1 => NAME1, PATH2 => NAME2 ..." where
// PATHs are valid http URI paths, NAMEs are method names in the service.
// NOTE: Adding a service while server is running is forbidden.
// NOTE: Adding a service while server is running is forbidden.
// Returns 0 on success, -1 otherwise.
// Returns 0 on success, -1 otherwise.
int
AddService
(
google
::
protobuf
::
Service
*
service
,
int
AddService
(
google
::
protobuf
::
Service
*
service
,
...
@@ -417,6 +439,8 @@ public:
...
@@ -417,6 +439,8 @@ public:
int
AddService
(
google
::
protobuf
::
Service
*
service
,
int
AddService
(
google
::
protobuf
::
Service
*
service
,
ServiceOwnership
ownership
,
ServiceOwnership
ownership
,
const
base
::
StringPiece
&
restful_mappings
);
const
base
::
StringPiece
&
restful_mappings
);
int
AddService
(
google
::
protobuf
::
Service
*
service
,
const
ServiceOptions
&
options
);
// Remove a service from this server.
// Remove a service from this server.
// NOTE: removing a service while server is running is forbidden.
// NOTE: removing a service while server is running is forbidden.
...
@@ -533,13 +557,10 @@ friend class ServerPrivateAccessor;
...
@@ -533,13 +557,10 @@ friend class ServerPrivateAccessor;
friend
class
Controller
;
friend
class
Controller
;
int
AddServiceInternal
(
google
::
protobuf
::
Service
*
service
,
int
AddServiceInternal
(
google
::
protobuf
::
Service
*
service
,
ServiceOwnership
ownership
,
bool
is_builtin_service
,
bool
is_builtin_service
,
base
::
StringPiece
restful_mapping
s
);
const
ServiceOptions
&
option
s
);
int
AddBuiltinService
(
google
::
protobuf
::
Service
*
service
)
{
int
AddBuiltinService
(
google
::
protobuf
::
Service
*
service
);
return
AddServiceInternal
(
service
,
SERVER_OWNS_SERVICE
,
true
,
""
);
}
// Remove all methods of `service' from internal structures.
// Remove all methods of `service' from internal structures.
void
RemoveMethodsOf
(
google
::
protobuf
::
Service
*
service
);
void
RemoveMethodsOf
(
google
::
protobuf
::
Service
*
service
);
...
...
test/brpc_server_unittest.cpp
View file @
48a0e323
...
@@ -130,7 +130,7 @@ protected:
...
@@ -130,7 +130,7 @@ protected:
brpc
::
Server
server
;
brpc
::
Server
server
;
EvilService
evil
(
conflict_sd
);
EvilService
evil
(
conflict_sd
);
EXPECT_EQ
(
0
,
server
.
AddServiceInternal
(
EXPECT_EQ
(
0
,
server
.
AddServiceInternal
(
&
evil
,
brpc
::
SERVER_DOESNT_OWN_SERVICE
,
false
,
""
));
&
evil
,
false
,
brpc
::
ServiceOptions
()
));
EXPECT_EQ
(
-
1
,
server
.
AddBuiltinServices
());
EXPECT_EQ
(
-
1
,
server
.
AddBuiltinServices
());
}
}
};
};
...
@@ -206,12 +206,18 @@ public:
...
@@ -206,12 +206,18 @@ public:
,
ncalled_echo5
(
0
)
,
ncalled_echo5
(
0
)
{}
{}
virtual
~
EchoServiceV1
()
{}
virtual
~
EchoServiceV1
()
{}
virtual
void
Echo
(
google
::
protobuf
::
RpcController
*
,
virtual
void
Echo
(
google
::
protobuf
::
RpcController
*
cntl_base
,
const
v1
::
EchoRequest
*
request
,
const
v1
::
EchoRequest
*
request
,
v1
::
EchoResponse
*
response
,
v1
::
EchoResponse
*
response
,
google
::
protobuf
::
Closure
*
done
)
{
google
::
protobuf
::
Closure
*
done
)
{
brpc
::
Controller
*
cntl
=
static_cast
<
brpc
::
Controller
*>
(
cntl_base
);
brpc
::
ClosureGuard
done_guard
(
done
);
brpc
::
ClosureGuard
done_guard
(
done
);
response
->
set_message
(
request
->
message
()
+
"_v1"
);
if
(
request
->
has_message
())
{
response
->
set_message
(
request
->
message
()
+
"_v1"
);
}
else
{
CHECK_EQ
(
brpc
::
PROTOCOL_HTTP
,
cntl
->
request_protocol
());
cntl
->
response_attachment
()
=
cntl
->
request_attachment
();
}
ncalled
.
fetch_add
(
1
);
ncalled
.
fetch_add
(
1
);
}
}
virtual
void
Echo2
(
google
::
protobuf
::
RpcController
*
,
virtual
void
Echo2
(
google
::
protobuf
::
RpcController
*
,
...
@@ -441,6 +447,76 @@ TEST_F(ServerTest, various_forms_of_uri_paths) {
...
@@ -441,6 +447,76 @@ TEST_F(ServerTest, various_forms_of_uri_paths) {
server1
.
Join
();
server1
.
Join
();
}
}
TEST_F
(
ServerTest
,
missing_required_fields
)
{
const
int
port
=
9200
;
brpc
::
Server
server1
;
EchoServiceV1
service_v1
;
ASSERT_EQ
(
0
,
server1
.
AddService
(
&
service_v1
,
brpc
::
SERVER_DOESNT_OWN_SERVICE
));
ASSERT_EQ
(
0
,
server1
.
Start
(
port
,
NULL
));
brpc
::
Channel
http_channel
;
brpc
::
ChannelOptions
chan_options
;
chan_options
.
protocol
=
"http"
;
ASSERT_EQ
(
0
,
http_channel
.
Init
(
"0.0.0.0"
,
port
,
&
chan_options
));
brpc
::
Controller
cntl
;
cntl
.
http_request
().
uri
()
=
"/EchoService/Echo"
;
http_channel
.
CallMethod
(
NULL
,
&
cntl
,
NULL
,
NULL
,
NULL
);
ASSERT_TRUE
(
cntl
.
Failed
());
ASSERT_EQ
(
brpc
::
EHTTP
,
cntl
.
ErrorCode
());
ASSERT_EQ
(
brpc
::
HTTP_STATUS_BAD_REQUEST
,
cntl
.
http_response
().
status_code
());
ASSERT_EQ
(
0
,
service_v1
.
ncalled
.
load
());
cntl
.
Reset
();
cntl
.
http_request
().
uri
()
=
"/EchoService/Echo"
;
cntl
.
http_request
().
set_method
(
brpc
::
HTTP_METHOD_POST
);
http_channel
.
CallMethod
(
NULL
,
&
cntl
,
NULL
,
NULL
,
NULL
);
ASSERT_TRUE
(
cntl
.
Failed
());
ASSERT_EQ
(
brpc
::
EHTTP
,
cntl
.
ErrorCode
());
ASSERT_EQ
(
brpc
::
HTTP_STATUS_BAD_REQUEST
,
cntl
.
http_response
().
status_code
());
ASSERT_EQ
(
0
,
service_v1
.
ncalled
.
load
());
cntl
.
Reset
();
cntl
.
http_request
().
uri
()
=
"/EchoService/Echo"
;
cntl
.
http_request
().
set_method
(
brpc
::
HTTP_METHOD_POST
);
cntl
.
request_attachment
().
append
(
"{
\"
message2
\"
:
\"
foo
\"
}"
);
http_channel
.
CallMethod
(
NULL
,
&
cntl
,
NULL
,
NULL
,
NULL
);
ASSERT_TRUE
(
cntl
.
Failed
());
ASSERT_EQ
(
brpc
::
EHTTP
,
cntl
.
ErrorCode
());
ASSERT_EQ
(
brpc
::
HTTP_STATUS_BAD_REQUEST
,
cntl
.
http_response
().
status_code
());
ASSERT_EQ
(
0
,
service_v1
.
ncalled
.
load
());
}
TEST_F
(
ServerTest
,
disallow_http_body_to_pb
)
{
const
int
port
=
9200
;
brpc
::
Server
server1
;
EchoServiceV1
service_v1
;
brpc
::
ServiceOptions
svc_opt
;
svc_opt
.
allow_http_body_to_pb
=
false
;
svc_opt
.
restful_mappings
=
"/access_echo1=>Echo"
;
ASSERT_EQ
(
0
,
server1
.
AddService
(
&
service_v1
,
svc_opt
));
ASSERT_EQ
(
0
,
server1
.
Start
(
port
,
NULL
));
brpc
::
Channel
http_channel
;
brpc
::
ChannelOptions
chan_options
;
chan_options
.
protocol
=
"http"
;
ASSERT_EQ
(
0
,
http_channel
.
Init
(
"0.0.0.0"
,
port
,
&
chan_options
));
brpc
::
Controller
cntl
;
cntl
.
http_request
().
uri
()
=
"/access_echo1"
;
http_channel
.
CallMethod
(
NULL
,
&
cntl
,
NULL
,
NULL
,
NULL
);
ASSERT_TRUE
(
cntl
.
Failed
());
ASSERT_EQ
(
brpc
::
EHTTP
,
cntl
.
ErrorCode
());
ASSERT_EQ
(
brpc
::
HTTP_STATUS_INTERNAL_SERVER_ERROR
,
cntl
.
http_response
().
status_code
());
ASSERT_EQ
(
1
,
service_v1
.
ncalled
.
load
());
cntl
.
Reset
();
cntl
.
http_request
().
uri
()
=
"/access_echo1"
;
cntl
.
http_request
().
set_method
(
brpc
::
HTTP_METHOD_POST
);
cntl
.
request_attachment
().
append
(
"heheda"
);
http_channel
.
CallMethod
(
NULL
,
&
cntl
,
NULL
,
NULL
,
NULL
);
ASSERT_FALSE
(
cntl
.
Failed
())
<<
cntl
.
ErrorText
();
ASSERT_EQ
(
"heheda"
,
cntl
.
response_attachment
());
ASSERT_EQ
(
2
,
service_v1
.
ncalled
.
load
());
}
TEST_F
(
ServerTest
,
restful_mapping
)
{
TEST_F
(
ServerTest
,
restful_mapping
)
{
const
int
port
=
9200
;
const
int
port
=
9200
;
EchoServiceV1
service_v1
;
EchoServiceV1
service_v1
;
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment