Skip to content

Repository files navigation

Contributors Forks Stargazers Issues Apache 2.0 License


httpfx

Uber Fx module for net/http.Client with SOCKS5 proxy support (including per-host bypass) and custom root CA trust.

Report Bug · Request Feature

Table of Contents


About The Project

httpfx is an Uber Fx module that provides a configured *http.Client and a Factory for creating additional client instances. It supports:

  • SOCKS5 proxy via golang.org/x/net/proxy (socks5://user:pass@host:port)
  • Per-host proxy bypass for hosts that should connect directly
  • Custom root CA trust: append internal/corporate CAs to the system pool or replace it
  • Per-client overrides via functional options on the Factory
  • Transport tuning — idle connections, timeouts, pool sizes

Built With

  • Go
  • Uber Fx
  • x/net

(back to top)


Getting Started

Prerequisites

  • Go 1.25+
  • An application using Uber Fx for dependency injection

Installation

go get github.com/go-core-fx/httpfx@latest

(back to top)


Usage

Module Setup

import (
    "time"

    "github.com/go-core-fx/httpfx"
    "go.uber.org/fx"
)

func main() {
    fx.New(
        fx.Provide(func() httpfx.Config {
            return httpfx.Config{
                ProxyURL: "socks5://127.0.0.1:1080",
                Bypass:   "localhost,127.0.0.1",
                Timeout:  30 * time.Second,
            }
        }),
        httpfx.Module(),
        // ... other modules
    ).Run()
}

The module provides both a default *http.Client and a Factory for creating additional clients.

Configuration Reference

Field Type Default Description
ProxyURL string "" SOCKS5 proxy URL (e.g. socks5://user:pass@host:port or socks5h://host:port).
Bypass string "" Comma-separated hosts to bypass the proxy (e.g. localhost,127.0.0.1).
Timeout time.Duration 0 Client-level request timeout. Zero means no timeout.
MaxIdleConns int 0 Maximum idle (keep-alive) connections. Zero means no limit.
MaxIdleConnsPerHost int 0 Maximum idle connections per host. Zero means Go default (2).
IdleConnTimeout time.Duration 0 Maximum time a connection stays idle. Zero means no timeout.
TLS.RootCAFile string "" Path to a PEM-encoded root CA file. Appended to the system pool unless replaced.
TLS.RootCAPEM string "" Inline PEM-encoded root CA data. Merged with TLS.RootCAFile when both are set.
TLS.RootCAReplaceSystem bool false When true, replace the system pool; only the configured root CAs are trusted.

When ProxyURL is empty, clients inherit the base transport's proxy behavior (by default http.DefaultTransport uses http.ProxyFromEnvironment, i.e. the host's proxy environment variables). Configure a socks5:// or socks5h:// URL to switch to a SOCKS5 dialer (which disables any inherited HTTP proxy); plain HTTP CONNECT proxies (http://proxy:8080) are not supported.

Platform note: append mode builds on x509.SystemCertPool(), which returns an empty pool on macOS/darwin (system roots load lazily at verify time), so append-mode behavior can differ by platform. Replace mode always trusts exactly the configured CAs.

Factory & Per-Client Options

Inject httpfx.Factory to create additional clients with shared base config but per-client overrides:

func Handler(f httpfx.Factory) error {
    // Default client — uses factory base config
    defaultClient, err := f.NewClient()
    if err != nil {
        return err
    }

    // Override timeout for a fast endpoint
    apiClient, err := f.NewClient(httpfx.WithTimeout(5 * time.Second))
    if err != nil {
        return err
    }

    // Disable proxy for internal service calls
    internalClient, err := f.NewClient(httpfx.WithProxyURL("", ""))
    if err != nil {
        return err
    }

    // Custom transport for a specific module
    uploadClient, err := f.NewClient(
        httpfx.WithTimeout(5 * time.Minute),
        httpfx.WithMaxIdleConns(10),
    )
    if err != nil {
        return err
    }

    _ = defaultClient
    _ = apiClient
    _ = internalClient
    _ = uploadClient

    return nil
}

Available Options

Option Description
WithProxyURL(url, bypass) Override SOCKS5 proxy URL and bypass list
WithTimeout(d) Override client timeout
WithMaxIdleConns(n) Override max idle connections
WithMaxIdleConnsPerHost(n) Override max idle connections per host
WithIdleConnTimeout(d) Override idle connection timeout
WithRootCAFile(path) Override root CA certificate file path
WithRootCAPEM(pem) Override inline PEM root CA data
WithRootCAReplaceSystem(v) Override system-pool replacement flag

Proxy Examples

All proxying goes through golang.org/x/net/proxy via an explicit socks5:// or socks5h:// URL. Plain HTTP CONNECT proxies (http://proxy:8080) are not supported.

SOCKS5 with authentication:

httpfx.Config{
    ProxyURL: "socks5://user:pass@127.0.0.1:1080",
}

SOCKS5 with bypass for local addresses and CIDR ranges:

httpfx.Config{
    ProxyURL: "socks5://127.0.0.1:1080",
    Bypass:   "localhost,127.0.0.1,192.168.0.0/16",
}

TLS & Root CA Examples

By default, clients trust the system certificate pool. To trust an internal or corporate CA, configure Config.TLS; configured CAs are appended to the system pool unless RootCAReplaceSystem is set.

Internal CA via file path (Config literal):

httpfx.Config{
    TLS: httpfx.TLSConfig{
        RootCAFile: "/etc/corp/root-ca.pem",
    },
}

Inline PEM data (merged with the file when both are set):

httpfx.Config{
    TLS: httpfx.TLSConfig{
        RootCAFile: "/etc/corp/root-ca.pem",
        RootCAPEM:  "<PEM-encoded certificate data>",
    },
}

Replace mode - trust ONLY the configured CAs (strict internal environments):

httpfx.Config{
    TLS: httpfx.TLSConfig{
        RootCAFile:          "/etc/corp/root-ca.pem",
        RootCAReplaceSystem: true,
    },
}

Same settings via Factory per-client options:

corpClient, err := f.NewClient(
    httpfx.WithRootCAFile("/etc/corp/root-ca.pem"),
)
if err != nil {
    return err
}

strictClient, err := f.NewClient(
    httpfx.WithRootCAPEM(pemData),
    httpfx.WithRootCAReplaceSystem(true),
)
if err != nil {
    return err
}

Notes:

  • Zero-value httpfx.Config{} keeps the default Go TLS behavior (system roots only).
  • Invalid CA configuration (missing file, invalid PEM) makes Factory.NewClient return an error; when clients are built through Module, application startup fails with that error.

(back to top)


Roadmap

  • SOCKS5 proxy support via golang.org/x/net/proxy
  • Per-host proxy bypass
  • Factory with per-client functional options
  • Transport tuning (idle connections, timeouts)
  • TLS configuration options

See the open issues for a full list of proposed features.

(back to top)


Contributing

Contributions are what make the open source community such an amazing place to learn, inspire, and create. Any contributions you make are greatly appreciated.

  1. Fork the Project
  2. Create your Feature Branch (git checkout -b feature/AmazingFeature)
  3. Commit your Changes (git commit -m 'Add some AmazingFeature')
  4. Push to the Branch (git push origin feature/AmazingFeature)
  5. Open a Pull Request

(back to top)


License

Distributed under the Apache License 2.0. See LICENSE for more information.

(back to top)


Acknowledgments

(back to top)

About

Uber Fx module for net/http.Client with SOCKS5 and HTTP proxy support via golang.org/x/net/proxy

Topics

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Contributors

Languages

Generated from go-core-fx/template