Пример #1
0
// ToJSON converts caddyfile to its JSON representation.
func ToJSON(caddyfile []byte) ([]byte, error) {
	var j Caddyfile

	serverBlocks, err := parse.ServerBlocks(filename, bytes.NewReader(caddyfile), false)
	if err != nil {
		return nil, err
	}

	for _, sb := range serverBlocks {
		block := ServerBlock{Body: make(map[string]interface{})}

		for _, host := range sb.HostList() {
			block.Hosts = append(block.Hosts, strings.TrimSuffix(host, ":"))
		}

		for dir, tokens := range sb.Tokens {
			disp := parse.NewDispenserTokens(filename, tokens)
			disp.Next() // the first token is the directive; skip it
			block.Body[dir] = constructLine(disp)
		}

		j = append(j, block)
	}

	result, err := json.Marshal(j)
	if err != nil {
		return nil, err
	}

	return result, nil
}
Пример #2
0
// ToJSON converts caddyfile to its JSON representation.
func ToJSON(caddyfile []byte) ([]byte, error) {
	var j Caddyfile

	serverBlocks, err := parse.ServerBlocks(filename, bytes.NewReader(caddyfile), false)
	if err != nil {
		return nil, err
	}

	for _, sb := range serverBlocks {
		block := ServerBlock{Body: [][]interface{}{}}

		// Fill up host list
		for _, host := range sb.HostList() {
			block.Hosts = append(block.Hosts, standardizeScheme(host))
		}

		// Extract directives deterministically by sorting them
		var directives = make([]string, len(sb.Tokens))
		for dir := range sb.Tokens {
			directives = append(directives, dir)
		}
		sort.Strings(directives)

		// Convert each directive's tokens into our JSON structure
		for _, dir := range directives {
			disp := parse.NewDispenserTokens(filename, sb.Tokens[dir])
			for disp.Next() {
				block.Body = append(block.Body, constructLine(&disp))
			}
		}

		// tack this block onto the end of the list
		j = append(j, block)
	}

	result, err := json.Marshal(j)
	if err != nil {
		return nil, err
	}

	return result, nil
}
Пример #3
0
// loadConfigsUpToIncludingTLS loads the configs from input with name filename and returns them,
// the parsed server blocks, the index of the last directive it processed, and an error (if any).
func loadConfigsUpToIncludingTLS(filename string, input io.Reader) ([]server.Config, []parse.ServerBlock, int, error) {
	var configs []server.Config

	// Each server block represents similar hosts/addresses, since they
	// were grouped together in the Caddyfile.
	serverBlocks, err := parse.ServerBlocks(filename, input, true)
	if err != nil {
		return nil, nil, 0, err
	}
	if len(serverBlocks) == 0 {
		newInput := DefaultInput()
		serverBlocks, err = parse.ServerBlocks(newInput.Path(), bytes.NewReader(newInput.Body()), true)
		if err != nil {
			return nil, nil, 0, err
		}
	}

	var lastDirectiveIndex int // we set up directives in two parts; this stores where we left off

	// Iterate each server block and make a config for each one,
	// executing the directives that were parsed in order up to the tls
	// directive; this is because we must activate Let's Encrypt.
	for i, sb := range serverBlocks {
		onces := makeOnces()
		storages := makeStorages()

		for j, addr := range sb.Addresses {
			config := server.Config{
				Host:       addr.Host,
				Port:       addr.Port,
				Scheme:     addr.Scheme,
				Root:       Root,
				Middleware: make(map[string][]middleware.Middleware),
				ConfigFile: filename,
				AppName:    AppName,
				AppVersion: AppVersion,
			}

			// It is crucial that directives are executed in the proper order.
			for k, dir := range directiveOrder {
				// Execute directive if it is in the server block
				if tokens, ok := sb.Tokens[dir.name]; ok {
					// Each setup function gets a controller, from which setup functions
					// get access to the config, tokens, and other state information useful
					// to set up its own host only.
					controller := &setup.Controller{
						Config:    &config,
						Dispenser: parse.NewDispenserTokens(filename, tokens),
						OncePerServerBlock: func(f func() error) error {
							var err error
							onces[dir.name].Do(func() {
								err = f()
							})
							return err
						},
						ServerBlockIndex:     i,
						ServerBlockHostIndex: j,
						ServerBlockHosts:     sb.HostList(),
						ServerBlockStorage:   storages[dir.name],
					}
					// execute setup function and append middleware handler, if any
					midware, err := dir.setup(controller)
					if err != nil {
						return nil, nil, lastDirectiveIndex, err
					}
					if midware != nil {
						// TODO: For now, we only support the default path scope /
						config.Middleware["/"] = append(config.Middleware["/"], midware)
					}
					storages[dir.name] = controller.ServerBlockStorage // persist for this server block
				}

				// Stop after TLS setup, since we need to activate Let's Encrypt before continuing;
				// it makes some changes to the configs that middlewares might want to know about.
				if dir.name == "tls" {
					lastDirectiveIndex = k
					break
				}
			}

			configs = append(configs, config)
		}
	}

	return configs, serverBlocks, lastDirectiveIndex, nil
}
Пример #4
0
// loadConfigs reads input (named filename) and parses it, returning the
// server configurations in the order they appeared in the input. As part
// of this, it activates Let's Encrypt for the configs that are produced.
// Thus, the returned configs are already optimally configured optimally
// for HTTPS.
func loadConfigs(filename string, input io.Reader) ([]server.Config, error) {
	var configs []server.Config

	// Each server block represents similar hosts/addresses, since they
	// were grouped together in the Caddyfile.
	serverBlocks, err := parse.ServerBlocks(filename, input, true)
	if err != nil {
		return nil, err
	}
	if len(serverBlocks) == 0 {
		newInput := DefaultInput()
		serverBlocks, err = parse.ServerBlocks(newInput.Path(), bytes.NewReader(newInput.Body()), true)
		if err != nil {
			return nil, err
		}
	}

	var lastDirectiveIndex int // we set up directives in two parts; this stores where we left off

	// Iterate each server block and make a config for each one,
	// executing the directives that were parsed in order up to the tls
	// directive; this is because we must activate Let's Encrypt.
	for i, sb := range serverBlocks {
		onces := makeOnces()
		storages := makeStorages()

		for j, addr := range sb.Addresses {
			config := server.Config{
				Host:       addr.Host,
				Port:       addr.Port,
				Root:       Root,
				Middleware: make(map[string][]middleware.Middleware),
				ConfigFile: filename,
				AppName:    AppName,
				AppVersion: AppVersion,
			}

			// It is crucial that directives are executed in the proper order.
			for k, dir := range directiveOrder {
				// Execute directive if it is in the server block
				if tokens, ok := sb.Tokens[dir.name]; ok {
					// Each setup function gets a controller, from which setup functions
					// get access to the config, tokens, and other state information useful
					// to set up its own host only.
					controller := &setup.Controller{
						Config:    &config,
						Dispenser: parse.NewDispenserTokens(filename, tokens),
						OncePerServerBlock: func(f func() error) error {
							var err error
							onces[dir.name].Do(func() {
								err = f()
							})
							return err
						},
						ServerBlockIndex:     i,
						ServerBlockHostIndex: j,
						ServerBlockHosts:     sb.HostList(),
						ServerBlockStorage:   storages[dir.name],
					}
					// execute setup function and append middleware handler, if any
					midware, err := dir.setup(controller)
					if err != nil {
						return nil, err
					}
					if midware != nil {
						// TODO: For now, we only support the default path scope /
						config.Middleware["/"] = append(config.Middleware["/"], midware)
					}
					storages[dir.name] = controller.ServerBlockStorage // persist for this server block
				}

				// Stop after TLS setup, since we need to activate Let's Encrypt before continuing;
				// it makes some changes to the configs that middlewares might want to know about.
				if dir.name == "tls" {
					lastDirectiveIndex = k
					break
				}
			}

			configs = append(configs, config)
		}
	}

	// Now we have all the configs, but they have only been set up to the
	// point of tls. We need to activate Let's Encrypt before setting up
	// the rest of the middlewares so they have correct information regarding
	// TLS configuration, if necessary. (this call is append-only, so our
	// iterations below shouldn't be affected)
	if !IsRestart() && !Quiet {
		fmt.Print("Activating privacy features...")
	}
	configs, err = letsencrypt.Activate(configs)
	if err != nil {
		if !Quiet {
			fmt.Println()
		}
		return nil, err
	}
	if !IsRestart() && !Quiet {
		fmt.Println(" done.")
	}

	// Finish setting up the rest of the directives, now that TLS is
	// optimally configured. These loops are similar to above except
	// we don't iterate all the directives from the beginning and we
	// don't create new configs.
	configIndex := -1
	for i, sb := range serverBlocks {
		onces := makeOnces()
		storages := makeStorages()

		for j := range sb.Addresses {
			configIndex++

			for k := lastDirectiveIndex + 1; k < len(directiveOrder); k++ {
				dir := directiveOrder[k]

				if tokens, ok := sb.Tokens[dir.name]; ok {
					controller := &setup.Controller{
						Config:    &configs[configIndex],
						Dispenser: parse.NewDispenserTokens(filename, tokens),
						OncePerServerBlock: func(f func() error) error {
							var err error
							onces[dir.name].Do(func() {
								err = f()
							})
							return err
						},
						ServerBlockIndex:     i,
						ServerBlockHostIndex: j,
						ServerBlockHosts:     sb.HostList(),
						ServerBlockStorage:   storages[dir.name],
					}
					midware, err := dir.setup(controller)
					if err != nil {
						return nil, err
					}
					if midware != nil {
						// TODO: For now, we only support the default path scope /
						configs[configIndex].Middleware["/"] = append(configs[configIndex].Middleware["/"], midware)
					}
					storages[dir.name] = controller.ServerBlockStorage // persist for this server block
				}
			}
		}
	}

	return configs, nil
}