Commit 829a0f34 authored by Matthew Holt's avatar Matthew Holt

Preserve and clean up original host input in Caddyfile-JSON conversions

parent bb80f991
...@@ -28,7 +28,7 @@ func ToJSON(caddyfile []byte) ([]byte, error) { ...@@ -28,7 +28,7 @@ func ToJSON(caddyfile []byte) ([]byte, error) {
// Fill up host list // Fill up host list
for _, host := range sb.HostList() { for _, host := range sb.HostList() {
block.Hosts = append(block.Hosts, strings.TrimSuffix(host, ":")) block.Hosts = append(block.Hosts, standardizeScheme(host))
} }
// Extract directives deterministically by sorting them // Extract directives deterministically by sorting them
...@@ -62,7 +62,6 @@ func ToJSON(caddyfile []byte) ([]byte, error) { ...@@ -62,7 +62,6 @@ func ToJSON(caddyfile []byte) ([]byte, error) {
// but only one line at a time, to be used at the top-level of // but only one line at a time, to be used at the top-level of
// a server block only (where the first token on each line is a // a server block only (where the first token on each line is a
// directive) - not to be used at any other nesting level. // directive) - not to be used at any other nesting level.
// goes to end of line
func constructLine(d *parse.Dispenser) []interface{} { func constructLine(d *parse.Dispenser) []interface{} {
var args []interface{} var args []interface{}
...@@ -80,8 +79,8 @@ func constructLine(d *parse.Dispenser) []interface{} { ...@@ -80,8 +79,8 @@ func constructLine(d *parse.Dispenser) []interface{} {
} }
// constructBlock recursively processes tokens into a // constructBlock recursively processes tokens into a
// JSON-encodable structure. // JSON-encodable structure. To be used in a directive's
// goes to end of block // block. Goes to end of block.
func constructBlock(d *parse.Dispenser) [][]interface{} { func constructBlock(d *parse.Dispenser) [][]interface{} {
block := [][]interface{}{} block := [][]interface{}{}
...@@ -110,15 +109,10 @@ func FromJSON(jsonBytes []byte) ([]byte, error) { ...@@ -110,15 +109,10 @@ func FromJSON(jsonBytes []byte) ([]byte, error) {
result += "\n\n" result += "\n\n"
} }
for i, host := range sb.Hosts { for i, host := range sb.Hosts {
if hostname, port, err := net.SplitHostPort(host); err == nil {
if port == "http" || port == "https" {
host = port + "://" + hostname
}
}
if i > 0 { if i > 0 {
result += ", " result += ", "
} }
result += strings.TrimSuffix(host, ":") result += standardizeScheme(host)
} }
result += jsonToText(sb.Body, 1) result += jsonToText(sb.Body, 1)
} }
...@@ -170,6 +164,17 @@ func jsonToText(scope interface{}, depth int) string { ...@@ -170,6 +164,17 @@ func jsonToText(scope interface{}, depth int) string {
return result return result
} }
// standardizeScheme turns an address like host:https into https://host,
// or "host:" into "host".
func standardizeScheme(addr string) string {
if hostname, port, err := net.SplitHostPort(addr); err == nil {
if port == "http" || port == "https" {
addr = port + "://" + hostname
}
}
return strings.TrimSuffix(addr, ":")
}
// Caddyfile encapsulates a slice of ServerBlocks. // Caddyfile encapsulates a slice of ServerBlocks.
type Caddyfile []ServerBlock type Caddyfile []ServerBlock
......
...@@ -63,7 +63,7 @@ baz" ...@@ -63,7 +63,7 @@ baz"
{ // 8 { // 8
caddyfile: `http://host, https://host { caddyfile: `http://host, https://host {
}`, }`,
json: `[{"hosts":["host:http","host:https"],"body":[]}]`, // hosts in JSON are always host:port format (if port is specified), for consistency json: `[{"hosts":["http://host","https://host"],"body":[]}]`, // hosts in JSON are always host:port format (if port is specified), for consistency
}, },
{ // 9 { // 9
caddyfile: `host { caddyfile: `host {
...@@ -124,3 +124,38 @@ func TestFromJSON(t *testing.T) { ...@@ -124,3 +124,38 @@ func TestFromJSON(t *testing.T) {
} }
} }
} }
func TestStandardizeAddress(t *testing.T) {
// host:https should be converted to https://host
output, err := ToJSON([]byte(`host:https`))
if err != nil {
t.Fatal(err)
}
if expected, actual := `[{"hosts":["https://host"],"body":[]}]`, string(output); expected != actual {
t.Errorf("Expected:\n'%s'\nActual:\n'%s'", expected, actual)
}
output, err = FromJSON([]byte(`[{"hosts":["https://host"],"body":[]}]`))
if err != nil {
t.Fatal(err)
}
if expected, actual := "https://host {\n}", string(output); expected != actual {
t.Errorf("Expected:\n'%s'\nActual:\n'%s'", expected, actual)
}
// host: should be converted to just host
output, err = ToJSON([]byte(`host:`))
if err != nil {
t.Fatal(err)
}
if expected, actual := `[{"hosts":["host"],"body":[]}]`, string(output); expected != actual {
t.Errorf("Expected:\n'%s'\nActual:\n'%s'", expected, actual)
}
output, err = FromJSON([]byte(`[{"hosts":["host:"],"body":[]}]`))
if err != nil {
t.Fatal(err)
}
if expected, actual := "host {\n}", string(output); expected != actual {
t.Errorf("Expected:\n'%s'\nActual:\n'%s'", expected, actual)
}
}
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment