package main import ( "fmt" "log" "net" "net/http" "os/exec" "strings" "time" "git.sr.ht/~emersion/gqlclient" "github.com/spf13/cobra") type Client struct { *gqlclient.Client BaseURL string HTTP *http.Client} func createClient(service string, cmd *cobra.Command) *Client { return createClientWithInstance(service, cmd, "")} func createClientWithInstance(service string, cmd *cobra.Command, instanceName string) *Client { cfg := loadConfig(cmd) if len(cfg.Instances) == 0 { log.Fatalf("no sr.ht instance configured") } if instanceFlag, err := cmd.Flags().GetString("instance"); err != nil { log.Fatal(err) } else if instanceFlag != "" { if instanceName != "" && !instancesEqual(instanceName, instanceFlag) { log.Fatalf("conflicting instances: %v and --instance=%v", instanceName, instanceFlag) } instanceName = instanceFlag } var inst *InstanceConfig if instanceName != "" { for _, instance := range cfg.Instances { if instance.match(instanceName) { inst = instance break } } if inst == nil { log.Fatalf("no instance for %s found", instanceName) } } else { inst = cfg.Instances[0] } var token string if len(inst.AccessTokenCmd) > 0 { cmd := exec.Command(inst.AccessTokenCmd[0], inst.AccessTokenCmd[1:]...) output, err := cmd.Output() if err != nil { log.Fatalf("could not execute access-token-cmd: %v", err) } fields := strings.Fields(string(output)) if len(fields) == 0 { log.Fatalf("access-token-cmd did not return a token") } token = fields[0] } else { token = inst.AccessToken } var baseURL string if serviceCfg := inst.Services()[service]; serviceCfg != nil { baseURL = serviceCfg.Origin } if baseURL == "" && strings.Contains(inst.Name, ".") && net.ParseIP(inst.Name) == nil { baseURL = fmt.Sprintf("https://%s.%s", service, inst.Name) } if baseURL == "" { log.Fatalf("failed to get origin for service %q in instance %q", service, inst.Name) } debug, err := cmd.Flags().GetBool("debug") if err != nil { log.Fatal(err) } return createClientWithToken(baseURL, token, debug)} func createClientWithToken(baseURL, token string, debug bool) *Client { gqlEndpoint := baseURL + "/query" httpClient := &http.Client{ Transport: &httpTransport{accessToken: token, logRequest: debug}, Timeout: 30 * time.Second, } return &Client{ Client: gqlclient.New(gqlEndpoint, httpClient), BaseURL: baseURL, HTTP: httpClient, }} type httpTransport struct { accessToken string logRequest bool} func (tr *httpTransport) RoundTrip(req *http.Request) (*http.Response, error) { req.Header.Set("User-Agent", "hut") req.Header.Set("Authorization", "Bearer "+tr.accessToken) if tr.logRequest { log.Println(req.Body) } return http.DefaultTransport.RoundTrip(req)}
package main
import (
"fmt"
"log"
"net"
"net/http"
"os/exec"
"strings"
"time"
"git.sr.ht/~emersion/gqlclient"
"github.com/spf13/cobra"
)
type Client struct {
*gqlclient.Client
BaseURL string
HTTP *http.Client
}
func createClient(service string, cmd *cobra.Command) *Client {
return createClientWithInstance(service, cmd, "")
}
func createClientWithInstance(service string, cmd *cobra.Command, instanceName string) *Client {
cfg := loadConfig(cmd)
if len(cfg.Instances) == 0 {
log.Fatalf("no sr.ht instance configured")
}
if instanceFlag, err := cmd.Flags().GetString("instance"); err != nil {
log.Fatal(err)
} else if instanceFlag != "" {
if instanceName != "" && !instancesEqual(instanceName, instanceFlag) {
log.Fatalf("conflicting instances: %v and --instance=%v", instanceName, instanceFlag)
}
instanceName = instanceFlag
}
var inst *InstanceConfig
if instanceName != "" {
for _, instance := range cfg.Instances {
if instance.match(instanceName) {
inst = instance
break
}
}
if inst == nil {
log.Fatalf("no instance for %s found", instanceName)
}
} else {
inst = cfg.Instances[0]
}
var token string
if len(inst.AccessTokenCmd) > 0 {
cmd := exec.Command(inst.AccessTokenCmd[0], inst.AccessTokenCmd[1:]...)
output, err := cmd.Output()
if err != nil {
log.Fatalf("could not execute access-token-cmd: %v", err)
}
fields := strings.Fields(string(output))
if len(fields) == 0 {
log.Fatalf("access-token-cmd did not return a token")
}
token = fields[0]
} else {
token = inst.AccessToken
}
var baseURL string
if serviceCfg := inst.Services()[service]; serviceCfg != nil {
baseURL = serviceCfg.Origin
}
if baseURL == "" && strings.Contains(inst.Name, ".") && net.ParseIP(inst.Name) == nil {
baseURL = fmt.Sprintf("https://%s.%s", service, inst.Name)
}
if baseURL == "" {
log.Fatalf("failed to get origin for service %q in instance %q", service, inst.Name)
}
debug, err := cmd.Flags().GetBool("debug")
if err != nil {
log.Fatal(err)
}
return createClientWithToken(baseURL, token, debug)
}
func createClientWithToken(baseURL, token string, debug bool) *Client {
gqlEndpoint := baseURL + "/query"
httpClient := &http.Client{
Transport: &httpTransport{accessToken: token, logRequest: debug},
Timeout: 30 * time.Second,
}
return &Client{
Client: gqlclient.New(gqlEndpoint, httpClient),
BaseURL: baseURL,
HTTP: httpClient,
}
}
type httpTransport struct {
accessToken string
logRequest bool
}
func (tr *httpTransport) RoundTrip(req *http.Request) (*http.Response, error) {
req.Header.Set("User-Agent", "hut")
req.Header.Set("Authorization", "Bearer "+tr.accessToken)
if tr.logRequest {
log.Println(req.Body)
}
return http.DefaultTransport.RoundTrip(req)
}