Repository: labstack/echo
File: echo.go (Go)

Code before:
	}

	// Execute chain
	if err := h(c); err != nil {
		e.HTTPErrorHandler(err, c)
	}

	// Release context
	e.pool.Put(c)
}

// Start starts an HTTP server.
func (e *Echo) Start(address string) error {
	e.Server.Addr = address
	return e.StartServer(e.Server)
}

// StartTLS starts an HTTPS server.
func (e *Echo) StartTLS(address string, certFile, keyFile string) (err error) {
	return e.StartTLSFromFile(address, certFile, keyFile, true)
}

// StartTLSFromFile starts an HTTPS server.
// If `fromFile` is `true`: `cert` and `key` are paths to files that contain the certificate and key.
// If `fromFile` is `false`: `cert` and `key` contain the certificate and key.
func (e *Echo) StartTLSFromFile(address string, cert, key string, fromFile bool) (err error) {
	if cert == "" || key == "" {
		return errors.New("invalid tls configuration")
	}

	s := e.TLSServer
	s.TLSConfig = new(tls.Config)
	s.TLSConfig.Certificates = make([]tls.Certificate, 1)
	if fromFile {
		s.TLSConfig.Certificates[0], err = tls.LoadX509KeyPair(cert, key)
	} else {
		s.TLSConfig.Certificates[0], err = tls.X509KeyPair([]byte(cert), []byte(key))
	}
	if err != nil {
		return err
	}

	return e.startTLS(address)
}

// StartAutoTLS starts an HTTPS server using certificates automatically installed from https://letsencrypt.org.
func (e *Echo) StartAutoTLS(address string) error {
	s := e.TLSServer
	s.TLSConfig = new(tls.Config)
	s.TLSConfig.GetCertificate = e.AutoTLSManager.GetCertificate
	return e.startTLS(address)

Review comment (suggestion):
The name is misleading. It loads either from file or from the strings provided.

It would be nice if we could avoid adding another method to start TLS... I generally avoid using `interface{}` as much as possible, but can't help wondering if it wouldn't be appropriate here. If we change the signature of `StartTLS()` to `StartTLS(address string, certFile, keyFile interface{})` then the callers could submit either `string` (which would mean path) or `[]byte` (which would mean key/cert content). It would be backward compatible, it would continue to accept strings as input. But it would also support the new feature. Thoughts @mbana @im-kulikov @vishr ?

Either way, this sounds like a very useful feature :-) Now one can feed it straight from AWS Parameter Store or from Vault :-) 

Code after:
			h = e.premiddleware[i](h)
		}
	}

	// Execute chain
	if err := h(c); err != nil {
		e.HTTPErrorHandler(err, c)
	}

	// Release context
	e.pool.Put(c)
}

// Start starts an HTTP server.
func (e *Echo) Start(address string) error {
	e.Server.Addr = address
	return e.StartServer(e.Server)
}

// StartTLS starts an HTTPS server.
// If `certFile` or `keyFile` is `string` the values are treated as file paths.
// If `certFile` or `keyFile` is `[]byte` the values are treated as the certificate or key as-is.
func (e *Echo) StartTLS(address string, certFile, keyFile interface{}) (err error) {
	var cert []byte
	if cert, err = filepathOrContent(certFile); err != nil {
		return
	}

	var key []byte
	if key, err = filepathOrContent(keyFile); err != nil {
		return
	}

	s := e.TLSServer
	s.TLSConfig = new(tls.Config)
	s.TLSConfig.Certificates = make([]tls.Certificate, 1)
	if s.TLSConfig.Certificates[0], err = tls.X509KeyPair(cert, key); err != nil {
		return
	}

	return e.startTLS(address)
}

func filepathOrContent(fileOrContent interface{}) (content []byte, err error) {
	switch v := fileOrContent.(type) {
	case string:
		return ioutil.ReadFile(v)
	case []byte:
		return v, nil
	default:
		return nil, ErrInvalidCertOrKeyType