Skip to content
This repository was archived by the owner on Sep 25, 2020. It is now read-only.
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
91 changes: 19 additions & 72 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,90 +11,36 @@
A command line utility to talk to a tchannel server.

```
tcurl [-H <hostlist> | -p host:port] <service> <endpoint> [options]

Version: 4.14.0

Options:
--head (-2) [data] JSON or raw
--body (-3) [data] JSON or raw
(JSON promoted to Thrift via IDL when applicable)
--shardKey send ringpop shardKey transport header
--depth=n configure inspect printing depth
--thrift (-t) [dir] directory containing Thrift files
--no-strict parse Thrift loosely
--json (-j) Use JSON argument scheme
(default unless endpoint has ::)
--http method
--raw encode arg2 & arg3 raw
--health
--timeout [num]
usage: tcurl [OPTIONS] service endpoint

Options:
-h --help Show detailed manpage
-v --version Print version
-H --hostlist Path to hostlist file
-p --peer IP and port of single peer
-t --thrift Path to thrift IDL file
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

or directory containing IDL files. Aside: let’s keep in mind we might someday support passing the path to an idl directory too.

-2 --head <value> Set header to <value>
-3 --body <value> Set body to <value>
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Note that should be JSON for as=json and as=thrift

--http <method> Use HTTP <method> instead of TCP
--health Print health for <service>
--raw Send header and body as binary diaray
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

s/diaray/data/

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Missing. --json is still needed to override as=thrift when arg1 contains ::

--shardKey Send Ringpop shardKey transport header
--no-strict Parse thrift IDL files loosely
--timeout <value> Set a timeout value in milliseconds
```

[Click here for full usage docs.](usage.md)

## Installation

`npm install tcurl`

## Examples

### Thrift

For the purposes of these examples, let's assume that you have a TChannel
server listening on `localhost:1234`. The server registers handlers for the
thrift interface saved as `services/chamber.thrift` and defined as:

```thrift
struct EchoRequest {
1: required string input;
}

service Chamber {
string echo(
1: required EchoRequest request;
)
}
```

You could use TCurl to query this service by running:

```
tcurl -p localhost:1234 chamber Chamber::echo -t ./services -3 '{"request": {"input": "foo"}}'
```

## `localhost` caveat

For TChannel and Hyperbahn to work together effectively, most tchannel services need to listen on the
external IP of the host they are running on.

This means when you use `127.0.0.1` you cannot reach the service with tcurl as it's not listening on
loopback.

To make supporting external IPs easier we've made `localhost` resolve to the external IP of the machine.
This means if your listening on loopback you have to use `127.0.0.1` and not `localhost`

## Exit Codes

- 0: for all successful requests
- 1: timeout
- 2: cancelled
- 3: busy
- 4: declined
- 5: unexpected error
- 6: bad request
- 7: network error
- 8: unhealthy (broken circuit)
- 124: unhealthy / not OK thrift response
- 125: misc tcurl / tchannel internal error
- 126: response not ok error
- 127: fatal protocol error
`npm install tcurl --global`

## NPM scripts

- `npm run add-licence` This will add the licence headers.
- `npm run cover` This runs the tests with code coverage
- `npm run lint` This will run the linter on your code
- `npm run man` This will build the manpage.
- `npm test` This will run the tests.
- `npm run trace` This will run your tests in tracing mode.
- `npm run travis` This is run by travis.CI to run your tests
Expand All @@ -105,6 +51,7 @@ This means if your listening on loopback you have to use `127.0.0.1` and not `lo
- Raynos
- ShanniLi
- kriskowal
- malandrew

## MIT Licenced

Expand Down
30 changes: 24 additions & 6 deletions index.js
Original file line number Diff line number Diff line change
Expand Up @@ -96,7 +96,7 @@ function main(argv, delegate) {
if (conf.help) {
return printFullHelp();
} else if (conf.h || conf._.length === 0) {
return help();
return help(conf.helpUrl);
}

var opts = parseArgs(conf);
Expand Down Expand Up @@ -128,11 +128,29 @@ main.exec = function execMain(str, delegate) {
main(str, delegate);
};

function help() {
console.log('usage: tcurl [--help] [-v | --version] [-H] [-p] [-t]');
console.log(' [-2 | --arg2 | --head] [-3 | --arg3 | --body]');
console.log(' [--shardKey] [--no-strict] [--timeout]');
console.log(' [--http] [--raw] [--health]');
function help(helpUrl) {
console.log('usage: tcurl [OPTIONS] service endpoint');
console.log('');
console.log('Options:');
console.log(' -h --help Show detailed manpage');
console.log(' -v --version Print version');
console.log(' -H --hostlist Path to hostlist file');
console.log(' -p --peer IP and port of single peer');
console.log(' -t --thrift Path to thrift IDL file');
console.log(' -2 --head <value> Set header to <value>');
console.log(' -3 --body <value> Set body to <value>');
console.log(' --http <method> Use HTTP <method> instead of TCP');
console.log(' --health Print health for <service>');
console.log(' --raw Send header and body as binary diaray')
console.log(' --shardKey Send Ringpop shardKey transport header');
console.log(' --no-strict Parse thrift IDL files loosely');
console.log(' --timeout <value> Set a timeout value in milliseconds');
if (typeof helpUrl === 'string' && helpUrl.length > 0) {
console.log('');
console.log('More information on how tcurl is used by your');
console.log('organization can be found at:');
console.log(helpUrl);
}
}

function printFullHelp() {
Expand Down
154 changes: 132 additions & 22 deletions man/tcurl.1
Original file line number Diff line number Diff line change
@@ -1,40 +1,82 @@
.TH "TCURL" "1" "October 2015" "v4.15.0" "tcurl"
.TH "TCURL" "1" "October 2015" "v4.15.1" "tcurl"
.SH "NAME"
\fBtcurl\fR \- curl for tchannel
.SH SYNOPSIS
.P
\fBtcurl\fP [\-\-help] [\-v | \-\-version] [\-H] [\-p] [\-t]
[\-2 | \-\-arg2 | \-\-head] [\-3 | \-\-arg3 | \-\-body]
[\-\-shardKey] [\-\-no\-strict] [\-\-timeout]
[\-\-http] [\-\-raw] [\-\-health]
tcurl [OPTIONS] service endpoint
.P
Options:
\-h \-\-help Show detailed manpage
\-v \-\-version Print version
\-H \-\-hostlist Path to hostlist file
\-p \-\-peer IP and port of single peer
\-t \-\-thrift Path to thrift IDL file
\-2 \-\-head <value> Set header to <value>
\-3 \-\-body <value> Set body to <value>
\-\-http <method> Use HTTP <method> instead of TCP
\-\-health Print health for <service>
\-\-raw Send header and body as binary diaray
\-\-shardKey Send Ringpop shardKey transport header
\-\-no\-strict Parse thrift IDL files loosely
\-\-timeout <value> Set a timeout value in milliseconds
.SH DESCRIPTION
.P
\fBtcurl\fP is a tool for constructing and sending requests to
a tchannel service\. It supports thrift, JSON, and raw request format\.
\fBtcurl\fP is a tool for constructing and sending requests to a tchannel service\.
It supports Thrift, JSON, and raw request format\.
.SH EXAMPLES
.RS 0
.IP \(bu 2
\fBtcurl \-p localhost:8080 serviceName \-\-health\fP
.IP \(bu 2
\fBtcurl \-p 127\.0\.0\.1:21300 hyperbahn Hyperbahn::discover \-t \./hyperbahn\.thrift \-3 '{"query":{"serviceName":"ringpop"}}'\fP
.IP \(bu 2
\fBtcurl \-p localhost:8080 serviceName endpoint \-\-raw \-3 'message'\fP
.IP \(bu 2
\fBtcurl \-p 127\.0\.0\.1:21300 hyperbahn Hyperbahn::discover \-t \./hyperbahn\.thrift \-3 '{"query":{"serviceName":"ringpop"}}'\fP

.RE
.P
The following is an example thrift file for the thrift example command above:
.P
.RS 2
.nf
```
struct Query {
1: required string serviceName;
}

