mirror of
https://github.com/sartoopjj/thefeed.git
synced 2026-05-18 07:44:45 +03:00
fix: update Android build process to use cgo for DNS resolution and streamline HTTP client configuration
This commit is contained in:
@@ -91,12 +91,20 @@ jobs:
|
||||
if [ "${{ matrix.goos }}" = "android" ]; then
|
||||
BUILD_MODE="-buildmode=pie"
|
||||
fi
|
||||
# Go's internal linker can do PIE for android/arm64 with CGO=0,
|
||||
# but android/arm (32-bit) needs an external linker via cgo.
|
||||
# Wire the NDK clang for the v7 build; arm64 stays CGO-less.
|
||||
if [ "${{ matrix.goos }}" = "android" ] && [ "${{ matrix.goarch }}" = "arm" ]; then
|
||||
# Android: build with cgo so DNS resolution goes through bionic
|
||||
# libc / netd instead of Go's pure-Go resolver, which on Android
|
||||
# finds /etc/resolv.conf empty and dies with "[::1]:53 connection
|
||||
# refused". Wire the right NDK clang per architecture.
|
||||
if [ "${{ matrix.goos }}" = "android" ]; then
|
||||
export CGO_ENABLED=1
|
||||
export CC="$ANDROID_NDK_LATEST_HOME/toolchains/llvm/prebuilt/linux-x86_64/bin/armv7a-linux-androideabi26-clang"
|
||||
case "${{ matrix.goarch }}" in
|
||||
arm)
|
||||
export CC="$ANDROID_NDK_LATEST_HOME/toolchains/llvm/prebuilt/linux-x86_64/bin/armv7a-linux-androideabi26-clang"
|
||||
;;
|
||||
arm64)
|
||||
export CC="$ANDROID_NDK_LATEST_HOME/toolchains/llvm/prebuilt/linux-x86_64/bin/aarch64-linux-android26-clang"
|
||||
;;
|
||||
esac
|
||||
test -x "$CC" || { echo "NDK clang not found at $CC"; exit 1; }
|
||||
fi
|
||||
if [ "${{ matrix.goos }}" = "android" ] && [ "${{ matrix.goarch }}" = "arm64" ]; then
|
||||
|
||||
+23
-63
@@ -8,7 +8,6 @@ import (
|
||||
"io"
|
||||
"net"
|
||||
"net/http"
|
||||
"runtime"
|
||||
"strconv"
|
||||
"sync"
|
||||
"time"
|
||||
@@ -17,66 +16,28 @@ import (
|
||||
"github.com/sartoopjj/thefeed/internal/protocol"
|
||||
)
|
||||
|
||||
// defaultRelayClient is used on platforms where the OS resolver works
|
||||
// out of the box (Linux desktop, macOS, Windows, *BSD). It resolves
|
||||
// `api.github.com` via the user's system DNS — the same way any other
|
||||
// browser/curl would.
|
||||
var defaultRelayClient = &http.Client{Timeout: 30 * time.Second}
|
||||
|
||||
// fallbackPublicDNS is the last-resort resolver list used on Android
|
||||
// when the project hasn't accumulated any active resolvers yet. The
|
||||
// dialer tries each one in turn, so a single blocked endpoint doesn't
|
||||
// kill the relay path. Mix of Cloudflare, Google, Quad9, AdGuard so at
|
||||
// least one is reachable from most networks (including blocked ones).
|
||||
var fallbackPublicDNS = []string{
|
||||
"1.1.1.1:53",
|
||||
"8.8.8.8:53",
|
||||
"9.9.9.9:53",
|
||||
"94.140.14.14:53", // AdGuard
|
||||
}
|
||||
|
||||
// newRelayHTTPClient picks the right HTTP client for the GitHub relay
|
||||
// path. On Android the pure-Go OS resolver finds /etc/resolv.conf empty
|
||||
// and falls back to [::1]:53 — so we override it with the project's
|
||||
// active DNS resolvers (the same ones the rest of the app validated).
|
||||
// Everywhere else, we use the OS resolver to keep local-loopback test
|
||||
// setups (resolver=127.0.0.1) from breaking, since the user's local
|
||||
// thefeed-server doesn't resolve external hostnames.
|
||||
func newRelayHTTPClient(resolvers []string) *http.Client {
|
||||
if runtime.GOOS != "android" {
|
||||
return defaultRelayClient
|
||||
}
|
||||
picks := append([]string(nil), resolvers...)
|
||||
if len(picks) == 0 {
|
||||
picks = append(picks, fallbackPublicDNS...)
|
||||
}
|
||||
var idx int
|
||||
dialDNS := func(ctx context.Context, network, _ string) (net.Conn, error) {
|
||||
// Round-robin through the picks so a single bad resolver doesn't
|
||||
// kill the relay path. Net.Resolver retries the Dial on failure
|
||||
// against the next entry.
|
||||
host := picks[idx%len(picks)]
|
||||
idx++
|
||||
d := net.Dialer{Timeout: 5 * time.Second}
|
||||
return d.DialContext(ctx, network, host)
|
||||
}
|
||||
return &http.Client{
|
||||
Timeout: 30 * time.Second,
|
||||
Transport: &http.Transport{
|
||||
DialContext: (&net.Dialer{
|
||||
Timeout: 10 * time.Second,
|
||||
Resolver: &net.Resolver{
|
||||
PreferGo: true,
|
||||
Dial: dialDNS,
|
||||
},
|
||||
}).DialContext,
|
||||
ForceAttemptHTTP2: true,
|
||||
MaxIdleConns: 10,
|
||||
IdleConnTimeout: 90 * time.Second,
|
||||
TLSHandshakeTimeout: 10 * time.Second,
|
||||
ExpectContinueTimeout: 1 * time.Second,
|
||||
},
|
||||
}
|
||||
// relayHTTPClient is the single shared HTTP client for the GitHub relay
|
||||
// path. Reusing one client (and its underlying *http.Transport) gives us
|
||||
// connection pooling and DNS-result caching for free across the many
|
||||
// per-file fetches a media-heavy refresh cycle produces.
|
||||
//
|
||||
// We use the OS resolver everywhere. On Android the build is cgo-enabled
|
||||
// (see .github/workflows/build.yml), so net.Lookup* goes through
|
||||
// bionic libc → netd → the device's actual DNS, the same path any other
|
||||
// Android app uses. On desktop the OS resolver is similarly fine.
|
||||
var relayHTTPClient = &http.Client{
|
||||
Timeout: 30 * time.Second,
|
||||
Transport: &http.Transport{
|
||||
DialContext: (&net.Dialer{
|
||||
Timeout: 10 * time.Second,
|
||||
KeepAlive: 30 * time.Second,
|
||||
}).DialContext,
|
||||
ForceAttemptHTTP2: true,
|
||||
MaxIdleConns: 10,
|
||||
IdleConnTimeout: 90 * time.Second,
|
||||
TLSHandshakeTimeout: 10 * time.Second,
|
||||
ExpectContinueTimeout: 1 * time.Second,
|
||||
},
|
||||
}
|
||||
|
||||
// relayInfoTTL is how long the cached repo-discovery payload stays valid.
|
||||
@@ -196,8 +157,7 @@ func (s *Server) serveFromGitHubRelay(w http.ResponseWriter, r *http.Request, si
|
||||
// The blob on disk is AES-256-GCM(nonce||ct||tag) over the plaintext.
|
||||
// Cap the fetch at plaintext size + small overhead.
|
||||
const aeadOverhead = protocol.NonceSize + 16 // GCM tag is 16 bytes
|
||||
httpClient := newRelayHTTPClient(fetcher.Resolvers())
|
||||
encBody, _, err := fetchGitHubRaw(ctx, httpClient, url, size+int64(aeadOverhead))
|
||||
encBody, _, err := fetchGitHubRaw(ctx, relayHTTPClient, url, size+int64(aeadOverhead))
|
||||
if err != nil {
|
||||
s.addLog(fmt.Sprintf("relay: fetch %s: %v", url, err))
|
||||
// Not handled — caller falls back to DNS.
|
||||
|
||||
Reference in New Issue
Block a user