Understanding the proxies.edgelq.com service APIv1, in proto package ntt.proxies.v1.
SPEKTRA Edge Proxies Service API
The Proxies service provides an easy way to establish secure tunnels between your clients, which helps your applications running in different locations to communicate with each other.

The Proxy service component relationship.
The main problem with establishing connections between two clients in different locations on the internet is that it’s not always easy to reach out to the other client through firewalls and NATs in between. Most home networks are protected by NATs and you usually have to implement a VPN network to set up a peer-to-peer connection.
The Proxies service provides clients with a meet-up endpoint for clients to establish client-initiated connections and stitches two connections to make an end-to-end connection between two clients. Because all connections are client-initiated, NAT and firewalls won’t cause any connection problems.
While the Proxies service provides only a framework to establish connections between clients, you can implement your own use cases on top of that such as tunnels for remote commands, which is how the Devices service utilizes the Proxies service, and TCP port forwarding just like the ZTNA service work with the Proxies service.
Full API Specifications (with resources):
Resources
Tunnels
A Tunnel is an end-to-end connection between two clients. It is built with two client-initiated gRPC sessions to our meet-up endpoint on the cloud to avoid problems caused by firewalls and NATs. As a tunnel works as a bare data stream just like a normal TCP connection, you can implement any protocol on top of it.
Tunnel Brokers
A tunnel broker is a part of the service backend, it provides a mechanism for establishing tunnels between consumers and providers.
Tunnel Consumers
A tunnel consumer is one of the end clients that connects with the broker to establish a tunnel with the selected provider.
Tunnel Providers
A tunnel provider is connecting to a broker (registration), and then passively waits for consumers to connect to it.
Code Samples
Ping/Pong over Tunnel
Let’s create a simple ping/pong service where consumers send Ping messages, and then Providers return Pong messages.
First, define a struct that implements provider.ServiceFactory
.
import provider "github.com/cloudwan/edgelq/proxies/provider/v1"
type PingService struct {
closed chan struct{} // will be closed when Close() is called
called chan struct{}
}
// Start is called when a new tunnel is established.
// You can initialize your service here, but
func (s *PingService) Start(ctx context.Context) error {
s.closed = make(chan struct{}, 0)
s.called = make(chan struct{}, 1)
}
// Send is called when the Consumer sends data to the Consumer.
func (s *PingService) Send(data []byte) error {
if string(data) != "PING" {
return fmt.Errorf("unexpected message received")
}
select {
case s.called <- stcut{}{}:
// asked to Recv() to send Pong
case <- s.closed:
it's being closed, give up
}
return nil
}
// Recv is called to receive message from the service.
func (s *PingService) Recv() ([]byte, error) {
select {
case <- s.called:
return []byte("PONG"), nil
case <- s.closed:
return nil, fmt.Error("service is closing")
}
}
// Close is called when the connection is going to be closed.
func (s *PingService) Close() error {
close(s.closed)
}
Then, create a Provider with the service.
import (
broker "github.com/cloudwan/edgelq/proxies/client/v1/broker"
provider "github.com/cloudwan/edgelq/proxies/provider/v1"
project "github.com/cloudwan/edgelq/proxies/resources/v1/project"
)
var client proxcbroker.BrokerServiceClient // setup a client
// List of services (we have only one at this moment).
services := map[string]provider.ServiceFactory{
"ping": func(ctx context.Context, arg []byte) (provider.Service, error) {
return NewPingService(), nil
},
}
// Create a Provider
provier := provider.NewProvider(
project.NewNameBuilder().SetId("YourProjectID").Name(),
"my-first-provider-id",
"us-west2",
"ping.edgelq.com",
services,
)
// Run it.
provider.Run(ctx, client)
Now your Ping service is “Provided”.
Next, let’s consume the service as a Consumer.
import (
broker "github.com/cloudwan/edgelq/proxies/client/v1/broker"
)
var client proxcbroker.BrokerServiceClient // setup a client
// define an “Outlet” that implements Recv() and Send()
type PingOutlet struct {
sent bool
}
// Send writes data from the other end to the Outlet.
func (o *PingOutlet) Send(data []byte) error {
fmt.Printf(“Received: %s\n”, string(data))
}
// Recv outputs data from the Outlet
func (o *PingOutlet) Recv() ([]byte, error) {
if o.sent {
Return nil, io.EOF
}
o.sent = true
return []byte(“PING”), nil
}
err := consumer.Connect(
context.Background(),
client,
proxrproject.NewNameBuilder().SetId("YourProjectID").Name(),
"my-first-consumer-id",
"us-west2",
"ping.edgelq.com",
"my-first-provider-id", // provider ID to connect to
"ping", // service name
nil, // no initial arg
PingOutlet{},
)