service Hyperbahn {
string discover(
1: required Query query;
)
}
```
.fi
.RE
.SH OPTIONS
.P
\fB\-v | \-\-version\fP
Print the current version\.
.P
\fB\-p host:port serviceName [endpoint]\fP
Specify the destination where the request should be sent to
including the host, the port, the serviceName, and the endpoint\.
When used with \-\-health, endpoint is not required\.
\fB\-p | \-\-peer host:port serviceName <endpoint>\fP
Specify the destination where the request should be sent to including the
host, the port, the serviceName, and the endpoint\. When used with \-\-health,
endpoint is not required\.
.P
\fB\-H host\-file serviceName [endpoint]\fP
\fB\-H | \-\-hostfile </path/to/hostfile> <serviceName> <endpoint>\fP
Similar to the \fB\-p\fP option\. Instead of the host:port, it takes a host\-file
that contains a list of host:port where this request can be sent to\.
TChannel will only pick one host:port to send the request to\.
TChannel will only pick one host:port to send the request to\. An example
hostfile with two hyperbahn hosts:
.P
.RS 2
.nf
```
[
"127\.0\.0\.1:21300",
"127\.0\.0\.1:21301"
]
```
.fi
.RE
.P
\fB\-\-health\fP
Send a health check request to a sevice that implements the "Meta::health"
Expand Down Expand Up @@ -83,23 +125,28 @@ service Hyperbahn {
.fi
.RE
.P
\fB\-t thrift\fP
Used with the thrift encoding to specify the path to the thrift files\.
The thrift option value can either point to a file or a directory\.
\fB\-t | \-\-thrift </path/to/thrift/file>\fP
Used with the thrift encoding to specify the path to the thrift files\. The
thrift option value can either point to a file or a directory\.
For example:
.P
.RS 2
.nf
```
tcurl \-p 127\.0\.0\.1:21300 serviceName Meta::health \-t \. \-3 null
```
The above command assumes that current folder contains the meta\.thrift IDL file\.
The above command assumes that current folder contains the meta\.thrift IDL
file\. The endpoint specified at the command line should be defined in the
specified thrift file\. Using the example immediatly above, the following
would be a valid request:
```
tcurl hyperbahn Hyperbahn::DiscoveryResult \-\-body '{ "serviceName": "ringpop" }' `\-\-thrift \./idl/hyperbahn\.thrift
.fi
.RE
.P
\fB\-\-no\-strict\fP
Disable the default strict mode of thrift parsing\. When strict mode is enabled,
all fields must be specified as either "required" or "optional"\.
Disable the default strict mode of thrift parsing\. When strict mode is
enabled, all fields must be specified as either "required" or "optional"\.
.P
\fB\-\-raw\fP
Use raw format (i\.e\. plain text) for request\.
Expand All @@ -117,7 +164,7 @@ tcurl \-p 127\.0\.0\.1:21300 echoServer '/echo' \-\-http 'POST' \-\-head '{"Acce
.RE
.P
\fB\-\-timeout value\fP
Specify the maximum time in miniseconds this request can take
Specify the maximum time in milliseconds this request can take
until it timeout\.
For example, the following command specifies a timeout value
of one second:
Expand All @@ -132,6 +179,57 @@ tcurl \-p 127\.0\.0\.1:8080 serviceName endpoint \-\-timeout 1000
.P
\fB\-\-shardKey\fP
Ringpop only\. Send ringpop shardKey transport header\.
.P
\fB\-\-config\fP
Path to a JSON or ini\-style configuration file with values for any
of the configurable keys above\.
.P
\fB\-\-helpUrl\fP
A url string that is printed along with usage information\. This feature
exists for organizations using tcurl, tchannel and hyperbahn to provide a
URL to a help document specific to how they use tcurl\. This option should
not be specified as a command line flag and should instead be specified
in a tcurlrc file\.
.SH CONFIGURATION
.P
\fBtcurl\fP supports getting its configuration from command line arguments,
environment variables and tcurlrc files (in that order)\.
.P
The command line options are listed above\. Environment variables should
be prefixed with TCURL_ and the key in UPPER_SNAKE_CASE\. e\.g\.
.P
.RS 2
.nf
```
TCURL_HOSTFILE=/path/to/hostfile\.json
TCURL_NO_STRICT=true
```
.fi
.RE
.P
After giving precedence to command line arguments and environment
variables it will probe the following JSON or ini\-style configuration
files in order of highest precedence to lowest\.
.RS 0
.IP \(bu 2
a tcurlrc specified with the \-\-config flag\.
.IP \(bu 2
a local \.tcurlrc in the current working directory or the first one
found looking in \./ \.\./ \.\./\.\./ \.\./\.\./\.\./ etc\.
.IP \(bu 2
$HOME/\.tcurlrc
.IP \(bu 2
$HOME/\.tcurl/config
.IP \(bu 2
$HOME/\.config/tcurl
.IP \(bu 2
$HOME/\.config/tcurl/config
.IP \(bu 2
/etc/tcurlrc
.IP \(bu 2
/etc/tcurl/config

.RE
.SH EXIT CODES
.RS 0
.IP \(bu 2
Expand Down Expand Up @@ -162,6 +260,18 @@ tcurl \-p 127\.0\.0\.1:8080 serviceName endpoint \-\-timeout 1000
\fB127: fatal protocol error\fP

.RE
.SH \fBlocalhost\fP caveat
.P
For TChannel and Hyperbahn to work together effectively, most tchannel
services need to listen on the external IP of the host they are running
on\.
.P
This means when you use \fB127\.0\.0\.1\fP you cannot reach the service with
tcurl as it's not listening on loopback\.
.P
To make supporting external IPs easier we've made \fBlocalhost\fP resolve
to the external IP of the machine\. This means if your listening on
loopback you have to use \fB127\.0\.0\.1\fP and not \fBlocalhost\fP
.SH BUGS
.P
Please report any bugs to https://github\.com/uber/tcurl
Expand Down
Loading