Skip to content

Support plain-HTTP self-hosted forges - #147

Open
andrew wants to merge 1 commit into
mainfrom
http-scheme-support
Open

Support plain-HTTP self-hosted forges#147
andrew wants to merge 1 commit into
mainfrom
http-scheme-support

Conversation

@andrew

@andrew andrew commented Aug 11, 2026

Copy link
Copy Markdown
Contributor

Self-hosted Gitea/Forgejo instances on private networks are often served over plain HTTP (e.g. http://172.30.0.10:3000 inside a docker network). Every code path that turns a domain into an API base URL currently hardcodes https://, so there is no way to point forge at such an instance — even with the domain configured and a token stored, requests fail on TLS handshake.

This adds three ways to specify the scheme:

  • --host and FORGE_HOST accept a full URL (--host http://forgejo.local:3000). The scheme is used for the API base; the bare host:port is still what config lookups and the forge registry key on.
  • scheme = http under a [domain] section in config, settable via forge auth login --scheme http.
  • DetectForgeType and Client.RegisterDomain accept an optional http:///https:// prefix on their domain argument, so library callers and the CLI's probing fallback can pass the scheme through. Bare domains still default to https so existing callers are unaffected.

Precedence for the base URL scheme is --hostFORGE_HOST → config [domain] schemehttps, matching the existing host-resolution order.

--host and FORGE_HOST now accept a full http://host:port URL, and a
scheme = http key is accepted under [domain] in config (settable via
forge auth login --scheme). The API base URL is built from that scheme
instead of hardcoding https, so a local Forgejo/Gitea on a private IP
without TLS is reachable.

DetectForgeType and Client.RegisterDomain accept an optional scheme
prefix on the domain argument for the same reason; the bare host is
still used as the registry key.

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Pull request overview

This PR adds first-class support for self-hosted forges served over plain HTTP by allowing the scheme to be specified via CLI/env/config and by teaching the library’s detection/registration APIs to accept http:///https://-prefixed inputs while keeping registry/config keys as bare host[:port].

Changes:

  • Accept full URLs in --host / FORGE_HOST, preserve scheme for API base URL construction, and default to https otherwise.
  • Add per-domain scheme = http|https config support (including forge auth login --scheme ...) with tests.
  • Update library APIs (DetectForgeType, Client.RegisterDomain) to accept optional URL scheme prefixes and add tests.

Reviewed changes

Copilot reviewed 10 out of 10 changed files in this pull request and generated 4 comments.

Show a summary per file
File Description
README.md Documents scheme = http and using full URL for --host/FORGE_HOST.
internal/resolve/resolve.go Adds scheme-aware host handling and baseURLFor() scheme precedence logic.
internal/resolve/resolve_test.go Adds tests for scheme-aware host/env/config behavior and API base URL.
internal/config/config.go Introduces DomainSection.Scheme, parses scheme from config, extends SetDomain.
internal/config/config_test.go Adds tests for scheme persistence/validation.
internal/cli/root.go Updates --host help text to mention full URLs.
internal/cli/auth.go Adds --scheme flag to persist scheme into config.
forges_test.go Adds tests ensuring detection/registration preserve http:// URLs.
forge.go Adds normalizeBaseURL() and updates RegisterDomain() to accept scheme-prefixed inputs.
detect.go Updates detection to use normalizeBaseURL() so callers can pass http:// URLs.

💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

Comment thread forge.go
Comment on lines +134 to +145
// normalizeBaseURL accepts either a bare host[:port] or a full http(s) URL and
// returns (baseURL, host). A bare host is assumed https.
func normalizeBaseURL(s string) (baseURL, host string) {
s = strings.TrimRight(s, "/")
if h, ok := strings.CutPrefix(s, "http://"); ok {
return s, h
}
if h, ok := strings.CutPrefix(s, "https://"); ok {
return s, h
}
return "https://" + s, s
}
Comment on lines +64 to 74
// splitScheme splits a leading http:// or https:// off s and returns
// (scheme, host). If s has no scheme, scheme is "".
func splitScheme(s string) (scheme, host string) {
if h, ok := strings.CutPrefix(s, "http://"); ok {
return "http", strings.TrimRight(h, "/")
}
if h, ok := strings.CutPrefix(s, "https://"); ok {
return "https", strings.TrimRight(h, "/")
}
return "", strings.TrimRight(s, "/")
}
Comment thread internal/cli/auth.go
Comment on lines +73 to +75
if scheme != "" && scheme != "http" && scheme != "https" {
return fmt.Errorf("invalid --scheme %q: must be http or https", scheme)
}
Comment thread internal/config/config.go
Comment on lines +373 to +375
if scheme != "" {
sections[domain]["scheme"] = scheme
}
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.

2 participants