net
net copied to clipboard
Lookup failed for simple http.Get("https://httpbin.org/anything")
Hi, thank you for the project! I am wondering if I am wrong something with this simple PoC:
package main
import (
"fmt"
"net/http"
_ "github.com/stealthrocket/net/http"
)
func main() {
// Use hostname in URL so TLS certificate validation succeeds.
resp, err := http.Get("https://httpbin.org/anything")
if err != nil {
panic(err)
}
defer resp.Body.Close()
fmt.Println("Response Status:", resp.Status)
fmt.Println("Response Headers:", resp.Header)
}
$ GOOS=wasip1 GOARCH=wasm go build -o main.wasm main.go
$ wasmedge main.wasm
panic: Get "https://httpbin.org/anything": dial httpbin.org:443 httpbin.org:443: lookup httpbin.org on [::1]:53: Connection refused
goroutine 1 [running]:
main.main()
...golang-wasm/http/main.go:16 +0x20
Also tried with macOS and Linux, with wasirun and nothing, it seems that lookup fails.
I have found this "tricky" approach:
package main
import (
"context"
"crypto/tls"
"crypto/x509"
_ "embed"
"fmt"
"io"
"net"
"net/http"
_ "github.com/stealthrocket/net/http"
"github.com/stealthrocket/net/wasip1"
)
//go:embed cacert.pem
var caCertsPEM []byte
func main() {
// Load CA certificates from embedded file
certPool := x509.NewCertPool()
if !certPool.AppendCertsFromPEM(caCertsPEM) {
panic("Failed to parse CA certificates")
}
// Override the default resolver to use 1.1.1.1:53 explicitly
net.DefaultResolver = &net.Resolver{
PreferGo: true,
Dial: func(ctx context.Context, network, address string) (net.Conn, error) {
// Force use of 1.1.1.1:53 instead of [::1]:53
return wasip1.DialContext(ctx, network, "1.1.1.1:53")
},
}
// Create HTTP client with custom TLS config and dialer
client := &http.Client{
Transport: &http.Transport{
DialContext: wasip1.DialContext,
TLSClientConfig: &tls.Config{
RootCAs: certPool,
},
},
}
fmt.Println("Fetching https://httpbin.org/anything ...")
resp, err := client.Get("https://httpbin.org/anything")
if err != nil {
panic(err)
}
defer resp.Body.Close()
fmt.Println("Response Status:", resp.Status)
fmt.Println("Response Headers:", resp.Header)
body, err := io.ReadAll(resp.Body)
if err != nil {
panic(err)
}
fmt.Printf("\nBody (first 500 chars):\n%s\n", string(body[:min(len(body), 500)]))
}
func min(a, b int) int {
if a < b {
return a
}
return b
}
this solves the certificate problem (curl -o cacert.pem https://curl.se/ca/cacert.pem)
And defines the DNS resolver.
I would like to find a way that this become transparent when compiling existing projects in wasm.
Do you know if is there some approach to hide this conversion when a user call http.Get?