mirror of
https://github.com/syncthing/syncthing.git
synced 2026-09-08 12:13:23 -04:00
Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
2ca95cf149 | ||
|
|
62f6060ceb | ||
|
|
c10408263e | ||
|
|
6c25cdebf6 |
No files matched your search
@@ -445,7 +445,7 @@ jobs:
|
||||
CERTIFICATE_PATH=$RUNNER_TEMP/codesign.p12
|
||||
echo "$DEVELOPER_ID_CERTIFICATE_BASE64" | base64 -d -o "$CERTIFICATE_PATH"
|
||||
security import "$CERTIFICATE_PATH" -k "$KEYCHAIN_PATH" -P "$DEVELOPER_ID_CERTIFICATE_PASSWORD" -T /usr/bin/codesign -T /usr/bin/productsign
|
||||
security set-key-partition-list -S apple-tool:,apple: -s -k actions "$KEYCHAIN_PATH"
|
||||
security set-key-partition-list -S apple-tool:,apple: -s -k "$KEYCHAIN_PASSWORD" "$KEYCHAIN_PATH"
|
||||
|
||||
# Set the codesign identity for following steps
|
||||
echo "CODESIGN_IDENTITY=$CODESIGN_IDENTITY" >> $GITHUB_ENV
|
||||
|
||||
@@ -7,6 +7,7 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"context"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
@@ -20,6 +21,7 @@ import (
|
||||
"strconv"
|
||||
"strings"
|
||||
"sync"
|
||||
"text/template"
|
||||
"time"
|
||||
|
||||
"github.com/alecthomas/kong"
|
||||
@@ -31,11 +33,12 @@ import (
|
||||
)
|
||||
|
||||
type cli struct {
|
||||
Listen string `default:":8080" help:"Listen address"`
|
||||
MetricsListen string `default:":8082" help:"Listen address for metrics"`
|
||||
URL string `short:"u" default:"https://api.github.com/repos/syncthing/syncthing/releases?per_page=25" help:"GitHub releases url"`
|
||||
Forward []string `short:"f" help:"Forwarded pages, format: /path->https://example/com/url"`
|
||||
CacheTime time.Duration `default:"15m" help:"Cache time"`
|
||||
Listen string `default:":8080" help:"Listen address"`
|
||||
MetricsListen string `default:":8082" help:"Listen address for metrics"`
|
||||
URL string `short:"u" default:"https://api.github.com/repos/syncthing/syncthing/releases?per_page=25" help:"GitHub releases url"`
|
||||
Forward []string `short:"f" help:"Forwarded pages, format: /path->https://example/com/url"`
|
||||
CacheTime time.Duration `default:"15m" help:"Cache time"`
|
||||
AssetURLTemplate string `help:"Template for asset URLs, blank to use GitHub default" env:"ASSET_URL_TEMPLATE"`
|
||||
}
|
||||
|
||||
func main() {
|
||||
@@ -69,7 +72,7 @@ func server(params *cli) error {
|
||||
}()
|
||||
}
|
||||
|
||||
cache := &cachedReleases{url: params.URL}
|
||||
cache := &cachedReleases{url: params.URL, assetURLTemplate: params.AssetURLTemplate}
|
||||
if err := cache.Update(context.Background()); err != nil {
|
||||
return fmt.Errorf("initial cache update: %w", err)
|
||||
} else {
|
||||
@@ -266,6 +269,7 @@ func filterForCompatibility(rels []upgrade.Release, ua, osv string) []upgrade.Re
|
||||
|
||||
type cachedReleases struct {
|
||||
url string
|
||||
assetURLTemplate string
|
||||
mut sync.RWMutex
|
||||
current []upgrade.Release
|
||||
latestRel, latestPre string
|
||||
@@ -278,7 +282,7 @@ func (c *cachedReleases) Releases() []upgrade.Release {
|
||||
}
|
||||
|
||||
func (c *cachedReleases) Update(ctx context.Context) error {
|
||||
rels, err := fetchGithubReleases(ctx, c.url)
|
||||
rels, err := fetchGithubReleases(ctx, c.url, c.assetURLTemplate)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -306,7 +310,7 @@ func (c *cachedReleases) Update(ctx context.Context) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func fetchGithubReleases(ctx context.Context, url string) ([]upgrade.Release, error) {
|
||||
func fetchGithubReleases(ctx context.Context, url, assetURLTemplate string) ([]upgrade.Release, error) {
|
||||
req, err := http.NewRequestWithContext(context.TODO(), http.MethodGet, url, nil)
|
||||
if err != nil {
|
||||
metricHTTPRequests.WithLabelValues("github-releases", "error").Inc()
|
||||
@@ -325,12 +329,25 @@ func fetchGithubReleases(ctx context.Context, url string) ([]upgrade.Release, er
|
||||
}
|
||||
metricHTTPRequests.WithLabelValues("github-releases", "success").Inc()
|
||||
|
||||
tpl, err := template.New("asset").Parse(assetURLTemplate)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// Move the URL used for browser downloads to the URL field, and remove
|
||||
// the browser URL field. This avoids going via the GitHub API for
|
||||
// downloads, since Syncthing uses the URL field.
|
||||
for _, rel := range rels {
|
||||
for j, asset := range rel.Assets {
|
||||
rel.Assets[j].URL = asset.BrowserURL
|
||||
if assetURLTemplate != "" {
|
||||
buf := new(bytes.Buffer)
|
||||
if err := tpl.Execute(buf, map[string]any{"Release": rel, "Asset": asset}); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
rel.Assets[j].URL = buf.String()
|
||||
} else {
|
||||
rel.Assets[j].URL = asset.BrowserURL
|
||||
}
|
||||
rel.Assets[j].BrowserURL = ""
|
||||
}
|
||||
}
|
||||
|
||||
+23
-14
@@ -23,6 +23,7 @@ import (
|
||||
"net"
|
||||
"net/http"
|
||||
"net/url"
|
||||
"os"
|
||||
"slices"
|
||||
"strconv"
|
||||
"strings"
|
||||
@@ -154,21 +155,10 @@ func (s *apiSrv) handler(w http.ResponseWriter, req *http.Request) {
|
||||
|
||||
slog.Debug("Handling request", "id", reqID, "method", req.Method, "url", req.URL, "proto", req.Proto)
|
||||
|
||||
remoteAddr := &net.TCPAddr{
|
||||
IP: nil,
|
||||
Port: -1,
|
||||
}
|
||||
|
||||
var remoteAddr *net.TCPAddr
|
||||
if s.useHTTP {
|
||||
// X-Forwarded-For can have multiple client IPs; split using the comma separator
|
||||
forwardIP, _, _ := strings.Cut(req.Header.Get("X-Forwarded-For"), ",")
|
||||
|
||||
// net.ParseIP will return nil if leading/trailing whitespace exists; use strings.TrimSpace()
|
||||
remoteAddr.IP = net.ParseIP(strings.TrimSpace(forwardIP))
|
||||
|
||||
if parsedPort, err := strconv.ParseInt(req.Header.Get("X-Client-Port"), 10, 0); err == nil {
|
||||
remoteAddr.Port = int(parsedPort)
|
||||
}
|
||||
remoteAddr = forwardedRemoteAddr(req)
|
||||
} else {
|
||||
var err error
|
||||
remoteAddr, err = net.ResolveTCPAddr("tcp", req.RemoteAddr)
|
||||
@@ -191,6 +181,21 @@ func (s *apiSrv) handler(w http.ResponseWriter, req *http.Request) {
|
||||
}
|
||||
}
|
||||
|
||||
func forwardedRemoteAddr(req *http.Request) *net.TCPAddr {
|
||||
forwardIP, _, _ := strings.Cut(req.Header.Get("X-Forwarded-For"), ",")
|
||||
|
||||
remoteAddr := &net.TCPAddr{
|
||||
IP: net.ParseIP(strings.TrimSpace(forwardIP)),
|
||||
Port: -1,
|
||||
}
|
||||
|
||||
if parsedPort, err := strconv.ParseInt(req.Header.Get("X-Client-Port"), 10, 0); err == nil {
|
||||
remoteAddr.Port = int(parsedPort)
|
||||
}
|
||||
|
||||
return remoteAddr
|
||||
}
|
||||
|
||||
func (s *apiSrv) handleGET(w http.ResponseWriter, req *http.Request) {
|
||||
reqID := req.Context().Value(idKey).(requestID)
|
||||
|
||||
@@ -327,7 +332,11 @@ func (s *apiSrv) handleAnnounce(deviceID protocol.DeviceID, addresses []string)
|
||||
return s.db.merge(&deviceID, dbAddrs, seen)
|
||||
}
|
||||
|
||||
func handlePing(w http.ResponseWriter, _ *http.Request) {
|
||||
func handlePing(w http.ResponseWriter, req *http.Request) {
|
||||
hostname, _ := os.Hostname()
|
||||
w.Header().Set("Discovery-Server-Instance", hostname)
|
||||
w.Header().Set("Discovery-Client-Address", req.RemoteAddr)
|
||||
w.Header().Set("Discovery-Client-Remote", forwardedRemoteAddr(req).String())
|
||||
w.WriteHeader(http.StatusNoContent)
|
||||
}
|
||||
|
||||
|
||||
Reference in new issue
Block a user