Pkg: Proxy Authentication Required (Received HTTP code 407 from proxy after CONNECT)

From what I could gather from reading the code of Pkg.jl and Download, it seems that there is no support for proxy authentication at all when downloading files.

Therefore I tried overriding Downloads.download function, which is used by the package manager for all (I think?) downloads.

Here is my solution, I hope that it could be useful to someone in the future:

using Downloads
import Downloads: ArgWrite, arg_write, Downloader, request, Response, status_ok, RequestError


function curl_download(
        url      :: AbstractString,
        output   :: Union{ArgWrite, Nothing} = nothing;
        headers  :: Union{AbstractVector, AbstractDict} = Pair{String, String}[],
        progress :: Union{Function, Nothing} = nothing,
        verbose  :: Bool = false)

    options = ["-L"]  # Follow redirections

    !verbose && push!(options, "-s", "-S")  # silent mode, but print errors if any
    verbose  && push!(options, "-v")  # Verbose mode

    # Pass the headers to curl
    for (header, content) in headers
        push!(options, "-H", header * ":" * content)
    end

    # Simple implementation: only file names are supported
    if !isa(output, AbstractString)
        error("Cannot handle this output file type: ", typeof(output), " as ", output)
    end

    push!(options, "-o", output)
    curl_cmd = `curl $options $url`

    if verbose
        println("Curl cmd: ", curl_cmd)
    end

    # Run the command, if it fails, print it and rethrow the error
    try
        run(curl_cmd)
    catch
        !verbose && println("Curl cmd failed: ", curl_cmd)
        rethrow()
    end

    return output
end


function Downloads.download(
    url        :: AbstractString,
    output     :: Union{ArgWrite, Nothing} = nothing;
    method     :: Union{AbstractString, Nothing} = nothing,
    headers    :: Union{AbstractVector, AbstractDict} = Pair{String,String}[],
    timeout    :: Real = Inf,
    progress   :: Union{Function, Nothing} = nothing,
    verbose    :: Bool = false,
    downloader :: Union{Downloader, Nothing} = nothing,
) :: ArgWrite
    return curl_download(url, output; headers, progress, verbose)
end

Here we just make a call to the curl via the command line and let it read the ~/.curlrc config file for proper proxy configuration.

Together with JULIA_PKG_USE_CLI_GIT=true, I could download and install CUDA.jl, AMDGPU.jl, LoopVectorization.jl… without any problems.

3 Likes