112 lines
2.6 KiB
Go
112 lines
2.6 KiB
Go
package tunnel
|
|
|
|
import (
|
|
"encoding/json"
|
|
"fmt"
|
|
"net/http"
|
|
"strings"
|
|
"time"
|
|
|
|
"github.com/google/uuid"
|
|
"github.com/pkg/errors"
|
|
|
|
"github.com/cloudflare/cloudflared/connection"
|
|
)
|
|
|
|
const httpTimeout = 15 * time.Second
|
|
|
|
// RunQuickTunnel requests a tunnel from the specified service.
|
|
// We use this to power quick tunnels on trycloudflare.com, but the
|
|
// service is open-source and could be used by anyone.
|
|
func RunQuickTunnel(sc *subcommandContext) error {
|
|
sc.log.Info().Msg("Requesting new Quick Tunnel...")
|
|
|
|
client := http.Client{
|
|
Transport: &http.Transport{
|
|
TLSHandshakeTimeout: httpTimeout,
|
|
ResponseHeaderTimeout: httpTimeout,
|
|
},
|
|
Timeout: httpTimeout,
|
|
}
|
|
|
|
resp, err := client.Post(fmt.Sprintf("%s/tunnel", sc.c.String("quick-service")), "application/json", nil)
|
|
if err != nil {
|
|
return errors.Wrap(err, "failed to request quick tunnel")
|
|
}
|
|
defer resp.Body.Close()
|
|
|
|
var data QuickTunnelResponse
|
|
if err := json.NewDecoder(resp.Body).Decode(&data); err != nil {
|
|
return errors.Wrap(err, "failed to unmarshal quick tunnel")
|
|
}
|
|
|
|
tunnelID, err := uuid.Parse(data.Result.ID)
|
|
if err != nil {
|
|
return errors.Wrap(err, "failed to parse quick tunnel ID")
|
|
}
|
|
|
|
credentials := connection.Credentials{
|
|
AccountTag: data.Result.AccountTag,
|
|
TunnelSecret: data.Result.Secret,
|
|
TunnelID: tunnelID,
|
|
TunnelName: data.Result.Name,
|
|
}
|
|
|
|
for _, line := range AsciiBox([]string{
|
|
"Your Quick Tunnel has been created! Visit it at:",
|
|
data.Result.Hostname,
|
|
}, 2) {
|
|
sc.log.Info().Msg(line)
|
|
}
|
|
|
|
return StartServer(
|
|
sc.c,
|
|
version,
|
|
&connection.NamedTunnelConfig{Credentials: credentials, QuickTunnelUrl: data.Result.Hostname},
|
|
sc.log,
|
|
sc.isUIEnabled,
|
|
)
|
|
}
|
|
|
|
type QuickTunnelResponse struct {
|
|
Success bool
|
|
Result QuickTunnel
|
|
Errors []QuickTunnelError
|
|
}
|
|
|
|
type QuickTunnelError struct {
|
|
Code int
|
|
Message string
|
|
}
|
|
|
|
type QuickTunnel struct {
|
|
ID string `json:"id"`
|
|
Name string `json:"name"`
|
|
Hostname string `json:"hostname"`
|
|
AccountTag string `json:"account_tag"`
|
|
Secret []byte `json:"secret"`
|
|
}
|
|
|
|
// Print out the given lines in a nice ASCII box.
|
|
func AsciiBox(lines []string, padding int) (box []string) {
|
|
maxLen := maxLen(lines)
|
|
spacer := strings.Repeat(" ", padding)
|
|
border := "+" + strings.Repeat("-", maxLen+(padding*2)) + "+"
|
|
box = append(box, border)
|
|
for _, line := range lines {
|
|
box = append(box, "|"+spacer+line+strings.Repeat(" ", maxLen-len(line))+spacer+"|")
|
|
}
|
|
box = append(box, border)
|
|
return
|
|
}
|
|
|
|
func maxLen(lines []string) int {
|
|
max := 0
|
|
for _, line := range lines {
|
|
if len(line) > max {
|
|
max = len(line)
|
|
}
|
|
}
|
|
return max
|
|
}
|