-
Notifications
You must be signed in to change notification settings - Fork 25
Creates the NormalizeAddr Func to Format IPv6 Addresses #157
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
Merged
Changes from 6 commits
Commits
Show all changes
11 commits
Select commit
Hold shift + click to select a range
f541e5b
create NormalizeAddr which accepts addresses and returns a formatted …
kheina d8d2dfe
add more tests and switch back to using url.Parse for better edge cas…
kheina 7217bad
update empty or invalid errors to just empty
kheina 7466b96
update NormalizeAddr func comment
kheina 24aa702
update file licenses
kheina ba4215f
comment typo
kheina ebe38e0
add additional rfc reference in comment, use loop instead of recursio…
kheina f985fe1
remove the commented vault tests
kheina 1eb90a9
remove net.SplitHostPort because it will parse anything into port as …
kheina b9faf19
add edge case for missing port values
kheina 25cf3e7
move NormalizeAddr from configutil to parseutil
kheina File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,106 @@ | ||
| // Copyright (c) HashiCorp, Inc. | ||
| // SPDX-License-Identifier: MPL-2.0 | ||
|
|
||
| package configutil | ||
|
|
||
| import ( | ||
| "fmt" | ||
| "net" | ||
| "net/url" | ||
| "strings" | ||
| ) | ||
|
|
||
| // general delimiters as defined in RFC-3986 §2.2 | ||
| // See: https://www.rfc-editor.org/rfc/rfc3986#section-2.2 | ||
| const genDelims = ":/?#[]@" | ||
|
|
||
| func normalizeHostPort(host string, port string, url bool) (string, error) { | ||
| if host == "" { | ||
| return "", fmt.Errorf("empty hostname") | ||
| } | ||
| if ip := net.ParseIP(host); ip != nil { | ||
| if url && ip.To4() == nil && port == "" { | ||
| // this is a unique case, host is ipv6 and requires brackets due to | ||
| // being part of a url, but they won't be added by net.JoinHostPort | ||
| // as there is no port | ||
|
kheina marked this conversation as resolved.
|
||
| return "[" + ip.String() + "]", nil | ||
| } | ||
| host = ip.String() | ||
| } else if strings.Contains(host, ":") { | ||
| // host is an invalid ipv6 literal. | ||
| // hosts cannot contain certain reserved characters, including ":" | ||
| // See: https://www.rfc-editor.org/rfc/rfc3986#section-3.2.2, | ||
| // https://www.rfc-editor.org/rfc/rfc3986#section-2.2 | ||
| return "", fmt.Errorf("host contains an invalid IPv6 literal") | ||
| } | ||
| if port == "" { | ||
| return host, nil | ||
| } | ||
| return net.JoinHostPort(host, port), nil | ||
| } | ||
|
|
||
| // NormalizeAddr takes an address as a string and returns a normalized copy. | ||
| // If the address is a URL, IP Address, or host:port address that includes an | ||
| // IPv6 address, the normalized copy will be conformant with RFC-5952 §4. If | ||
| // the address cannot be parsed, an error will be returned. | ||
| // | ||
| // There are two valid formats: | ||
| // | ||
| // - hosts: "host" | ||
| // - may be any of: IPv6 literal, IPv4 literal, dns name, or [sub]domain name | ||
| // - IPv6 literals are not required to be encapsulated within square brackets | ||
| // in this format | ||
| // | ||
| // - URIs: "[scheme://] [user@] host [:port] [/path] [?query] [#frag]" | ||
| // - format should conform with RFC-3986 §3 or else the returned address may | ||
| // be parsed and formatted incorrectly | ||
| // - hosts containing IPv6 literals MUST be encapsulated within square brackets, | ||
| // as defined in RFC-3986 §3.2.2 and RFC-5952 §6 | ||
| // - all non-host components are optional | ||
| // | ||
| // See: | ||
| // - https://www.rfc-editor.org/rfc/rfc5952#section-4 | ||
| // - https://www.rfc-editor.org/rfc/rfc3986#section-3 | ||
| func NormalizeAddr(address string) (string, error) { | ||
| if address == "" { | ||
| return "", fmt.Errorf("empty address") | ||
| } | ||
|
|
||
| if ip := net.ParseIP(address); ip != nil { | ||
| return ip.String(), nil | ||
| } | ||
|
|
||
| if strings.HasPrefix(address, "[") && strings.HasSuffix(address, "]") { | ||
| return NormalizeAddr(address[1 : len(address)-1]) | ||
|
kheina marked this conversation as resolved.
Outdated
|
||
| } | ||
|
|
||
| if host, port, err := net.SplitHostPort(address); err == nil { | ||
| return normalizeHostPort(host, port, false) | ||
| } | ||
|
|
||
| // if the provided address does not have a scheme provided, attempt to | ||
| // provide one and re-parse the result. this is done by looking for the | ||
| // first general delimiter and checking if it exists or if it's not a colon | ||
| // See: https://www.rfc-editor.org/rfc/rfc3986#section-3 | ||
| if idx := strings.IndexAny(address, genDelims); idx < 0 || address[idx] != ':' { | ||
| const scheme = "https://" | ||
| // attempt to parse it as a url, we only want to try this func when we | ||
| // know for sure it has a scheme, since it can parse ANYTHING, but then | ||
| // just puts it into u.Path without the scheme | ||
| if u, err := url.Parse(scheme + address); err == nil { | ||
| if u.Host, err = normalizeHostPort(u.Hostname(), u.Port(), true); err != nil { | ||
| return "", err | ||
| } | ||
| return strings.TrimPrefix(u.String(), scheme), nil | ||
| } | ||
| } else { | ||
| if u, err := url.Parse(address); err == nil { | ||
| if u.Host, err = normalizeHostPort(u.Hostname(), u.Port(), true); err != nil { | ||
| return "", err | ||
| } | ||
| return u.String(), nil | ||
| } | ||
| } | ||
|
|
||
| return "", fmt.Errorf("unable to normalize given address") | ||
| } | ||
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.