| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160 |
- package gluetun
- import (
- "encoding/json"
- "errors"
- "fmt"
- "io"
- "net/http"
- "os"
- "strings"
- "git.aetherial.dev/aeth/gluetun-qbitt-sidecar/pkg/shared"
- "github.com/pelletier/go-toml/v2"
- )
- /*
- 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"
- STATUS_PATH = "v1/vpn/status"
- API_KEY_HEADER = "X-API-Key"
- GLUETUN_ADDRESS = "GLUETUN_ADDRESS"
- )
- type GluetunClient struct {
- client *http.Client
- server shared.Server
- }
- type Port struct {
- Port int `json:"port"`
- }
- type Configuration struct {
- Roles []Role `toml:"roles"`
- }
- type Role struct {
- Name string `toml:"name"`
- Routes []string `toml:"routes"`
- Auth string `toml:"auth"`
- Username string `toml:"username,omitempty"`
- Password string `toml:"password,omitempty"`
- Apikey string `toml:"apikey,omitempty"`
- }
- func NewGluetunClient() {}
- /*
- 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) (Role, error) {
- var config Configuration
- var role Role
- fb, err := os.ReadFile(path)
- if err != nil {
- return role, err
- }
- fmt.Printf("%s\n", string(fb))
- err = toml.Unmarshal(fb, &config)
- if err != nil {
- return role, err
- }
- for i := range config.Roles {
- for x := range config.Roles[i].Routes {
- if strings.Contains(config.Roles[i].Routes[x], PORT_FORWARD_PATH) {
- return config.Roles[i], nil
- }
- }
- }
- return role, errors.New(fmt.Sprintf("No routes found that contained the path: '%s'", PORT_FORWARD_PATH))
- }
- // get the gluetun address
- func GetGluetunAddress() (shared.Server, error) {
- var srv shared.Server
- client := http.Client{}
- srv, err := shared.ParseServer("http://gluetun:8000")
- if err != nil {
- return srv, err
- }
- req, err := http.NewRequest(http.MethodGet, srv.FormatWith(STATUS_PATH), nil)
- if err != nil {
- return srv, err
- }
- resp, err := client.Do(req)
- if err != nil {
- return srv, err
- }
- if resp.StatusCode == http.StatusUnauthorized { // can assume that unauthorized means that the server is alive on that endpoint
- return srv, nil
- }
- // try to parse out the environment variable that supposed to carry the value (if it is different)
- addressFromEnv := os.Getenv(GLUETUN_ADDRESS)
- srv, err = shared.ParseServer(addressFromEnv)
- if err != nil {
- return srv, err
- }
- return srv, nil
- }
- /*
- 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
- }
|