Skip to content

Commit

Permalink
fix: slash handling for static files (replaces pull/27)
Browse files Browse the repository at this point in the history
  • Loading branch information
reddec committed Dec 29, 2023
1 parent 5931b31 commit d2e405c
Show file tree
Hide file tree
Showing 2 changed files with 79 additions and 4 deletions.
10 changes: 8 additions & 2 deletions application/lambda/lambda.go
Original file line number Diff line number Diff line change
Expand Up @@ -67,8 +67,7 @@ func (local *localLambda) Invoke(ctx context.Context, request types.Request, res
defer request.Body.Close()

if local.staticDir != "" && request.Method == http.MethodGet {
path := strings.SplitN(request.Path, "/", 2)[1]
return local.writeStaticFile(path, response)
return local.serveStaticFile(request, response)
}

if len(local.manifest.Run) == 0 {
Expand Down Expand Up @@ -125,6 +124,13 @@ func (local *localLambda) Invoke(ctx context.Context, request types.Request, res
return nil
}

func (local *localLambda) serveStaticFile(request types.Request, response io.Writer) error {
// poor man path trimming
// trailing slash always removed (later replaced by index.html)
_, file, _ := strings.Cut(strings.Trim(request.Path, "/"), "/")
return local.writeStaticFile(file, response)
}

func (local *localLambda) Remove() error {
return os.RemoveAll(local.rootDir)
}
Expand Down
73 changes: 71 additions & 2 deletions application/lambda/lambda_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,13 +4,18 @@ import (
"archive/tar"
"bytes"
"context"
"github.com/reddec/trusted-cgi/types"
"github.com/stretchr/testify/assert"
"io"
"io/ioutil"
"net/http"
"os"
"path/filepath"
"testing"
"time"

"github.com/reddec/trusted-cgi/application"
"github.com/reddec/trusted-cgi/types"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
)

func Test_tar(t *testing.T) {
Expand Down Expand Up @@ -134,3 +139,67 @@ func TestLocalLambda_Invoke(t *testing.T) {

assert.Equal(t, "hello world", out.String())
}

func TestStaticFile(t *testing.T) {
d, err := os.MkdirTemp("", "test-lambda-*")
require.NoError(t, err)
defer os.RemoveAll(d)

require.NoError(t, os.Mkdir(filepath.Join(d, "static"), 0755))
require.NoError(t, os.WriteFile(filepath.Join(d, "static", "index.html"), []byte("index page"), 0755))
require.NoError(t, os.WriteFile(filepath.Join(d, "static", "root"), []byte("root page"), 0755))
require.NoError(t, os.Mkdir(filepath.Join(d, "static", "foo"), 0755))
require.NoError(t, os.WriteFile(filepath.Join(d, "static", "foo", "foo"), []byte("foo page"), 0755))
require.NoError(t, os.Mkdir(filepath.Join(d, "static", "foo", "bar"), 0755))
require.NoError(t, os.WriteFile(filepath.Join(d, "static", "foo", "bar", "bar"), []byte("bar page"), 0755))

fn, err := DummyPublic(d, "cat", "-")
require.NoError(t, err)

manifest := fn.Manifest()
manifest.Static = "static"
require.NoError(t, fn.SetManifest(manifest))
require.NoError(t, fn.reindex()) // fixme: usage of private API

t.Run("index served", func(t *testing.T) {
content, err := testRequest(fn, http.MethodGet, "/f/", nil)
require.NoError(t, err)
assert.Equal(t, "index page", string(content))
})

t.Run("index served even without slash", func(t *testing.T) {
content, err := testRequest(fn, http.MethodGet, "/f", nil)
require.NoError(t, err)
assert.Equal(t, "index page", string(content))
})

t.Run("root path served", func(t *testing.T) {
content, err := testRequest(fn, http.MethodGet, "/f/root", nil)
require.NoError(t, err)
assert.Equal(t, "root page", string(content))
})

t.Run("sub path served", func(t *testing.T) {
content, err := testRequest(fn, http.MethodGet, "/f/foo/foo", nil)
require.NoError(t, err)
assert.Equal(t, "foo page", string(content))
})
t.Run("sub sub path served", func(t *testing.T) {
content, err := testRequest(fn, http.MethodGet, "/f/foo/bar/bar", nil)
require.NoError(t, err)
assert.Equal(t, "bar page", string(content))
})
}

func testRequest(fn application.Invokable, method string, path string, payload []byte) ([]byte, error) {
timeout, cancel := context.WithTimeout(context.Background(), 1*time.Second)
defer cancel()

var out bytes.Buffer
err := fn.Invoke(timeout, types.Request{
Method: method,
Path: path,
Body: io.NopCloser(bytes.NewReader(payload)),
}, &out, nil)
return out.Bytes(), err
}

0 comments on commit d2e405c

Please sign in to comment.