Skip to content

Commit

Permalink
Fixed bug #687
Browse files Browse the repository at this point in the history
zip-based implementation of http.FileSystem did not have `http.File::Seek()`
implementation.
  • Loading branch information
kontsevoy committed Jan 4, 2017
1 parent 39c0a37 commit 33044f6
Show file tree
Hide file tree
Showing 5 changed files with 92 additions and 20 deletions.
2 changes: 1 addition & 1 deletion Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
# Naming convention:
# for stable releases we use "1.0.0" format
# for pre-releases, we use "1.0.0-beta.2" format
VERSION=1.3.1
VERSION=1.3.2

# These are standard autotools variables, don't change them please
BUILDDIR ?= build
Expand Down
3 changes: 3 additions & 0 deletions constants.go
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,9 @@ const (
// ComponentTunClient is a tunnel client
ComponentTunClient = "tunclient"

// DebugEnvVar tells tests to use verbose debug output
DebugEnvVar = "DEBUG"

// DefaultTimeout sets read and wrie timeouts for SSH server ops
DefaultTimeout time.Duration = 30 * time.Second

Expand Down
52 changes: 46 additions & 6 deletions lib/web/static.go
Original file line number Diff line number Diff line change
Expand Up @@ -28,13 +28,21 @@ import (
"strings"

log "github.com/Sirupsen/logrus"

"github.com/gravitational/teleport"
"github.com/gravitational/trace"

"github.com/kardianos/osext"
)

// relative path to static assets. this is useful during development.
var debugAssetsPath string

const (
webAssetsMissingError = "the teleport binary was built without web assets, try building with `make release`"
webAssetsReadError = "failure reading web assets from the binary"
)

// NewStaticFileSystem returns the initialized implementation of http.FileSystem
// interface which can be used to serve Teleport Proxy Web UI
//
Expand Down Expand Up @@ -71,8 +79,8 @@ func NewStaticFileSystem(debugMode bool) (http.FileSystem, error) {
// isDebugMode determines if teleport is running in a "debug" mode.
// It looks at DEBUG environment variable
func isDebugMode() bool {
v, err := strconv.ParseBool(os.Getenv("DEBUG"))
return v && err == nil
v, _ := strconv.ParseBool(os.Getenv(teleport.DebugEnvVar))
return v
}

// LoadWebResources returns a filesystem implementation compatible
Expand Down Expand Up @@ -107,7 +115,10 @@ func readZipArchive(archivePath string) (ResourceMap, error) {
// this often happens when teleport is launched without the web assets
// zip file attached to the binary. for launching it in such mode
// set DEBUG environment variable to 1
return nil, trace.NotFound("Failed reading web assets from the binary. %v", err)
if err == zip.ErrFormat {
return nil, trace.NotFound(webAssetsMissingError)
}
return nil, trace.NotFound("%s %v", webAssetsReadError, err)
}
entries := make(ResourceMap)
for _, file := range zreader.File {
Expand All @@ -127,14 +138,43 @@ func readZipArchive(archivePath string) (ResourceMap, error) {
type resource struct {
reader io.ReadCloser
file *zip.File
pos int64
}

func (rsc *resource) Read(p []byte) (n int, err error) {
return rsc.reader.Read(p)
n, err = rsc.reader.Read(p)
rsc.pos += int64(n)
return n, err
}

func (rsc *resource) Seek(offset int64, whence int) (int64, error) {
return offset, nil
var (
pos int64
err error
)
// zip.File does not support seeking. To implement Seek on top of it,
// we close the existing reader, re-open it, and read 'offset' bytes from
// the beginning
if err = rsc.reader.Close(); err != nil {
return 0, err
}
if rsc.reader, err = rsc.file.Open(); err != nil {
return 0, err
}
switch whence {
case io.SeekStart:
pos = offset
case io.SeekCurrent:
pos = rsc.pos + offset
case io.SeekEnd:
pos = int64(rsc.file.UncompressedSize64) + offset
}
if pos > 0 {
b := make([]byte, pos)
rsc.reader.Read(b)
}
rsc.pos = pos
return pos, nil
}

func (rsc *resource) Readdir(count int) ([]os.FileInfo, error) {
Expand Down Expand Up @@ -162,5 +202,5 @@ func (rm ResourceMap) Open(name string) (http.File, error) {
if err != nil {
return nil, trace.Wrap(err)
}
return &resource{reader, f}, nil
return &resource{reader, f, 0}, nil
}
53 changes: 41 additions & 12 deletions lib/web/static_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,9 +17,13 @@ limitations under the License.
package web

import (
"io"
"io/ioutil"
"net/http"
"os"

"github.com/gravitational/teleport"

"gopkg.in/check.v1"
)

Expand All @@ -34,39 +38,64 @@ func (s *StaticSuite) SetUpSuite(c *check.C) {

func (s *StaticSuite) TestDebugModeEnv(c *check.C) {
c.Assert(isDebugMode(), check.Equals, false)
os.Setenv("DEBUG", "no")
os.Setenv(teleport.DebugEnvVar, "no")
c.Assert(isDebugMode(), check.Equals, false)
os.Setenv("DEBUG", "0")
os.Setenv(teleport.DebugEnvVar, "0")
c.Assert(isDebugMode(), check.Equals, false)
os.Setenv("DEBUG", "1")
os.Setenv(teleport.DebugEnvVar, "1")
c.Assert(isDebugMode(), check.Equals, true)
os.Setenv("DEBUG", "true")
os.Setenv(teleport.DebugEnvVar, "true")
c.Assert(isDebugMode(), check.Equals, true)
}

func (s *StaticSuite) TestLocalFS(c *check.C) {
// load FS from the local
fs, err := NewStaticFileSystem(true)
c.Assert(err, check.IsNil)
c.Assert(fs, check.NotNil)

f, err := fs.Open("/index.html")
c.Assert(err, check.IsNil)
bytes, err := ioutil.ReadAll(f)
c.Assert(err, check.IsNil)
c.Assert(len(bytes) > 600, check.Equals, true)
c.Assert(f.Close(), check.IsNil)
checkFS(fs, c)
}

func (s *StaticSuite) TestZipFS(c *check.C) {
fs, err := readZipArchive("../../fixtures/assets.zip")
c.Assert(err, check.IsNil)
c.Assert(fs, check.NotNil)

checkFS(fs, c)
}

func checkFS(fs http.FileSystem, c *check.C) {
// test simple full read:
f, err := fs.Open("/index.html")
c.Assert(err, check.IsNil)
bytes, err := ioutil.ReadAll(f)
c.Assert(err, check.IsNil)
c.Assert(len(bytes) > 600, check.Equals, true)
c.Assert(len(bytes), check.Equals, 813)
c.Assert(f.Close(), check.IsNil)

// seek + read
f, err = fs.Open("/index.html")
c.Assert(err, check.IsNil)
defer f.Close()

n, err := f.Seek(10, io.SeekStart)
c.Assert(err, check.IsNil)
c.Assert(n, check.Equals, int64(10))

bytes, err = ioutil.ReadAll(f)
c.Assert(err, check.IsNil)
c.Assert(len(bytes), check.Equals, 803)

n, err = f.Seek(-50, io.SeekEnd)
c.Assert(err, check.IsNil)
bytes, err = ioutil.ReadAll(f)
c.Assert(err, check.IsNil)
c.Assert(len(bytes), check.Equals, 50)

f.Seek(-50, io.SeekEnd)
n, err = f.Seek(-50, io.SeekCurrent)
c.Assert(err, check.IsNil)
bytes, err = ioutil.ReadAll(f)
c.Assert(err, check.IsNil)
c.Assert(len(bytes), check.Equals, 100)
}
2 changes: 1 addition & 1 deletion version.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
package teleport

const (
Version = "1.3.1"
Version = "1.3.2"
)

var Gitref string

0 comments on commit 33044f6

Please sign in to comment.