This PR exposes client connection information (such as the base URL, the HTTP request Doer and common HTTP utility functions for extended Pebble clients) under the Transport struct of new clientutil package.
This allows external applications to extend the Pebble client and perform HTTP requests to the underlying daemon without exposing the internal state of the client to third-party applications that use the client package to call Pebble APIs.
The clientutil package is not intended for these applications, but for software that extends Pebble.
The client API stays exactly the same, with the difference of Pebble and applications extending Pebble using new internal APIs to construct a client:
/* Example 1: Creating a client for extending the CLI. */
package main
import (
"github.com/canonical/pebble/client"
"github.com/canonical/pebble/internals/clientutil"
)
func main() {
// Create a client transport instance (DoSync*)
transport, err := clientutil.NewTransport(&clientutil.TransportOptions{
Address: "https://localhost:3000", // Either base URL or socket path.
UserAgent: "MyApplication/0.1",
})
if err != nil { /* ... */ }
// Create a Pebble client
client := client.NewFromTransport(transport)
// Pass in the client and the transport
if err := cli.Run(client, transport); err != nil {
/* ... */
}
}
Pebble CLI will pass the client and transport through CmdOptions:
// CmdOptions exposes state made accessible during command execution.
type CmdOptions struct {
Client *client.Client
Transport *clientutil.Transport
Parser *flags.Parser
}
Extending a Pebble client could be done in the following manner:
package xclient
import (
"github.com/canonical/pebble/client"
"github.com/canonical/pebble/internals/clientutil"
)
// Client is a Pebble-compatible gateway for talking to the X daemon.
// All APIs that Pebble supports are available, in addition to X-specific
// ones.
type Client struct {
*client.Client
transport *clientutil.Transport
}
func New(client *client.Client, transport *clientutil.Transport) *Client {
return &Client{Client: client, transport: transport}
}
func (c *Client) Foo() {
/* The Do(), DoSync(), DoAsync() APIs are prone to change -- WIP */
c.transport.Do("POST", "/v1/foo", nil, nil, nil, nil)
}
And extended application's commands could be constructed the following way:
This PR exposes client connection information (such as the base URL, the HTTP request
Doer
and common HTTP utility functions for extended Pebble clients) under theTransport
struct of newclientutil
package.This allows external applications to extend the Pebble client and perform HTTP requests to the underlying daemon without exposing the internal state of the client to third-party applications that use the
client
package to call Pebble APIs.The
clientutil
package is not intended for these applications, but for software that extends Pebble.The client API stays exactly the same, with the difference of Pebble and applications extending Pebble using new internal APIs to construct a client:
Pebble CLI will pass the client and transport through
CmdOptions
:Extending a Pebble client could be done in the following manner:
And extended application's commands could be constructed the following way: