2016-12-17 04:28:59 -07:00
|
|
|
// Copyright (C) 2014 Audrius Butkevičius
|
|
|
|
|
2016-12-16 17:25:45 -07:00
|
|
|
package main
|
|
|
|
|
|
|
|
import (
|
|
|
|
"bytes"
|
|
|
|
"crypto/tls"
|
|
|
|
"net/http"
|
|
|
|
"strings"
|
|
|
|
|
|
|
|
"github.com/AudriusButkevicius/cli"
|
|
|
|
)
|
|
|
|
|
|
|
|
type APIClient struct {
|
|
|
|
httpClient http.Client
|
|
|
|
endpoint string
|
|
|
|
apikey string
|
|
|
|
username string
|
|
|
|
password string
|
|
|
|
id string
|
|
|
|
csrf string
|
|
|
|
}
|
|
|
|
|
|
|
|
var instance *APIClient
|
|
|
|
|
|
|
|
func getClient(c *cli.Context) *APIClient {
|
|
|
|
if instance != nil {
|
|
|
|
return instance
|
|
|
|
}
|
|
|
|
endpoint := c.GlobalString("endpoint")
|
|
|
|
if !strings.HasPrefix(endpoint, "http") {
|
|
|
|
endpoint = "http://" + endpoint
|
|
|
|
}
|
|
|
|
httpClient := http.Client{
|
|
|
|
Transport: &http.Transport{
|
|
|
|
TLSClientConfig: &tls.Config{
|
|
|
|
InsecureSkipVerify: c.GlobalBool("insecure"),
|
|
|
|
},
|
|
|
|
},
|
|
|
|
}
|
|
|
|
client := APIClient{
|
|
|
|
httpClient: httpClient,
|
|
|
|
endpoint: endpoint,
|
|
|
|
apikey: c.GlobalString("apikey"),
|
|
|
|
username: c.GlobalString("username"),
|
|
|
|
password: c.GlobalString("password"),
|
|
|
|
}
|
|
|
|
|
|
|
|
if client.apikey == "" {
|
|
|
|
request, err := http.NewRequest("GET", client.endpoint, nil)
|
|
|
|
die(err)
|
|
|
|
response := client.handleRequest(request)
|
|
|
|
client.id = response.Header.Get("X-Syncthing-ID")
|
|
|
|
if client.id == "" {
|
|
|
|
die("Failed to get device ID")
|
|
|
|
}
|
|
|
|
for _, item := range response.Cookies() {
|
|
|
|
if item.Name == "CSRF-Token-"+client.id[:5] {
|
|
|
|
client.csrf = item.Value
|
|
|
|
goto csrffound
|
|
|
|
}
|
|
|
|
}
|
|
|
|
die("Failed to get CSRF token")
|
|
|
|
csrffound:
|
|
|
|
}
|
|
|
|
instance = &client
|
|
|
|
return &client
|
|
|
|
}
|
|
|
|
|
|
|
|
func (client *APIClient) handleRequest(request *http.Request) *http.Response {
|
|
|
|
if client.apikey != "" {
|
|
|
|
request.Header.Set("X-API-Key", client.apikey)
|
|
|
|
}
|
|
|
|
if client.username != "" || client.password != "" {
|
|
|
|
request.SetBasicAuth(client.username, client.password)
|
|
|
|
}
|
|
|
|
if client.csrf != "" {
|
|
|
|
request.Header.Set("X-CSRF-Token-"+client.id[:5], client.csrf)
|
|
|
|
}
|
|
|
|
|
|
|
|
response, err := client.httpClient.Do(request)
|
|
|
|
die(err)
|
|
|
|
|
|
|
|
if response.StatusCode == 404 {
|
|
|
|
die("Invalid endpoint or API call")
|
|
|
|
} else if response.StatusCode == 401 {
|
|
|
|
die("Invalid username or password")
|
|
|
|
} else if response.StatusCode == 403 {
|
|
|
|
if client.apikey == "" {
|
|
|
|
die("Invalid CSRF token")
|
|
|
|
}
|
|
|
|
die("Invalid API key")
|
|
|
|
} else if response.StatusCode != 200 {
|
|
|
|
body := strings.TrimSpace(string(responseToBArray(response)))
|
|
|
|
if body != "" {
|
|
|
|
die(body)
|
|
|
|
}
|
|
|
|
die("Unknown HTTP status returned: " + response.Status)
|
|
|
|
}
|
|
|
|
return response
|
|
|
|
}
|
|
|
|
|
|
|
|
func httpGet(c *cli.Context, url string) *http.Response {
|
|
|
|
client := getClient(c)
|
|
|
|
request, err := http.NewRequest("GET", client.endpoint+"/rest/"+url, nil)
|
|
|
|
die(err)
|
|
|
|
return client.handleRequest(request)
|
|
|
|
}
|
|
|
|
|
|
|
|
func httpPost(c *cli.Context, url string, body string) *http.Response {
|
|
|
|
client := getClient(c)
|
|
|
|
request, err := http.NewRequest("POST", client.endpoint+"/rest/"+url, bytes.NewBufferString(body))
|
|
|
|
die(err)
|
|
|
|
return client.handleRequest(request)
|
|
|
|
}
|