Ecosyste.ms: Awesome
An open API service indexing awesome lists of open source software.
https://github.com/oseiskar/protowire
Write protobuf messages & GRPC calls from the command line without the proto files
https://github.com/oseiskar/protowire
command-line-tool grpc protobuf protocol-buffers python
Last synced: 4 months ago
JSON representation
Write protobuf messages & GRPC calls from the command line without the proto files
- Host: GitHub
- URL: https://github.com/oseiskar/protowire
- Owner: oseiskar
- License: mit
- Created: 2017-05-25T17:43:47.000Z (over 7 years ago)
- Default Branch: master
- Last Pushed: 2021-08-07T19:12:01.000Z (over 3 years ago)
- Last Synced: 2024-10-13T02:12:16.190Z (4 months ago)
- Topics: command-line-tool, grpc, protobuf, protocol-buffers, python
- Language: Python
- Homepage:
- Size: 37.1 KB
- Stars: 5
- Watchers: 3
- Forks: 0
- Open Issues: 1
-
Metadata Files:
- Readme: README.md
- License: LICENSE
Awesome Lists containing this project
README
# Protowire [![PyPI](https://img.shields.io/pypi/v/protowire.svg)](https://pypi.python.org/pypi/protowire)
Write protobuf messages from the command line:
pw (field number) [data type] (value) > output.bin
where `data type` is one of the [protobuf datatypes](https://developers.google.com/protocol-buffers/docs/proto3#scalar) (or `int` = `int32` = `int64`). If `value` is not given, it is read from STDIN.
The field number can be left out and defaults to 1.This enables creating protobuf messages for GRPC calls or other purposes without a protobuf compiler. The `pw` tool has no library dependencies (plain Python) and does not need the `.proto` files or any code generated from them.
### Installation
sudo pip install protowire
### Examples
To write a protobuf message conforming to, e.g., `message Test1 { int32 a = 1; }` such that `a` has the value 150, write
pw 1 int32 150 > message.bin
Then examine (cf. [official docs](https://developers.google.com/protocol-buffers/docs/encoding#simple)):
$ hd /tmp/msg.bin
00000000 08 96 01 |...|
00000003Another example: `message Test2 { string b = 2; }` with `b = "testing"`:
pw 2 string testing
More complex examples (also from [here](https://developers.google.com/protocol-buffers/docs/encoding#embedded)) can be composed using standard UNIX tools
pw int 150 | pw 3 bytes
and
(pw fixed64 10 && pw 2 bool true) | pw 4 bytes
## GRPC client
This tool also requires the `grpcio` Python package (`pip install grpcio`)
pw-grpc-client (-is) (-os) (--tag 1) host:port/path
Consider the following example:
```protobuf
syntax = "proto3";message RequestThing {
string query = 1;
}message ResponseItem {
int32 foo = 1;
// ...
}service MyService {
rpc UnaryMethod(RequestThing) returns (ResponseItem) {}
rpc ServerStream(RequestThing) returns (stream ResponseItem) {}
rpc ClientStream(stream RequestThing) returns (ResponseItem) {}
rpc BidirectionalStream(stream RequestThing) returns (stream ResponseItem) {}
}// helper collections
message RequestCollection {
repeated RequestThing things = 1;
}message ResponseCollection {
repeated ResponseItem items = 1;
}
```An **`UnaryMethod`** call using a `RequestThing` with `query = "hello"` can be sent to a server running at `localhost:8000` as follows:
pw string "hello" | \
pw-grpc-client localhost:8000/MyService/UnaryMethod \
> response_item.binwhich saves the obtained `ResponseItem` protobuf the file `response_item.bin`.
It is also possible to convert **`ServerStream`** responses to protobuf `ResponseCollection`s using the `-os`/`--stream_response` flag:
pw string "hello" | \
pw-grpc-client localhost:8000/MyService/ServerStream -os \
> response_collection.binSimilarly, **`ClientStream`** can be constructed from `RequestCollection`s with `-is`/`--stream_request`:
pw string "singleton item" | pw 1 bytes | \
pw-grpc-client localhost:8000/MyService/ClientStream -is \
> response_item.binThe flags `-is` and `-os` can be used simultaneously for **`BidirectionalStream`**
((pw string "first" | pw bytes) && (pw string "second" | pw bytes)) | \
pw-grpc-client localhost:8000/MyService/BidirectionalStream -is -os \
> response_collection.binIn all `-os`-cases, there is also a `--tag` flag that can be used to change the field number in the response protobuf collection. For example `message ResponseCollection { repeated ResponseItem items = 2; }` would require:
pw string "hello" | \
pw-grpc-client localhost:8000/MyService/ServerStream -os --tag 2 \
> response_collection.bin## GRPC frames for low-level communication
This tool does not need any GRPC or protbuf packages, but can be combined with a HTTP/2 client like `nghttp` to make GRPC calls.
Usage:pw-grpc-frame [wrap|unwrap] (--stream) (--tag 1)
Wrap into a GRPC frame and unwrap the response to normal protobuf:
pw 1 string "my query" | pw-grpc-frame wrap > request.bin
nghttp -H ":method: POST" -H "Content-Type: application/grpc" -H "TE: trailers" \
--data=request.bin \
http://localhost:8000/MyService/UnaryMethod \
| pw-grpc-frame unwrap > /tmp/output.binThe option `--stream` can be used with both wrap and unwrap to convert protobuf collections to GRPC streams like in the other GRPC client example. The `--tag` option can be used to change the field number in the "unwrapped" protobuf collection.
Notice that older versions of `nghttp` (like 0.6.4 in Debian Jessie) [cannot read STDIN](https://github.com/nghttp2/nghttp2/issues/133) with `-d -`.
## Development
1. Create virtualenv
* Python 2: `virtualenv venvs/python2`
* Python 3: `python3 -m venv venvs/python3`
1. Activate virtualenv: `source venvs/pythonNNN/bin/activate`
1. Install locally `pip install -e .[dev]`
1. `./run-tests.sh`
1. `deactivate` virtualenv