Installing or updating (same command can be used for both):
dotnet tool update -g dotnet-echo
Usage:
> dotnet echo -?
echo
A trivial program that echoes whatever is sent to it via HTTP or gRPC
Usage:
echo [options] [<port>...]
Arguments:
<port> Port(s) to listen on. [default: 80 or 443 with --ssl] [default: ]
Options:
-ssl Use HTTPS with self-signed SSL certificate, persisted as dotnet-echo.pfx in the current directory.
-http2 Use HTTP/2 only. Prevents additional port for HTTP/2 to support gRPC.
--version Show version information
-?, -h, --help Show help and usage information
The program will automatically check for updates once a day and recommend updating if there is a new version available.
The service supports gRPC too, with echo.proto:
syntax = "proto3";
service chamber {
rpc echo (message) returns (message);
}
message message {
string payload = 1;
}
Since gRPC needs to use HTTP/2,
dotnet-echo
will use the specified port
(s) + 1 to listen HTTP/2-only traffic
(i.e. if you specify 8080
, the gRPC endpoint will be available at http://localhost:8081
).
You can avoid the additional port by forcing HTTP/2-only with the --http2
option.
Example of a .NET client to run echo
in the chamber
service:
<Project>
...
<ItemGroup>
<PackageReference Include="Google.Protobuf" Version="*" />
<PackageReference Include="Grpc.Net.Client" Version="*" />
<PackageReference Include="Grpc.Tools" Version="*" />
</ItemGroup>
<ItemGroup>
<Protobuf Include="echo.proto" GrpcServices="Client" />
</ItemGroup>
</Project>
var channel = GrpcChannel.ForAddress("http://localhost:8081");
var service = new chamber.chamberClient(channel);
var response = await service.echoAsync(new message { Payload = "Hello World" }, cancellationToken: cancellation);
Console.WriteLine(response.Payload);
Example of a .NET client using HTTP/2 only mode for a regular HTTP POST:
var http = new HttpClient();
var send = await http.SendAsync(new HttpRequestMessage(
HttpMethod.Post,
"http://localhost:8081")
{
Content = new StringContent("Hello HTTP"),
Version = new Version(2, 0),
VersionPolicy = HttpVersionPolicy.RequestVersionOrHigher,
});
Alternatively, you can force all HTTP requests to be sent with the required Version 2.0 property with a simple delegating HTTP handler like :
class Http2Handler : DelegatingHandler
{
public Http2Handler() : this(new HttpClientHandler()) { }
public Http2Handler(HttpMessageHandler inner) : base(inner) { }
protected override Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, CancellationToken cancellationToken)
{
request.Version = new Version(2, 0);
request.VersionPolicy = HttpVersionPolicy.RequestVersionOrHigher;
return base.SendAsync(request, cancellationToken);
}
}
Which can be consumed like:
var http = new HttpClient(new Http2Handler());
var post = await http.PostAsync("http://localhost:8081", new StringContent("Hello HTTP"));
Since the handler automatically sets the relevant message properties, we can use the simpler
Delete/Get/Post/Put
methods instead.
An example of the output during execution:
And running on Ubuntu: