package gluetun import ( "encoding/json" "fmt" "io" "net/http" "os" "strings" ) /* will need to parse a configuration like this: [[roles]] name = "qbittorrent" # Define a list of routes with the syntax "Http-Method /path" routes = ["GET /v1/portforward"] # Define an authentication method with its parameters auth = "basic" username = "myusername" password = "mypassword" Or if using the API key authentication method: auth = "apikey" apikey = "myapikey" the 'apikey' is then sent in the X-API-Key header we will need to extract the username and password for authentication to gluetun. This will be done by mounting the same config file that gluetun has to a static location, like /gluetun-qbitt-sidecar/config.toml will need to just retrieve the exposed port via the route: GET /v1/portforward ----> {"port":5914} */ const ( PORT_FORWARD_PATH = "v1/portforward" API_KEY_HEADER = "X-API-Key" ) type Port struct { Port int `json:"port"` } type Authentication struct { ApiKey string `toml:"apikey"` Username string `toml:"username"` Password string `toml:"password"` } /* Read in the config.toml file that gluetun uses to set the api key / username and password :param path: the path to the config file. Use the path for where this is running, since this can be either ran as a container next to your deployment, or on the host itself */ func GetAuthentication(path string) (Authentication, error) { var auth Authentication _, err := os.ReadFile(path) if err != nil { return auth, err } return auth, nil } // strips everything but the port number and hostname from a string func sanitizeUrl(s string) string { protoStripped := strings.ReplaceAll( strings.ReplaceAll( strings.ReplaceAll( s, "https", "", ), "http", "", ), "://", "", ) splitHost := strings.Split(protoStripped, "/") return splitHost[0] } /* Gets the forwarded port from the server */ func GetForwardedPort(address string, apiKey string) (Port, error) { formattedUrl := fmt.Sprintf("http://%s/%s", sanitizeUrl(address), PORT_FORWARD_PATH) req, err := http.NewRequest(http.MethodGet, formattedUrl, nil) if err != nil { return Port{}, err } req.Header.Add(API_KEY_HEADER, apiKey) client := http.Client{} resp, err := client.Do(req) if err != nil { return Port{}, err } var b []byte defer resp.Body.Close() b, err = io.ReadAll(resp.Body) if err != nil { return Port{}, err } var port Port err = json.Unmarshal(b, &port) if err != nil { return port, err } return port, nil }