Skip to content

Commit

Permalink
Serve and redirect index pages like http.FileServer (#10)
Browse files Browse the repository at this point in the history
  • Loading branch information
vearutop authored Sep 13, 2021
1 parent c78f450 commit ad1db1d
Show file tree
Hide file tree
Showing 12 changed files with 241 additions and 15 deletions.
16 changes: 14 additions & 2 deletions .github/workflows/bench.yml
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ jobs:
bench:
strategy:
matrix:
go-version: [ 1.16.x ]
go-version: [ 1.17.x ]
runs-on: ubuntu-latest
steps:
- name: Install Go
Expand Down Expand Up @@ -74,7 +74,12 @@ jobs:
id: bench
run: |
export REF_NAME=new
BENCH_COUNT=5 make bench-run bench-stat
BENCH_COUNT=5 make bench
OUTPUT=$(make bench-stat-diff)
OUTPUT="${OUTPUT//'%'/'%25'}"
OUTPUT="${OUTPUT//$'\n'/'%0A'}"
OUTPUT="${OUTPUT//$'\r'/'%0D'}"
echo "::set-output name=diff::$OUTPUT"
OUTPUT=$(make bench-stat)
OUTPUT="${OUTPUT//'%'/'%25'}"
OUTPUT="${OUTPUT//$'\n'/'%0A'}"
Expand All @@ -89,6 +94,13 @@ jobs:
### Benchmark Result
<details><summary>Benchmark diff with base branch</summary>
```
${{ steps.bench.outputs.diff }}
```
</details>
<details><summary>Benchmark result</summary>
```
${{ steps.bench.outputs.result }}
```
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/golangci-lint.yml
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ jobs:
uses: golangci/[email protected]
with:
# Required: the version of golangci-lint is required and must be specified without patch version: we always use the latest patch version.
version: v1.40.1
version: v1.41.1

# Optional: working directory, useful for monorepos
# working-directory: somedir
Expand Down
45 changes: 45 additions & 0 deletions .github/workflows/gorelease.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
# This script is provided by github.com/bool64/dev.
name: gorelease
on:
pull_request:
env:
GO111MODULE: "on"
jobs:
gorelease:
strategy:
matrix:
go-version: [ 1.17.x ]
runs-on: ubuntu-latest
steps:
- name: Install Go
uses: actions/setup-go@v2
with:
go-version: ${{ matrix.go-version }}
- name: Checkout code
uses: actions/checkout@v2
- name: Gorelease cache
uses: actions/cache@v2
with:
path: |
~/go/bin/gorelease
key: ${{ runner.os }}-gorelease
- name: Gorelease
id: gorelease
run: |
test -e ~/go/bin/gorelease || go install golang.org/x/exp/cmd/gorelease@latest
OUTPUT=$(gorelease || exit 0)
OUTPUT="${OUTPUT//'%'/'%25'}"
OUTPUT="${OUTPUT//$'\n'/'%0A'}"
OUTPUT="${OUTPUT//$'\r'/'%0D'}"
echo "::set-output name=report::$OUTPUT"
- name: Comment Report
uses: marocchino/sticky-pull-request-comment@v2
with:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
header: gorelease
message: |
### API Changes
<pre>
${{ steps.gorelease.outputs.report }}
</pre>
12 changes: 6 additions & 6 deletions .github/workflows/test-unit.yml
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ jobs:
test:
strategy:
matrix:
go-version: [ 1.16.x ]
go-version: [ 1.16.x, 1.17.x ]
runs-on: ubuntu-latest
steps:
- name: Install Go
Expand All @@ -35,21 +35,21 @@ jobs:
restore-keys: |
${{ runner.os }}-go-cache
- name: Restore base test coverage
if: matrix.go-version == '1.16.x'
if: matrix.go-version == '1.17.x'
uses: actions/cache@v2
with:
path: |
unit-base.txt
# Use base sha for PR or new commit hash for master/main push in test result key.
key: ${{ runner.os }}-unit-test-coverage-${{ (github.event.pull_request.base.sha != github.event.after) && github.event.pull_request.base.sha || github.event.after }}
- name: Checkout base code
if: matrix.go-version == '1.16.x' && env.RUN_BASE_COVERAGE == 'on' && steps.benchmark-base.outputs.cache-hit != 'true' && github.event.pull_request.base.sha != ''
if: matrix.go-version == '1.17.x' && env.RUN_BASE_COVERAGE == 'on' && steps.benchmark-base.outputs.cache-hit != 'true' && github.event.pull_request.base.sha != ''
uses: actions/checkout@v2
with:
ref: ${{ github.event.pull_request.base.sha }}
path: __base
- name: Run test for base code
if: matrix.go-version == '1.16.x' && env.RUN_BASE_COVERAGE == 'on' && steps.benchmark-base.outputs.cache-hit != 'true' && github.event.pull_request.base.sha != ''
if: matrix.go-version == '1.17.x' && env.RUN_BASE_COVERAGE == 'on' && steps.benchmark-base.outputs.cache-hit != 'true' && github.event.pull_request.base.sha != ''
run: |
cd __base
make | grep test-unit && (make test-unit && go tool cover -func=./unit.coverprofile | sed -e 's/.go:[0-9]*:\t/.go\t/g' | sed -e 's/\t\t*/\t/g' > ../unit-base.txt) || echo "No test-unit in base"
Expand All @@ -69,7 +69,7 @@ jobs:
if: ${{ github.ref == 'refs/heads/master' || github.ref == 'refs/heads/main' }}
run: cp unit.txt unit-base.txt
- name: Comment Test Coverage
if: matrix.go-version == '1.16.x'
if: matrix.go-version == '1.17.x'
uses: marocchino/sticky-pull-request-comment@v2
with:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
Expand All @@ -85,7 +85,7 @@ jobs:
</details>
- name: Upload code coverage
if: matrix.go-version == '1.16.x'
if: matrix.go-version == '1.17.x'
uses: codecov/codecov-action@v1
with:
file: ./unit.coverprofile
Expand Down
4 changes: 3 additions & 1 deletion .golangci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,9 @@ linters-settings:
unparam:
check-exported: true
cyclop:
max-complexity: 12
max-complexity: 14
funlen:
lines: 65

linters:
enable-all: true
Expand Down
2 changes: 1 addition & 1 deletion Makefile
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
#GOLANGCI_LINT_VERSION := "v1.40.1" # Optional configuration to pinpoint golangci-lint version.
#GOLANGCI_LINT_VERSION := "v1.41.1" # Optional configuration to pinpoint golangci-lint version.

# The head of Makefile determines location of dev-go to include standard targets.
GO ?= go
Expand Down
1 change: 1 addition & 0 deletions _testdata/index.html
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Hello, uncompressed!
Binary file added _testdata/index.html.gz
Binary file not shown.
2 changes: 1 addition & 1 deletion go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,6 @@ go 1.16

require (
github.com/andybalholm/brotli v1.0.3
github.com/bool64/dev v0.1.35
github.com/bool64/dev v0.1.41
github.com/stretchr/testify v1.4.0
)
4 changes: 2 additions & 2 deletions go.sum
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
github.com/andybalholm/brotli v1.0.3 h1:fpcw+r1N1h0Poc1F/pHbW40cUm/lMEQslZtCkBQ0UnM=
github.com/andybalholm/brotli v1.0.3/go.mod h1:fO7iG3H7G2nSZ7m0zPUDn85XEX2GTukHGRSepvi9Eig=
github.com/bool64/dev v0.1.35 h1:uouBAq2kAJ+k9UypYRs118bAYttNQWDyK4IzjfLb5fc=
github.com/bool64/dev v0.1.35/go.mod h1:cTHiTDNc8EewrQPy3p1obNilpMpdmlUesDkFTF2zRWU=
github.com/bool64/dev v0.1.41 h1:L554LCQZc3d7mtcdPUgDbSrCVbr48/30zgu0VuC/FTA=
github.com/bool64/dev v0.1.41/go.mod h1:cTHiTDNc8EewrQPy3p1obNilpMpdmlUesDkFTF2zRWU=
github.com/davecgh/go-spew v1.1.0 h1:ZDRjVQ15GmhC3fiQ8ni8+OwkZQO4DARzQgrnXU1Liz8=
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
Expand Down
40 changes: 39 additions & 1 deletion server.go
Original file line number Diff line number Diff line change
Expand Up @@ -163,6 +163,10 @@ func (s *Server) hashDir(p string) error {
fn := path.Join(p, f.Name())

if f.IsDir() {
s.info[path.Clean(fn)] = fileInfo{
isDir: true,
}

if err = s.hashDir(fn); err != nil {
return err
}
Expand Down Expand Up @@ -284,6 +288,10 @@ func (s *Server) minEnc(accessEncoding string, fn string) (fileInfo, Encoding) {
}

// ServeHTTP serves static files.
//
// For compatibility with std http.FileServer:
// if request path ends with /index.html, it is redirected to base directory;
// if request path points to a directory without trailing "/", it is redirected to a path with trailing "/".
func (s *Server) ServeHTTP(rw http.ResponseWriter, req *http.Request) {
if req.Method != http.MethodGet && req.Method != http.MethodHead {
rw.Header().Set("Allow", http.MethodGet+", "+http.MethodHead)
Expand All @@ -292,9 +300,25 @@ func (s *Server) ServeHTTP(rw http.ResponseWriter, req *http.Request) {
return
}

if strings.HasSuffix(req.URL.Path, "/index.html") {
localRedirect(rw, req, "./")

return
}

fn := strings.TrimPrefix(req.URL.Path, "/")
ae := req.Header.Get("Accept-Encoding")

if s.info[fn].isDir {
localRedirect(rw, req, path.Base(req.URL.Path)+"/")

return
}

if fn == "" || strings.HasSuffix(fn, "/") {
fn += "index.html"
}

// Always add Accept-Encoding to Vary to prevent intermediate caches corruption.
rw.Header().Add("Vary", "Accept-Encoding")

Expand All @@ -320,7 +344,7 @@ func (s *Server) ServeHTTP(rw http.ResponseWriter, req *http.Request) {
// Decompress compressed data into response.
for _, enc := range s.Encodings {
info, found := s.info[fn+enc.FileExt]
if !found || enc.Decoder == nil {
if !found || enc.Decoder == nil || info.isDir {
continue
}

Expand Down Expand Up @@ -355,6 +379,7 @@ type fileInfo struct {
hash string
size int
content []byte
isDir bool
}

// OnError is an option to customize error handling in Server.
Expand Down Expand Up @@ -397,3 +422,16 @@ func GzipEncoding() Encoding {
func EncodeOnInit(server *Server) {
server.EncodeOnInit = true
}

// localRedirect gives a Moved Permanently response.
// It does not convert relative paths to absolute paths like Redirect does.
//
// Copied go1.17/src/net/http/fs.go:685.
func localRedirect(w http.ResponseWriter, r *http.Request, newPath string) {
if q := r.URL.RawQuery; q != "" {
newPath += "?" + q
}

w.Header().Set("Location", newPath)
w.WriteHeader(http.StatusMovedPermanently)
}
Loading

0 comments on commit ad1db1d

Please sign in to comment.