Skip to content

Commit 8716acb

Browse files
mbanavishr
authored andcommitted
Echo.StartTLS: accept string or []byte as parameters. (#1277)
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.
1 parent 3d73323 commit 8716acb

File tree

2 files changed

+94
-5
lines changed

2 files changed

+94
-5
lines changed

echo.go

Lines changed: 27 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,7 @@ import (
4343
"errors"
4444
"fmt"
4545
"io"
46+
"io/ioutil"
4647
stdLog "log"
4748
"net"
4849
"net/http"
@@ -269,6 +270,7 @@ var (
269270
ErrRendererNotRegistered = errors.New("renderer not registered")
270271
ErrInvalidRedirectCode = errors.New("invalid redirect status code")
271272
ErrCookieNotFound = errors.New("cookie not found")
273+
ErrInvalidCertOrKeyType = errors.New("invalid cert or key type, must be string or []byte")
272274
)
273275

274276
// Error handlers
@@ -605,20 +607,40 @@ func (e *Echo) Start(address string) error {
605607
}
606608

607609
// StartTLS starts an HTTPS server.
608-
func (e *Echo) StartTLS(address string, certFile, keyFile string) (err error) {
609-
if certFile == "" || keyFile == "" {
610-
return errors.New("invalid tls configuration")
610+
// If `certFile` or `keyFile` is `string` the values are treated as file paths.
611+
// If `certFile` or `keyFile` is `[]byte` the values are treated as the certificate or key as-is.
612+
func (e *Echo) StartTLS(address string, certFile, keyFile interface{}) (err error) {
613+
var cert []byte
614+
if cert, err = filepathOrContent(certFile); err != nil {
615+
return
611616
}
617+
618+
var key []byte
619+
if key, err = filepathOrContent(keyFile); err != nil {
620+
return
621+
}
622+
612623
s := e.TLSServer
613624
s.TLSConfig = new(tls.Config)
614625
s.TLSConfig.Certificates = make([]tls.Certificate, 1)
615-
s.TLSConfig.Certificates[0], err = tls.LoadX509KeyPair(certFile, keyFile)
616-
if err != nil {
626+
if s.TLSConfig.Certificates[0], err = tls.X509KeyPair(cert, key); err != nil {
617627
return
618628
}
629+
619630
return e.startTLS(address)
620631
}
621632

633+
func filepathOrContent(fileOrContent interface{}) (content []byte, err error) {
634+
switch v := fileOrContent.(type) {
635+
case string:
636+
return ioutil.ReadFile(v)
637+
case []byte:
638+
return v, nil
639+
default:
640+
return nil, ErrInvalidCertOrKeyType
641+
}
642+
}
643+
622644
// StartAutoTLS starts an HTTPS server using certificates automatically installed from https://letsencrypt.org.
623645
func (e *Echo) StartAutoTLS(address string) error {
624646
s := e.TLSServer

echo_test.go

Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import (
44
"bytes"
55
stdContext "context"
66
"errors"
7+
"io/ioutil"
78
"net/http"
89
"net/http/httptest"
910
"reflect"
@@ -12,6 +13,7 @@ import (
1213
"time"
1314

1415
"github.com/stretchr/testify/assert"
16+
"github.com/stretchr/testify/require"
1517
)
1618

1719
type (
@@ -428,6 +430,71 @@ func TestEchoStartTLS(t *testing.T) {
428430
e.Close()
429431
}
430432

433+
func TestEchoStartTLSByteString(t *testing.T) {
434+
cert, err := ioutil.ReadFile("_fixture/certs/cert.pem")
435+
require.NoError(t, err)
436+
key, err := ioutil.ReadFile("_fixture/certs/key.pem")
437+
require.NoError(t, err)
438+
439+
testCases := []struct {
440+
cert interface{}
441+
key interface{}
442+
expectedErr error
443+
name string
444+
}{
445+
{
446+
cert: "_fixture/certs/cert.pem",
447+
key: "_fixture/certs/key.pem",
448+
expectedErr: nil,
449+
name: `ValidCertAndKeyFilePath`,
450+
},
451+
{
452+
cert: cert,
453+
key: key,
454+
expectedErr: nil,
455+
name: `ValidCertAndKeyByteString`,
456+
},
457+
{
458+
cert: cert,
459+
key: 1,
460+
expectedErr: ErrInvalidCertOrKeyType,
461+
name: `InvalidKeyType`,
462+
},
463+
{
464+
cert: 0,
465+
key: key,
466+
expectedErr: ErrInvalidCertOrKeyType,
467+
name: `InvalidCertType`,
468+
},
469+
{
470+
cert: 0,
471+
key: 1,
472+
expectedErr: ErrInvalidCertOrKeyType,
473+
name: `InvalidCertAndKeyTypes`,
474+
},
475+
}
476+
477+
for _, test := range testCases {
478+
test := test
479+
t.Run(test.name, func(t *testing.T) {
480+
e := New()
481+
e.HideBanner = true
482+
483+
go func() {
484+
err := e.StartTLS(":0", test.cert, test.key)
485+
if test.expectedErr != nil {
486+
require.EqualError(t, err, test.expectedErr.Error())
487+
} else if err != http.ErrServerClosed { // Prevent the test to fail after closing the servers
488+
require.NoError(t, err)
489+
}
490+
}()
491+
time.Sleep(200 * time.Millisecond)
492+
493+
require.NoError(t, e.Close())
494+
})
495+
}
496+
}
497+
431498
func TestEchoStartAutoTLS(t *testing.T) {
432499
e := New()
433500
errChan := make(chan error, 0)

0 commit comments

Comments
 (0)