After starting the local test server via source test/suite/setup.sh && startServer
, you can send
the following list of requests via protoCURL. The test/proto/happyday.proto is used for these examples.
Each request needs to mount the directory of proto files into the containers /proto
path to ensure, that they are
visible inside the docker container.
All of these commands work with the native CLI as well as docker. For the native CLI, one can simply use protocurl -I $PWD/test/proto
instead of docker run -v $PWD/test/proto:/proto --network host protocurl
Basic Example
$ docker run -v "$PWD/test/proto:/proto" --network host qaware/protocurl \
-i ..HappyDayRequest -o ..HappyDayResponse \
-u http://localhost:8080/happy-day/verify \
-d "includeReason: true"
=========================== POST Request Text =========================== >>>
includeReason: true
=========================== POST Response Text =========================== <<<
isHappyDay: true
reason: "Thursday is a Happy Day! ⭐"
formattedDate: "Thu, 01 Jan 1970 00:00:00 GMT"
Explict full message package paths and explicit proto file
$ docker run -v "$PWD/test/proto:/proto" --network host qaware/protocurl \
-f happyday.proto -i happyday.HappyDayRequest -o happyday.HappyDayResponse \
-u http://localhost:8080/happy-day/verify -d ""
=========================== POST Request Text =========================== >>>
=========================== POST Response Text =========================== <<<
isHappyDay: true
formattedDate: "Thu, 01 Jan 1970 00:00:00 GMT"
Using imported and nested messages such as well-known Google Protobuf types
$ docker run -v "$PWD/test/proto:/proto" --network host qaware/protocurl \
-i ..HappyDayRequest -o ..HappyDayResponse \
-u http://localhost:8080/happy-day/verify \
-d "date: { seconds: 1648044939}"
=========================== POST Request Text =========================== >>>
date: {
seconds: 1648044939
}
=========================== POST Response Text =========================== <<<
formattedDate: "Wed, 23 Mar 2022 14:15:39 GMT"
Omitting -o <response-type> shows raw format
$ docker run -v "$PWD/test/proto:/proto" --network host qaware/protocurl \
-q -f happyday.proto -i happyday.HappyDayRequest \
-u http://localhost:8080/happy-day/verify \
-d "includeReason: true"
1: 1
2: "Thursday is a Happy Day! ⭐"
3: "Thu, 01 Jan 1970 00:00:00 GMT"
4: ""
When the response type is unknown or one wants to debug and see what is all in the response, then this format shows the values for the given field numbers (instead of their field names).
However, since Protobuf is not self-describing the types cannot be correctly inferred and may be incorrect.
JSON
If your input text starts with a {
, then it is inferred to be JSON
and the output will automatically be shown in JSON format.
$ docker run -v "$PWD/test/proto:/proto" --network host qaware/protocurl \
-i ..HappyDayRequest -o ..HappyDayResponse \
-u http://localhost:8080/happy-day/verify \
-d "{ \"date\": \"2022-03-23T14:15:39Z\" }"
=========================== POST Request JSON =========================== >>>
{"date":"2022-03-23T14:15:39Z"}
=========================== POST Response JSON =========================== <<<
{"formattedDate":"Wed, 23 Mar 2022 14:15:39 GMT"}
JSON with pretty-printing
$ docker run -v "$PWD/test/proto:/proto" --network host qaware/protocurl \
-i ..HappyDayRequest -o ..HappyDayResponse \
-u http://localhost:8080/happy-day/verify --out=json:pretty \
-d "{ \"date\": \"2022-03-23T14:15:39Z\" }"
=========================== POST Request JSON =========================== >>>
{"date":"2022-03-23T14:15:39Z"}
=========================== POST Response JSON =========================== <<<
{
"formattedDate": "Wed, 23 Mar 2022 14:15:39 GMT"
}
Show response output only via -q
$ docker run -v "$PWD/test/proto:/proto" --network host qaware/protocurl \
-q -f happyday.proto -i happyday.HappyDayRequest -o happyday.HappyDayResponse \
-u http://localhost:8080/happy-day/verify \
-d "includeReason: true"
isHappyDay: true
reason: "Thursday is a Happy Day! ⭐"
formattedDate: "Thu, 01 Jan 1970 00:00:00 GMT"
With -q
all errors are written to stderr making it ideal for piping in scripts. Hence this request against a non-existing endpoint
$ docker run -v "$PWD/test/proto:/proto" --network host qaware/protocurl \
-q -i ..HappyDayRequest -o ..HappyDayResponse \
-u http://localhost:8080/does-not-exist \
-d ""
will produce no output, exit with a non-zero exitcode and only show this error:
Error: Request was unsuccessful. Received response status code outside of 2XX. Got: HTTP/1.1 404 Not Found
No Default Header
Some headers use default values (e.g. Content-Type: application/x-protobuf
). If you do not want to use these default values, use --no-default-headers
flag (only work when using --curl
).
$ docker run -v "$PWD/test/proto:/proto" --network host qaware/protocurl \
-i ..HappyDayRequest -o ..HappyDayResponse \
-u http://localhost:8080/happy-day/verify \
-d "date: { seconds: 1648044939}" \
--curl -n -H 'Content-Type: application/octet-stream'
=========================== POST Request Text =========================== >>>
date: {
seconds: 1648044939
}
=========================== POST Response Text =========================== <<<
formattedDate: "Wed, 23 Mar 2022 14:15:39 GMT"
Verbose via -v
$ docker run -v "$PWD/test/proto:/proto" --network host qaware/protocurl \
-v -i ..HappyDayRequest -o ..HappyDayResponse \
-u http://localhost:8080/happy-day/verify \
-d "date: { seconds: 1648044939}"
Inferred input text type as text.
Infering proto files (-F), since -f <file> was not provided.
protocurl <version>, build <hash>, https://github.com/qaware/protocurl
Adding default header argument to request headers : [Content-Type: application/x-protobuf]
Invoked with following default & parsed arguments:
{
"ProtoFilesDir": "/proto",
"ProtoInputFilePath": "",
"RequestType": "..HappyDayRequest",
"ResponseType": "..HappyDayResponse",
"Url": "http://localhost:8080/happy-day/verify",
"Method": "POST",
"DataText": "date: { seconds: 1648044939}",
"InTextType": "text",
"OutTextType": "text",
"DecodeRawResponse": false,
"DisplayBinaryAndHttp": true,
"NoDefaultHeaders": false,
"RequestHeaders": [
"Content-Type: application/x-protobuf"
],
"CustomCurlPath": "",
"AdditionalCurlArgs": "",
"Verbose": true,
"ShowOutputOnly": false,
"SilentMode": false,
"ForceNoCurl": false,
"ForceCurl": false,
"GlobalProtoc": false,
"CustomProtocPath": "",
"InferProtoFiles": true
}
Found bundled protoc at /protocurl/protocurl-internal/bin/protoc
Using google protobuf include: /protocurl/protocurl-internal/include
Converting all files in /proto to a FileDescriptorSet.
Found .proto: happyday.proto
=========================== .proto descriptor ===========================
file: {
name: "google/protobuf/timestamp.proto"
package: "google.protobuf"
message_type: {
name: "Timestamp"
field: {
name: "seconds"
number: 1
label: LABEL_OPTIONAL
type: TYPE_INT64
json_name: "seconds"
}
field: {
name: "nanos"
number: 2
label: LABEL_OPTIONAL
type: TYPE_INT32
json_name: "nanos"
}
}
options: {
java_package: "com.google.protobuf"
java_outer_classname: "TimestampProto"
java_multiple_files: true
go_package: "google.golang.org/protobuf/types/known/timestamppb"
cc_enable_arenas: true
objc_class_prefix: "GPB"
csharp_namespace: "Google.Protobuf.WellKnownTypes"
}
syntax: "proto3"
}
file: {
name: "happyday.proto"
package: "happyday"
dependency: "google/protobuf/timestamp.proto"
message_type: {
name: "HappyDayRequest"
field: {
name: "date"
number: 1
label: LABEL_OPTIONAL
type: TYPE_MESSAGE
type_name: ".google.protobuf.Timestamp"
json_name: "date"
}
field: {
name: "includeReason"
number: 2
label: LABEL_OPTIONAL
type: TYPE_BOOL
json_name: "includeReason"
}
field: {
name: "double"
number: 3
label: LABEL_OPTIONAL
type: TYPE_DOUBLE
json_name: "double"
}
field: {
name: "int32"
number: 4
label: LABEL_OPTIONAL
type: TYPE_INT32
json_name: "int32"
}
field: {
name: "int64"
number: 5
label: LABEL_OPTIONAL
type: TYPE_INT64
json_name: "int64"
}
field: {
name: "string"
number: 6
label: LABEL_OPTIONAL
type: TYPE_STRING
json_name: "string"
}
field: {
name: "bytes"
number: 7
label: LABEL_OPTIONAL
type: TYPE_BYTES
json_name: "bytes"
}
field: {
name: "fooEnum"
number: 8
label: LABEL_OPTIONAL
type: TYPE_ENUM
type_name: ".happyday.Foo"
json_name: "fooEnum"
}
field: {
name: "misc"
number: 9
label: LABEL_REPEATED
type: TYPE_MESSAGE
type_name: ".happyday.MiscInfo"
json_name: "misc"
}
field: {
name: "float"
number: 10
label: LABEL_OPTIONAL
type: TYPE_FLOAT
json_name: "float"
}
field: {
name: "NonCamel_case_FieldName"
number: 11
label: LABEL_OPTIONAL
type: TYPE_STRING
json_name: "NonCamelCaseFieldName"
}
}
message_type: {
name: "HappyDayResponse"
field: {
name: "isHappyDay"
number: 1
label: LABEL_OPTIONAL
type: TYPE_BOOL
json_name: "isHappyDay"
}
field: {
name: "reason"
number: 2
label: LABEL_OPTIONAL
type: TYPE_STRING
json_name: "reason"
}
field: {
name: "formattedDate"
number: 3
label: LABEL_OPTIONAL
type: TYPE_STRING
json_name: "formattedDate"
}
field: {
name: "err"
number: 4
label: LABEL_OPTIONAL
type: TYPE_STRING
json_name: "err"
}
}
message_type: {
name: "MiscInfo"
field: {
name: "weatherOfPastFewDays"
number: 1
label: LABEL_REPEATED
type: TYPE_STRING
json_name: "weatherOfPastFewDays"
}
field: {
name: "fooString"
number: 2
label: LABEL_OPTIONAL
type: TYPE_STRING
oneof_index: 0
json_name: "fooString"
}
field: {
name: "fooEnum"
number: 3
label: LABEL_OPTIONAL
type: TYPE_ENUM
type_name: ".happyday.Foo"
oneof_index: 0
json_name: "fooEnum"
}
oneof_decl: {
name: "alternative"
}
}
enum_type: {
name: "Foo"
value: {
name: "BAR"
number: 0
}
value: {
name: "BAZ"
number: 1
}
value: {
name: "FAZ"
number: 2
}
}
syntax: "proto3"
}
Searching for message with base name: HappyDayRequest
Resolved message package-paths for name HappyDayRequest: [happyday.HappyDayRequest]
Searching for message with base name: HappyDayRequest
Resolved message package-paths for name HappyDayRequest: [happyday.HappyDayRequest]
=========================== POST Request Text =========================== >>>
date: {
seconds: 1648044939
}
=========================== POST Request Binary =========================== >>>
00000000 0a 06 08 8b d7 ec 91 06 |........|
Found curl: /usr/bin/curl
Invoking curl http request.
Understood additional curl args: []
Total curl args:
-s
-X
POST
--output
<tmp>
--dump-header
<tmp>
--data-binary
@<tmp>
-H
Content-Type: application/x-protobuf
http://localhost:8080/happy-day/verify
=========================== POST Response Headers =========================== <<<
HTTP/1.1 200 OK
Content-Type: application/x-protobuf
Date: Sat, 25 May 2024 22:15:22 GMT
Connection: keep-alive
Keep-Alive: timeout=5
Content-Length: 35
=========================== POST Response Binary =========================== <<<
00000000 08 00 1a 1d 57 65 64 2c 20 32 33 20 4d 61 72 20 |....Wed, 23 Mar |
00000010 32 30 32 32 20 31 34 3a 31 35 3a 33 39 20 47 4d |2022 14:15:39 GM|
00000020 54 22 00 |T".|
Searching for message with base name: HappyDayResponse
Resolved message package-paths for name HappyDayResponse: [happyday.HappyDayResponse]
=========================== POST Response Text =========================== <<<
formattedDate: "Wed, 23 Mar 2022 14:15:39 GMT"