Skip to content

Commit

Permalink
Merge pull request #7 from plan97/dev
Browse files Browse the repository at this point in the history
Refactored API's and added new tests
  • Loading branch information
plan97 committed Mar 14, 2021
2 parents 4b44c8e + 78b1156 commit 3f4ef4e
Show file tree
Hide file tree
Showing 16 changed files with 636 additions and 543 deletions.
2 changes: 1 addition & 1 deletion .github/workflows/go.yml
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ jobs:
- name: Set up Go
uses: actions/setup-go@v2
with:
go-version: "^1.16"
go-version: 1.16.2

- name: Add missing and remove unused modules
run: go mod tidy
Expand Down
15 changes: 14 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
@@ -1,4 +1,17 @@
# gofileserver
# Go File Server
[![Go Reference](https://pkg.go.dev/badge/github.com/plan97/gofileserver.svg)](https://pkg.go.dev/github.com/plan97/gofileserver)

A simple server with web UI, which serves files under a directory and is written in Go.

## Install

```
go get github.com/plan97/gofileserver/cmd/runfs
```

## Usage

After installing, run the following to check on usage.
```
runfs --help
```
465 changes: 0 additions & 465 deletions bindata.go

This file was deleted.

13 changes: 1 addition & 12 deletions cmd/runfs/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,22 +2,11 @@ package main

import (
"fmt"

server "github.com/plan97/gofileserver"
"github.com/plan97/gofileserver/config"
)

func main() {
c := config.New()
err := c.Fetch()
if err != nil {
fmt.Println(err)
return
}

err = server.Serve(c)
err := runfs()
if err != nil {
fmt.Println(err)
return
}
}
25 changes: 25 additions & 0 deletions cmd/runfs/runfs.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
package main

import (
server "github.com/plan97/gofileserver"
"github.com/plan97/gofileserver/config"
)

func runfs() error {
conf := config.New()
if err := conf.Fetch(); err != nil {
return err
}

router, err := server.Setup(conf)
if err != nil {
return err
}

if conf.HTTPS {
err = router.RunTLS(conf.Addr, conf.SSLCertFile, conf.SSLKeyFile)
} else {
err = router.Run(conf.Addr)
}
return err
}
24 changes: 12 additions & 12 deletions config/fetch.go
Original file line number Diff line number Diff line change
Expand Up @@ -29,8 +29,8 @@ type Config struct {
AllowCors bool
}

// Fetch configuration.
func (c *Config) Fetch() error {
// Fetch configuration from flags.
func (conf *Config) Fetch() (err error) {
config := viper.New()

flag.String("dir", "", "Directory to serve")
Expand All @@ -42,20 +42,20 @@ func (c *Config) Fetch() error {

pflag.CommandLine.AddGoFlagSet(flag.CommandLine)
pflag.Parse()
err := config.BindPFlags(pflag.CommandLine)
err = config.BindPFlags(pflag.CommandLine)
if err != nil {
return err
return
}

c.BaseDir = config.GetString("dir")
c.Addr = config.GetString("addr")
c.HTTPS = config.GetBool("https")
c.SSLCertFile = config.GetString("cert")
c.SSLKeyFile = config.GetString("key")
c.AllowCors = config.GetBool("cors")
conf.BaseDir = config.GetString("dir")
conf.Addr = config.GetString("addr")
conf.HTTPS = config.GetBool("https")
conf.SSLCertFile = config.GetString("cert")
conf.SSLKeyFile = config.GetString("key")
conf.AllowCors = config.GetBool("cors")

c.BaseDir, err = filepath.Abs(c.BaseDir)
return err
conf.BaseDir, err = filepath.Abs(conf.BaseDir)
return
}

// New returns a Config instance.
Expand Down
24 changes: 24 additions & 0 deletions config/fetch_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
package config

import "testing"

func TestConfig_Fetch(t *testing.T) {
tests := []struct {
name string
conf *Config
wantErr bool
}{
{
name: "test 1",
conf: New(),
wantErr: false,
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
if err := tt.conf.Fetch(); (err != nil) != tt.wantErr {
t.Errorf("Config.Fetch() error = %v, wantErr %v", err, tt.wantErr)
}
})
}
}
5 changes: 2 additions & 3 deletions go.mod
Original file line number Diff line number Diff line change
@@ -1,12 +1,11 @@
module github.com/plan97/gofileserver

go 1.15
go 1.16

require (
github.com/gin-contrib/cors v1.3.1
github.com/gin-gonic/gin v1.6.3
github.com/jteeuwen/go-bindata v3.0.7+incompatible
github.com/olebedev/staticbin v0.0.0-20150208021645-588762e15a7f
github.com/go-playground/assert/v2 v2.0.1
github.com/spf13/pflag v1.0.5
github.com/spf13/viper v1.7.1
)
4 changes: 0 additions & 4 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -118,8 +118,6 @@ github.com/json-iterator/go v1.1.7/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/u
github.com/json-iterator/go v1.1.9 h1:9yzud/Ht36ygwatGx56VwCZtlI/2AD15T1X2sjSuGns=
github.com/json-iterator/go v1.1.9/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4=
github.com/jstemmer/go-junit-report v0.0.0-20190106144839-af01ea7f8024/go.mod h1:6v2b51hI/fHJwM22ozAgKL4VKDeJcHhJFhtBdhmNjmU=
github.com/jteeuwen/go-bindata v3.0.7+incompatible h1:91Uy4d9SYVr1kyTJ15wJsog+esAZZl7JmEfTkwmhJts=
github.com/jteeuwen/go-bindata v3.0.7+incompatible/go.mod h1:JVvhzYOiGBnFSYRyV00iY8q7/0PThjIYav1p9h5dmKs=
github.com/jtolds/gls v4.20.0+incompatible h1:xdiiI2gbIgH/gLH7ADydsJ1uDOEzR8yvV7C0MuV77Wo=
github.com/jtolds/gls v4.20.0+incompatible/go.mod h1:QJZ7F/aHp+rZTRtaJ1ow/lLfFfVYBRgL+9YlvaHOwJU=
github.com/julienschmidt/httprouter v1.2.0/go.mod h1:SYymIcj16QtmaHHD7aYtjjsJG7VTCxuUUipMqKk8s4w=
Expand Down Expand Up @@ -160,8 +158,6 @@ github.com/modern-go/reflect2 v1.0.1 h1:9f412s+6RmYXLWZSEzVVgPGK7C2PphHj5RJrvfx9
github.com/modern-go/reflect2 v1.0.1/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0=
github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U=
github.com/oklog/ulid v1.3.1/go.mod h1:CirwcVhetQ6Lv90oh/F+FBtV6XMibvdAFo93nm5qn4U=
github.com/olebedev/staticbin v0.0.0-20150208021645-588762e15a7f h1:mxdEh+TkraVKJzm1CQIz86kCbr/G577IAAOp1/rP8CE=
github.com/olebedev/staticbin v0.0.0-20150208021645-588762e15a7f/go.mod h1:VFL8T3WLNjmLjFL1McC7yoN7fNxDX2B0Tf9q9XuK5q0=
github.com/pascaldekloe/goe v0.0.0-20180627143212-57f6aae5913c/go.mod h1:lzWF7FIEvWOWxwDKqyGYQf6ZUaNfKdP144TG7ZOy1lc=
github.com/pelletier/go-toml v1.2.0 h1:T5zMGML61Wp+FlcbWjRDT7yAxhJNAiPPLOFECq181zc=
github.com/pelletier/go-toml v1.2.0/go.mod h1:5z9KED0ma1S8pY6P1sdut58dfprrGBbd/94hg7ilaic=
Expand Down
1 change: 0 additions & 1 deletion handlers/listdir.go
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,5 @@ func ListDirFiles(baseDir string) gin.HandlerFunc {
}
}
c.JSON(http.StatusOK, req)
return
}
}
152 changes: 152 additions & 0 deletions handlers/listdir_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,152 @@
package handlers

