mirror of
https://github.com/advplyr/audiobookshelf.git
synced 2026-05-30 23:40:40 +02:00
[PR #4885] Implement experimental DNS pre-resolution, enabling Podcast downloads even with partial DNS resolution failures #4365
Reference in New Issue
Block a user
Delete Branch "%!s()"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
📋 Pull Request Information
Original PR: https://github.com/advplyr/audiobookshelf/pull/4885
Author: @PassionateBytes
Created: 12/2/2025
Status: 🔄 Open
Base:
master← Head:fix-dns-resolution📝 Commits (3)
da040c7Implement experimental DNS pre-resolution33d2839Use experimental DNS resolution on redirectsfc81be0Handle redirect loops and maximum redirect limits📊 Changes
1 file changed (+78 additions, -0 deletions)
View changed files
📝
server/Server.js(+78 -0)📄 Description
Brief summary
This PR introduces an optional configuration parameter
EXP_DNS_RESOLUTIONto the server, which enables a custom mechanism for pre-resolving hostnames in allaxiosweb requests. This mechanism uses the dedicateddnspackage to explicitly resolveAandAAAArecords. This bypasses thegetaddrinfosyscall, which in the Alpine container environment fails entirely, if only part of the DNS query results in aSERVFAIL.This enables successful web requests in situations that would otherwise fail due to partial DNS resolution failures. - i.e. situations in which a DNS query resolves an
Arecord of a hostname, while rejecting requests forAAAArecords (R-CodeSERVFAIL, orREFUSED). I have found that this causes thegetaddrinfosyscall to fail entirely inside the Alpine container environment specifically, with the result that the entire web request fails. (Note that this is an alpine specific problem).Enabling this new feature with
EXP_DNS_RESOLUTION=1will trigger explicit DNS resolution, with graceful fallback between IPv4 and IPv6. If either fails to resolve, while the other succeeds, the web request will still be allowed to go through, rather than failing entirely.Which issue is fixed?
Additionally, a discussion of the issue server side can be found here:
...potentially more than just these issues - I have seen the same problem manifest for multiple different podcasts myself, so I expect to find more related issues. Will add them here when I come across more.
In-depth Description
It appears that in some environments axios' fails to execute a web request entirely, when a domain name gets resolved only partialy.
This can be the case when a DNS server is misconfigured, or overly restrictive, such that it only resolves IPv4 addresses (
Arecords) successfully, while rejecting IPv6 address requests (AAAArecords) withSERVFAIL(or vise versa).Consider the example below:
Understanding Status Quo:
As an example, the German News Podcast 'Lage der Nation' hosts their public feeds on
feeds.lagedernation.organd their episodes oncdn.lagedernation.org.Resolving these domains returns IPv4 addresses (
Arecord) successfully. However, their DNS server configuration appears to be faulty, because it consistently leads to aSERVFAILwhen attempting to resolve for IPv6 addresses (AAAArecords).This failure mode can be replicated in various environments:
In certain environments, axios appears to fail the entire web request when it encounters such a partial DNS resolution failure, even though a valid IPv4 address was returned. This results in errors like:
Full Error Message...
A discussion of this particular issue can be found here
A known workaround is to disable IPv6 entirely, but that is not generally feasible for everyone and not future proof.
The Solution:
This PR implements a custom DNS resolution mechanism that bypasses axios' default DNS handling (which relies on the OS's
getaddrinfo()system call and can fail in certain environments).My implementation hooks into the global axios client, following existing similar patterns in the codebase (analogous to the
EXP_PROXY_SUPPORTfeature).When enabled via
EXP_DNS_RESOLUTION=1, the following changes are applied:1. Explicit DNS resolution before executing web requests
A request interceptor is added to the global axios instance that:
Arecords viadns.resolve4()) and IPv6 (AAAArecords viadns.resolve6()) addressesPREFER_IPV6=1flag to reverse the priorityAandAAAAseparately, allowing for independent, graceful handling of failuresHostheader of the request2. Explicit redirect handling
Axios' built-in redirect following feature would bypass the custom DNS resolution interceptor. Thus automatic redirect handling is disabled (
maxRedirects = 0) and a response interceptor is added that:The Result:
With this implementation, web requests to domains with partial DNS resolution failures will succeed when
EXP_DNS_RESOLUTION=1is set, as the custom logic ensures that at least one valid IP address is used for the request.How have you tested this?
Tested against the paid
feeds.lagedernation.organdcdn.lagedernation.orgwhich both exhibits the partial DNS resolution failure:EXP_DNS_RESOLUTION=1: axios requests fail completely, failing to load the RSS feed as well ass podcast audio filesEXP_DNS_RESOLUTION=1: requests succeed by explicitly using IPv4 resolutionEXP_DNS_RESOLUTION=1andPREFER_IPV6=1: requests succeed, even though initial IPv6 resolution fails withSERVFAIL, but it gracefully falls back to IPv4 resolutionThe implementation also handles gracefully:
🔄 This issue represents a GitHub Pull Request. It cannot be merged through Gitea due to API limitations.