feat: initial goget release — modern IPv6-first download utility
This commit is contained in:
@@ -0,0 +1,134 @@
|
||||
//go:build linux || freebsd
|
||||
// +build linux freebsd
|
||||
|
||||
package gemini
|
||||
|
||||
import (
|
||||
"bufio"
|
||||
"context"
|
||||
"crypto/ecdsa"
|
||||
"crypto/elliptic"
|
||||
"crypto/rand"
|
||||
"crypto/tls"
|
||||
"crypto/x509"
|
||||
"crypto/x509/pkix"
|
||||
"math/big"
|
||||
"net"
|
||||
"net/url"
|
||||
"strconv"
|
||||
"strings"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"codeberg.org/petrbalvin/goget/internal/core"
|
||||
)
|
||||
|
||||
type stringWriter struct{ sb *strings.Builder }
|
||||
|
||||
func (w *stringWriter) Write(p []byte) (int, error) { return w.sb.Write(p) }
|
||||
|
||||
func testTLSConfig() *tls.Config {
|
||||
key, _ := ecdsa.GenerateKey(elliptic.P256(), rand.Reader)
|
||||
tmpl := &x509.Certificate{
|
||||
SerialNumber: big.NewInt(1),
|
||||
Subject: pkix.Name{CommonName: "localhost"},
|
||||
NotBefore: time.Now(),
|
||||
NotAfter: time.Now().Add(time.Hour),
|
||||
IPAddresses: []net.IP{net.ParseIP("127.0.0.1")},
|
||||
}
|
||||
certDER, _ := x509.CreateCertificate(rand.Reader, tmpl, tmpl, &key.PublicKey, key)
|
||||
return &tls.Config{
|
||||
Certificates: []tls.Certificate{{
|
||||
Certificate: [][]byte{certDER},
|
||||
PrivateKey: key,
|
||||
}},
|
||||
}
|
||||
}
|
||||
|
||||
func TestGeminiSuccess(t *testing.T) {
|
||||
cfg := testTLSConfig()
|
||||
listener, err := tls.Listen("tcp", "127.0.0.1:0", cfg)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
defer listener.Close()
|
||||
port := listener.Addr().(*net.TCPAddr).Port
|
||||
|
||||
go func() {
|
||||
conn, _ := listener.Accept()
|
||||
if conn == nil {
|
||||
return
|
||||
}
|
||||
defer conn.Close()
|
||||
r := bufio.NewReader(conn)
|
||||
r.ReadString('\n')
|
||||
conn.Write([]byte("20 text/gemini\r\n# Hello\n\nContent.\n"))
|
||||
}()
|
||||
|
||||
proto := NewProtocol()
|
||||
proto.TLSInsecure = true
|
||||
u, _ := url.Parse("gemini://127.0.0.1:" + strconv.Itoa(port) + "/")
|
||||
var buf strings.Builder
|
||||
_, err = proto.Download(context.Background(), &core.DownloadRequest{
|
||||
URL: u,
|
||||
Writer: &stringWriter{&buf},
|
||||
})
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if !strings.Contains(buf.String(), "Hello") {
|
||||
t.Errorf("got %q", buf.String())
|
||||
}
|
||||
}
|
||||
|
||||
func TestGeminiTemporaryFailure(t *testing.T) {
|
||||
cfg := testTLSConfig()
|
||||
listener, _ := tls.Listen("tcp", "127.0.0.1:0", cfg)
|
||||
defer listener.Close()
|
||||
port := listener.Addr().(*net.TCPAddr).Port
|
||||
|
||||
go func() {
|
||||
conn, _ := listener.Accept()
|
||||
if conn == nil {
|
||||
return
|
||||
}
|
||||
defer conn.Close()
|
||||
r := bufio.NewReader(conn)
|
||||
r.ReadString('\n')
|
||||
conn.Write([]byte("40 overloaded\r\n"))
|
||||
}()
|
||||
|
||||
proto := NewProtocol()
|
||||
proto.TLSInsecure = true
|
||||
u, _ := url.Parse("gemini://127.0.0.1:" + strconv.Itoa(port) + "/")
|
||||
_, err := proto.Download(context.Background(), &core.DownloadRequest{URL: u})
|
||||
if err == nil {
|
||||
t.Error("expected temporary failure error")
|
||||
}
|
||||
}
|
||||
|
||||
func TestGeminiPermanentFailure(t *testing.T) {
|
||||
cfg := testTLSConfig()
|
||||
listener, _ := tls.Listen("tcp", "127.0.0.1:0", cfg)
|
||||
defer listener.Close()
|
||||
port := listener.Addr().(*net.TCPAddr).Port
|
||||
|
||||
go func() {
|
||||
conn, _ := listener.Accept()
|
||||
if conn == nil {
|
||||
return
|
||||
}
|
||||
defer conn.Close()
|
||||
r := bufio.NewReader(conn)
|
||||
r.ReadString('\n')
|
||||
conn.Write([]byte("51 not found\r\n"))
|
||||
}()
|
||||
|
||||
proto := NewProtocol()
|
||||
proto.TLSInsecure = true
|
||||
u, _ := url.Parse("gemini://127.0.0.1:" + strconv.Itoa(port) + "/")
|
||||
_, err := proto.Download(context.Background(), &core.DownloadRequest{URL: u})
|
||||
if err == nil {
|
||||
t.Error("expected permanent failure error")
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user