import (
"errors"
"net/http"
"net/http/httptest"
"path/filepath"
"strings"
"testing"

"github.com/gin-gonic/gin"
"github.com/go-playground/assert/v2"
)

var errAssertionFailed = errors.New("assertion failed")

func TestListDirFiles(t *testing.T) {
type args struct {
baseDir string
}
tests := []struct {
name string
args args
testFunc func(gin.HandlerFunc) error
wantErr bool
}{
{
name: "test 1",
args: args{baseDir: func() string {
dir, err := filepath.Abs("")
if err != nil {
return ""
}
return dir
}()},
testFunc: func(fn gin.HandlerFunc) error {
gin.SetMode(gin.ReleaseMode)
router := gin.New()
router.Use(gin.Recovery())
api := router.Group("/api")
api.POST("list_dir_files", fn)

w := httptest.NewRecorder()
body := strings.NewReader(`{"dir":[]}`)
req, _ := http.NewRequest(http.MethodPost, "/api/list_dir_files", body)
req.Header.Set("Content-Type", "application/json")
router.ServeHTTP(w, req)

if !assert.IsEqual(http.StatusOK, w.Code) {
return errAssertionFailed
}
return nil
},
wantErr: false,
},
{
name: "test 2",
args: args{baseDir: func() string {
dir, err := filepath.Abs("")
if err != nil {
return ""
}
return dir
}()},
testFunc: func(fn gin.HandlerFunc) error {
gin.SetMode(gin.ReleaseMode)
router := gin.New()
router.Use(gin.Recovery())
api := router.Group("/api")
api.POST("list_dir_files", fn)

w := httptest.NewRecorder()
body := strings.NewReader(`{"dir":[".."]}`)
req, _ := http.NewRequest(http.MethodPost, "/api/list_dir_files", body)
req.Header.Set("Content-Type", "application/json")
router.ServeHTTP(w, req)

if !assert.IsEqual(http.StatusBadRequest, w.Code) {
return errAssertionFailed
}
return nil
},
wantErr: false,
},
{
name: "test 3",
args: args{baseDir: func() string {
dir, err := filepath.Abs("")
if err != nil {
return ""
}
return dir
}()},
testFunc: func(fn gin.HandlerFunc) error {
gin.SetMode(gin.ReleaseMode)
router := gin.New()
router.Use(gin.Recovery())
api := router.Group("/api")
api.POST("list_dir_files", fn)

w := httptest.NewRecorder()
body := strings.NewReader(`{"dir":["non_existing_dir"]}`)
req, _ := http.NewRequest(http.MethodPost, "/api/list_dir_files", body)
req.Header.Set("Content-Type", "application/json")
router.ServeHTTP(w, req)

if !assert.IsEqual(http.StatusInternalServerError, w.Code) {
return errAssertionFailed
}
return nil
},
wantErr: false,
},
{
name: "test 4",
args: args{baseDir: func() string {
dir, err := filepath.Abs("")
if err != nil {
return ""
}
return dir
}()},
testFunc: func(fn gin.HandlerFunc) error {
gin.SetMode(gin.ReleaseMode)
router := gin.New()
router.Use(gin.Recovery())
api := router.Group("/api")
api.POST("list_dir_files", fn)

w := httptest.NewRecorder()
body := strings.NewReader(`[]`)
req, _ := http.NewRequest(http.MethodPost, "/api/list_dir_files", body)
req.Header.Set("Content-Type", "application/json")
router.ServeHTTP(w, req)

if !assert.IsEqual(http.StatusBadRequest, w.Code) {
return errAssertionFailed
}
return nil
},
wantErr: false,
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
got := ListDirFiles(tt.args.baseDir)
if err := tt.testFunc(got); (err != nil) != tt.wantErr {
t.Errorf("testFunc(HandlerFunc) error = %v, wantErr %v", err, tt.wantErr)
}
})
}
}
23 changes: 11 additions & 12 deletions handlers/zipdir.go
Original file line number Diff line number Diff line change
Expand Up @@ -46,24 +46,31 @@ func ZipDir(baseDir string) gin.HandlerFunc {
fmt.Sprintf("attachment; filename=%s", strconv.Quote(fmt.Sprintf("%s.zip", filename))))
c.Header("Content-Type", c.Writer.Header().Get("Content-Type"))

// Walk the directory recursively and add all files to ZIP.
zipWriter := zip.NewWriter(c.Writer)
defer zipWriter.Close()

// Walk the directory recursively and add all files to ZIP.
err := filepath.Walk(path, func(filePath string, info os.FileInfo, err error) error {
if info.IsDir() {
return nil
}
if err != nil {
return err
}

if info.IsDir() {
return nil
}

relPath := strings.TrimPrefix(filepath.ToSlash(strings.TrimPrefix(filePath, path)), "/")

zipFile, err := zipWriter.Create(relPath)
if err != nil {
return err
}

fsFile, err := os.Open(filePath)
if err != nil {
return err
}

_, err = io.Copy(zipFile, fsFile)
if err != nil {
return err
Expand All @@ -74,13 +81,5 @@ func ZipDir(baseDir string) gin.HandlerFunc {
c.AbortWithError(http.StatusInternalServerError, err)
return
}

err = zipWriter.Close()
if err != nil {
c.AbortWithError(http.StatusInternalServerError, err)
return
}

return
}
}
Loading

0 comments on commit 3f4ef4e

Please sign in to comment.