Skip to content

Add fallback for DNS config#182

Merged
NGTmeaty merged 1 commit into
internetarchive:masterfrom
MathiasDPX:fix-fallback-dnsconfig
Mar 6, 2026
Merged

Add fallback for DNS config#182
NGTmeaty merged 1 commit into
internetarchive:masterfrom
MathiasDPX:fix-fallback-dnsconfig

Conversation

@MathiasDPX

@MathiasDPX MathiasDPX commented Mar 5, 2026

Copy link
Copy Markdown
Contributor

This PR adds a fallback mechanism in case loading the DNS configuration from /etc/resolv.conf fails.

With this change, gowarc can now officially support Windows and potentially other operating systems or environments where /etc/resolv.conf is not available. Since the feature was developed and tested on Windows, Windows support is confirmed.

Linux compatibility should not be affected, as systems with a valid /etc/resolv.conf will continue using the standard DNS configuration.

In the example code, a new variable dnsFallback is introduced, which defines a dns.ClientConfig using Cloudflare DNS servers.

Fix #121

Example code
package main

import (
	"fmt"
	"io"
	"net/http"
	"time"

	warc "github.com/internetarchive/gowarc"
	"github.com/miekg/dns"
)

func main() {
	// Configure WARC settings
	rotatorSettings := &warc.RotatorSettings{
		WarcinfoContent: warc.Header{
			"software": "My WARC writing client v1.0",
		},
		Prefix:             "WEB",
		Compression:        "gzip",
		WARCWriterPoolSize: 1, // Records will be written to 4 WARC files in parallel, it helps maximize the disk IO on some hardware. To be noted, even if we have multiple WARC writers, WARCs are ALWAYS written by pair in the same file. (req/resp pair)
	}

	// Configure DNS fallback settings
	dnsFallback := &dns.ClientConfig{
		Servers:  []string{"1.1.1.1", "1.0.0.1"}, // Cloudflare DNS
		Port:     "53",
		Ndots:    1,
		Timeout:  5,
		Attempts: 1,
	}

	// Configure HTTP client settings
	clientSettings := warc.HTTPClientSettings{
		RotatorSettings: rotatorSettings,
		TempDir:         "./temp",
		DNSServers:      []string{"8.8.8.8", "8.8.4.4"},
		DNSFallback:     dnsFallback, // Fallback DNS config if /etc/resolv.conf is unavailable
		DedupeOptions: warc.DedupeOptions{
			LocalDedupe:   true,
			CDXDedupe:     false,
			SizeThreshold: 2048, // Only payloads above that threshold will be deduped
		},
		DialTimeout:           10 * time.Second,
		ResponseHeaderTimeout: 30 * time.Second,
		DNSResolutionTimeout:  5 * time.Second,
		DNSRecordsTTL:         5 * time.Minute,
		DNSCacheSize:          10000,
		MaxReadBeforeTruncate: 1000000000,
		DecompressBody:        true,
		FollowRedirects:       true,
		VerifyCerts:           true,
		RandomLocalIP:         true,
	}

	// Create HTTP client
	client, err := warc.NewWARCWritingHTTPClient(clientSettings)
	if err != nil {
		panic(err)
	}
	defer client.Close()

	// The error channel NEED to be consumed, else it will block the
	// execution of the WARC module
	go func() {
		for err := range client.ErrChan {
			fmt.Errorf("WARC writer error: %s", err.Err.Error())
		}
	}()

	// This is optional but the module give a feedback on a channel passed as context value to the
	// request, this helps knowing when the record has been written to disk. If this is not used, the WARC
	// writing is asynchronous
	req, err := http.NewRequest("GET", "https://archive.org/robots.txt", nil)
	if err != nil {
		panic(err)
	}

	feedbackChan := make(chan struct{}, 1)
	req = req.WithContext(warc.WithFeedbackChannel(req.Context(), feedbackChan))

	resp, err := client.Do(req)
	if err != nil {
		panic(err)
	}
	defer resp.Body.Close()

	// Process response
	// Note: the body NEED to be consumed to be written to the WARC file.
	io.Copy(io.Discard, resp.Body)

	// Will block until records are actually written to the WARC file
	<-feedbackChan
}

@NGTmeaty NGTmeaty left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is a great solution to the issue. Thank you!

@NGTmeaty NGTmeaty merged commit acd3171 into internetarchive:master Mar 6, 2026
3 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Create fallback for Windows DNS settings

2 participants