26 Commits

Author SHA1 Message Date
codeskyblue
80c9e79869 update again 2022-07-26 19:23:30 +08:00
codeskyblue
2adc57be6c change ci from travis to github actions 2022-07-26 18:44:49 +08:00
codeskyblue
6829892be4 update go build version 2022-07-26 18:33:24 +08:00
codeskyblue
26545513de fix #137 2022-05-23 18:19:46 +08:00
codeskyblue
342d9cc14c Merge pull request #125 from maxunof/master
Migration to go:embed and some other changes
2021-09-14 14:22:54 +08:00
codeskyblue
ed85a9687b Merge pull request #126 from miguelnv/issue#117-error-fetching-large-folders
issue#117-error-fetching-large-folders
2021-09-13 22:29:55 +08:00
Miguel Vieira
fe8dcd76c1 thread-safe concurrent file size info map 2021-09-05 03:34:26 +01:00
Max
230bc3d182 so now we can use go install 2021-08-20 11:34:30 +00:00
Max
28a90b90dd fix version load 2021-08-20 11:26:15 +00:00
Max
e607da8ec2 make footer more pretty 2021-08-20 11:26:00 +00:00
Max
e47bdd1272 migrate from vfs to go:embed 2021-08-20 11:24:42 +00:00
Max
ff821dcb63 fix typo in readme (#122) 2021-08-20 13:18:03 +03:00
codeskyblue
8887f4ef69 Merge pull request #124 from maxunof/master
fix readme
2021-08-20 16:36:54 +08:00
Max
bd1a35541a fix readme x2 2021-08-19 17:47:15 +03:00
Max
56045c6c8e fix readme 2021-08-19 16:48:45 +03:00
codeskyblue
b5bd6779f9 fix #105 2021-04-06 10:52:25 +08:00
codeskyblue
8665999fc0 Merge branch 'prefix' 2021-04-06 10:43:01 +08:00
codeskyblue
677c5a7cec update names 2021-04-06 10:42:49 +08:00
codeskyblue
41981a3d8a update readme 2021-04-01 11:16:51 +08:00
codeskyblue
47789eec68 Merge branch 'aeoluswing-master' 2021-03-30 17:04:43 +08:00
codeskyblue
4c880193ce merge pull request 2021-03-30 17:04:23 +08:00
codeskyblue
86aeecfac2 Merge branch 'master' of https://github.com/aeoluswing/gohttpserver into aeoluswing-master 2021-03-30 16:47:34 +08:00
aeolus
e8af97872c Merge pull request #2 from aeoluswing/fix-uplimit-20210326
Fix the assignment of sync buf
2021-03-26 18:58:16 +08:00
aeoluswing
d7590729f1 Fix the assignment of sync buf 2021-03-26 18:50:06 +08:00
aeolus
1258ac759f Merge pull request #1 from aeoluswing/fix-uplimit-20210326
Optimize the performance of the copy phase during the upload process
2021-03-26 14:18:29 +08:00
aeoluswing
a60a9c4811 Optimize the performance of the copy phase during the upload process 2021-03-26 14:03:54 +08:00
14 changed files with 145 additions and 147 deletions

34
.github/workflows/release.yml vendored Normal file
View File

@@ -0,0 +1,34 @@
name: goreleaser
on:
push:
# run only against tags
tags:
- '*'
permissions:
contents: write
# packages: write
# issues: write
jobs:
goreleaser:
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v2
with:
fetch-depth: 0
- name: Fetch all tags
run: git fetch --force --tags
- name: Set up Go
uses: actions/setup-go@v2
with:
go-version: 1.18
- name: Run GoReleaser
uses: goreleaser/goreleaser-action@v2
with:
# either 'goreleaser' (default) or 'goreleaser-pro'
distribution: goreleaser
version: latest
args: release --rm-dist
env:
GITHUB_TOKEN: ${{ secrets.TOKEN }}

View File

@@ -1,13 +1,10 @@
before:
hooks:
- go mod tidy
- go generate .
builds:
- env:
- CGO_ENABLED=0
main: .
flags:
- -tags=vfs
ldflags: -s -w -X main.VERSION={{.Version}} -X main.BUILDTIME={{.Date}} -X main.GITCOMMIT={{.Commit}}
goos:
- linux

View File

@@ -1,25 +0,0 @@
services:
- docker
language: go
go:
- "1.16"
env:
- GO111MODULE=on
script:
- go test -v
addons:
apt:
packages:
- docker-ce
deploy:
- provider: script
skip_cleanup: true
script: curl -sL https://git.io/goreleaser | bash
on:
tags: true
condition: $TRAVIS_OS_NAME = linux
#- provider: script
# skip_cleanup: true
# script: bash docker/push_images && bash docker/push_manifest
# on:
# branch: master

View File

@@ -58,10 +58,8 @@ Tested with go-1.16
1. [x] Support unzip zip file when upload(with form: unzip=true)
## Installation
```
go get -v github.com/codeskyblue/gohttpserver
cd $GOPATH/src/github.com/codeskyblue/gohttpserver
go build && ./gohttpserver
```bash
$ go install github.com/codeskyblue/gohttpserver@latest
```
Or download binaries from [github releases](https://github.com/codeskyblue/gohttpserver/releases)
@@ -69,14 +67,14 @@ Or download binaries from [github releases](https://github.com/codeskyblue/gohtt
If you are using Mac, simply run command
```bash
brew install codeskyblue/tap/gohttpserver
$ brew install codeskyblue/tap/gohttpserver
```
## Usage
Listen on port 8000 of all interfaces, and enable file uploading.
```
./gohttpserver -r ./ --port 8000 --upload
$ gohttpserver -r ./ --port 8000 --upload
```
Use command `gohttpserver --help` to see more usage.
@@ -85,13 +83,13 @@ Use command `gohttpserver --help` to see more usage.
share current directory
```bash
docker run -it --rm -p 8000:8000 -v $PWD:/app/public --name gohttpserver codeskyblue/gohttpserver
$ docker run -it --rm -p 8000:8000 -v $PWD:/app/public --name gohttpserver codeskyblue/gohttpserver
```
Share current directory with http basic auth
```bash
docker run -it --rm -p 8000:8000 -v $PWD:/app/public --name gohttpserver \
$ docker run -it --rm -p 8000:8000 -v $PWD:/app/public --name gohttpserver \
codeskyblue/gohttpserver \
--auth-type http --auth-http username:password
```
@@ -99,7 +97,7 @@ docker run -it --rm -p 8000:8000 -v $PWD:/app/public --name gohttpserver \
Share current directory with openid auth. (Works only in netease company.)
```bash
docker run -it --rm -p 8000:8000 -v $PWD:/app/public --name gohttpserver \
$ docker run -it --rm -p 8000:8000 -v $PWD:/app/public --name gohttpserver \
codeskyblue/gohttpserver \
--auth-type openid
```
@@ -107,8 +105,8 @@ docker run -it --rm -p 8000:8000 -v $PWD:/app/public --name gohttpserver \
To build image yourself, please change the PWD to the root of this repo.
```bash
cd gohttpserver/
docker build -t codeskyblue/gohttpserver -f docker/Dockerfile .
$ cd gohttpserver/
$ docker build -t codeskyblue/gohttpserver -f docker/Dockerfile .
```
## Authentication options
@@ -132,7 +130,7 @@ docker build -t codeskyblue/gohttpserver -f docker/Dockerfile .
You can configure to let a http reverse proxy handling authentication.
When using oauth2-proxy, the backend will use identification info from request headers `X-Auth-Request-Email` as userId and `X-Auth-Request-Fullname` as user's display name.
Please config your oauth2 reverse proxy yourself.
More about [oauth2-proxy](https://github.com/bitly/oauth2_proxy).
More about [oauth2-proxy](https://github.com/oauth2-proxy/oauth2-proxy).
All required headers list as following.
@@ -198,8 +196,8 @@ accessTables:
### ipa plist proxy
This is used for server on which https is enabled. default use <https://plistproxy.herokuapp.com/plist>
```
./gohttpserver --plistproxy=https://someproxyhost.com/
```bash
$ gohttpserver --plistproxy=https://someproxyhost.com/
```
Test if proxy works:
@@ -264,6 +262,35 @@ gohttpserver should started with `--xheaders` argument when behide nginx.
Refs: <http://nginx.org/en/docs/http/ngx_http_core_module.html#client_max_body_size>
gohttpserver also support `--prefix` flag which will help to when meet `/` is occupied by other service. relative issue <https://github.com/codeskyblue/gohttpserver/issues/105>
Usage example:
```bash
# for gohttpserver
$ gohttpserver --prefix /foo --addr :8200 --xheaders
```
**Nginx settigns**
```
server {
listen 80;
server_name your-domain-name.com;
location /foo {
proxy_pass http://127.0.0.1:8200; # here need to change
proxy_redirect off;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
client_max_body_size 0; # disable upload limit
}
}
```
## FAQ
- [How to generate self signed certificate with openssl](http://stackoverflow.com/questions/10175812/how-to-create-a-self-signed-certificate-with-openssl)
@@ -279,14 +306,13 @@ Depdencies are managed by [govendor](https://github.com/kardianos/govendor)
1. Build develop version. **assets** directory must exists
```sh
go build
./gohttpserver
$ go build
$ ./gohttpserver
```
2. Build single binary release
```sh
go generate .
go build -tags vfs
$ go build
```
Theme are defined in [assets/themes](assets/themes) directory. Now only two themes are available, "black" and "green".
@@ -306,7 +332,7 @@ Theme are defined in [assets/themes](assets/themes) directory. Now only two them
**Go Libraries**
* [vfsgen](https://github.com/shurcooL/vfsgen)
* [vfsgen](https://github.com/shurcooL/vfsgen) Not using now
* [go-bindata-assetfs](https://github.com/elazarl/go-bindata-assetfs) Not using now
* <http://www.gorillatoolkit.org/pkg/handlers>

12
assets.go Normal file
View File

@@ -0,0 +1,12 @@
package main
import (
"embed"
"net/http"
)
//go:embed assets
var assetsFS embed.FS
// Assets contains project assets.
var Assets = http.FS(assetsFS)

View File

@@ -129,7 +129,7 @@
<tbody>
<tr v-for="f in computedFiles">
<td>
<a v-on:click='clickFileOrDir(f, $event)' href="{{getEncodePath(f)}}">
<a v-on:click='clickFileOrDir(f, $event)' href="{{getEncodePath(f.name)}}">
<!-- ?raw=false -->
<i style="padding-right: 0.5em" class="fa" v-bind:class='genFileClass(f)'></i> {{f.name}}
</a>
@@ -142,7 +142,7 @@
<td class="hidden-xs">{{formatTime(f.mtime)}}</td>
<td style="text-align: left">
<template v-if="f.type == 'dir'">
<a class="btn btn-default btn-xs" href="{{getEncodePath(f)}}/?op=archive">
<a class="btn btn-default btn-xs" href="{{getEncodePath(f.name)}}/?op=archive">
<span class="hidden-xs">Archive</span> Zip
<span class="glyphicon glyphicon-download-alt"></span>
</a>
@@ -256,8 +256,7 @@
</div>
<div class="col-md-12">
<div id="footer" class="pull-right" style="margin: 2em 1em">
<a href="https://github.com/codeskyblue/gohttpserver">gohttpserver (ver:{{version}})</a>, written by <a href="https://github.com/codeskyblue">codeskyblue</a>.
Copyright 2016-2021. go1.16
<a href="https://github.com/codeskyblue/gohttpserver">gohttpserver ({{version}})</a>, by <a href="https://github.com/codeskyblue">codeskyblue</a>.
</div>
</div>
</div>

View File

@@ -36,7 +36,6 @@ function showErrorMessage(jqXHR) {
console.error(errMsg)
}
var vm = new Vue({
el: "#app",
data: {
@@ -141,8 +140,8 @@ var vm = new Vue({
});
},
methods: {
getEncodePath: function (f) {
return pathJoin([location.pathname, encodeURIComponent(f.name)]);
getEncodePath: function (filepath) {
return pathJoin([location.pathname].concat(filepath.split("/").map(v => encodeURIComponent(v))))
},
formatTime: function (timestamp) {
var m = moment(timestamp);
@@ -191,7 +190,7 @@ var vm = new Vue({
genDownloadURL: function (f) {
var search = location.search;
var sep = search == "" ? "?" : "&"
return location.origin + this.getEncodePath(f) + location.search + sep + "download=true";
return location.origin + this.getEncodePath(f.name) + location.search + sep + "download=true";
},
shouldHaveQrcode: function (name) {
return ['apk', 'ipa'].indexOf(getExtention(name)) !== -1;
@@ -237,7 +236,7 @@ var vm = new Vue({
return "fa-file-text-o"
},
clickFileOrDir: function (f, e) {
var reqPath = pathJoin([location.pathname, encodeURIComponent(f.name)]);
var reqPath = this.getEncodePath(f.name)
// TODO: fix here tomorrow
if (f.type == "file") {
window.location.href = reqPath;
@@ -253,7 +252,7 @@ var vm = new Vue({
showInfo: function (f) {
console.log(f);
$.ajax({
url: pathJoin(["/", location.pathname, encodeURIComponent(f.name)]),
url: this.getEncodePath(f.name),
data: {
op: "info",
},
@@ -280,7 +279,7 @@ var vm = new Vue({
return
}
$.ajax({
url: pathJoin(["/", location.pathname, "/", encodeURIComponent(name)]),
url: this.getEncodePath(name),
method: "POST",
success: function (res) {
console.log(res)
@@ -294,12 +293,12 @@ var vm = new Vue({
deletePathConfirm: function (f, e) {
e.preventDefault();
if (!e.altKey) { // skip confirm when alt pressed
if (!window.confirm("Delete " + location.pathname + "/" + f.name + " ?")) {
if (!window.confirm("Delete " + f.name + " ?")) {
return;
}
}
$.ajax({
url: pathJoin([location.pathname, encodeURIComponent(f.name)]),
url: this.getEncodePath(f.name),
method: 'DELETE',
success: function (res) {
loadFileList()
@@ -434,7 +433,7 @@ $(function () {
loadFileList(location.pathname + location.search)
// update version
$.getJSON(URL_PREFIX + "/-/sysinfo", function (res) {
$.getJSON("/-/sysinfo", function (res) {
vm.version = res.version;
})

View File

@@ -1,9 +0,0 @@
// +build !vfs
//go:generate go run assets_generate.go
package main
import "net/http"
// Assets contains project assets.
var Assets http.FileSystem = http.Dir("assets")

View File

@@ -1,23 +0,0 @@
// +build ignore
package main
import (
"log"
"net/http"
"github.com/shurcooL/vfsgen"
)
func main() {
var fs http.FileSystem = http.Dir("assets")
err := vfsgen.Generate(fs, vfsgen.Options{
PackageName: "main",
BuildTags: "vfs",
VariableName: "Assets",
})
if err != nil {
log.Fatalln(err)
}
}

View File

@@ -23,13 +23,10 @@ fi
build() {
echo "$1 $2 ..."
GOOS=$1 GOARCH=$2 go build \
-tags vfs \
-ldflags "$LDFLAGS" \
-o dist/gohttpserver-${3:-""}
}
go generate .
build linux arm linux-arm
build darwin amd64 mac-amd64
build linux amd64 linux-amd64

4
go.mod
View File

@@ -17,11 +17,9 @@ require (
github.com/gorilla/sessions v1.1.3
github.com/pkg/errors v0.8.0 // indirect
github.com/shogo82148/androidbinary v0.0.0-20180627093851-01c4bfa8b3b5
github.com/shurcooL/httpfs v0.0.0-20171119174359-809beceb2371 // indirect
github.com/shurcooL/vfsgen v0.0.0-20181020040650-a97a25d856ca
github.com/smartystreets/goconvey v1.6.4 // indirect
github.com/stretchr/testify v1.3.0
golang.org/x/net v0.0.0-20201021035429-f5854403a974 // indirect
golang.org/x/text v0.3.3
golang.org/x/tools v0.1.0 // indirect
howett.net/plist v0.0.0-20201203080718-1454fab16a06 // indirect
)

17
go.sum
View File

@@ -44,10 +44,6 @@ github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZb
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/shogo82148/androidbinary v0.0.0-20180627093851-01c4bfa8b3b5 h1:bXRaUWl3Afe3F9YR5NU1U3UB5zjCHlu4im5p3J/LUYk=
github.com/shogo82148/androidbinary v0.0.0-20180627093851-01c4bfa8b3b5/go.mod h1:05AjXWPWLdTIl9+REKhSmTeoJ6Wz5e9ir0Q0NRxCIKo=
github.com/shurcooL/httpfs v0.0.0-20171119174359-809beceb2371 h1:SWV2fHctRpRrp49VXJ6UZja7gU9QLHwRpIPBN89SKEo=
github.com/shurcooL/httpfs v0.0.0-20171119174359-809beceb2371/go.mod h1:ZY1cvUeJuFPAdZ/B6v7RHavJWZn2YPVFQ1OSXhCGOkg=
github.com/shurcooL/vfsgen v0.0.0-20181020040650-a97a25d856ca h1:3fECS8atRjByijiI8yYiuwLwQ2ZxXobW7ua/8GRB3pI=
github.com/shurcooL/vfsgen v0.0.0-20181020040650-a97a25d856ca/go.mod h1:TrYk7fJVaAttu97ZZKrO9UbRa8izdowaMIZcxYMbVaw=
github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d h1:zE9ykElWQ6/NYmHa3jpm/yHnI4xSofP+UP6SpjHcSeM=
github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d/go.mod h1:OnSkiWE9lh6wB0YB77sQom3nweQdgAjqCqsofrRNTgc=
github.com/smartystreets/goconvey v1.6.4 h1:fv0U8FUIMPNf1L9lnHLvLhgicrIVChEkdzIKYqbNC9s=
@@ -55,33 +51,20 @@ github.com/smartystreets/goconvey v1.6.4/go.mod h1:syvi0/a8iFYH4r/RixwvyeAJjdLS9
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/testify v1.3.0 h1:TivCn/peBQ7UY8ooIcPgZFpTNSz0Q2U6UrFlUfqbe0Q=
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20201021035429-f5854403a974 h1:IX6qOQeG5uLjB/hjjwjedwfjND0hgjPMMyO1RoIXQNI=
golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210119212857-b64e53b001e4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.3 h1:cokOdA+Jmi5PJGXLlLllQSgYigAEfHXJAERHVMaCc2k=
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
golang.org/x/tools v0.0.0-20190328211700-ab21143f2384/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
golang.org/x/tools v0.1.0 h1:po9/4sTYwZU9lPhi1tOrb4hCv3qrhiQ77LZfGa2OjwY=
golang.org/x/tools v0.1.0/go.mod h1:xkSsbof2nBLbhDlRMhhhyNLN/zl3eTqcnHD5viDpcZ0=
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127 h1:qIbj1fsPNlZgppZ+VLlY7N33q108Sa+fhmuc+sWQYwY=
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=

View File

@@ -16,6 +16,7 @@ import (
"path/filepath"
"strconv"
"strings"
"sync"
"time"
"regexp"
@@ -41,6 +42,11 @@ type IndexFileItem struct {
Info os.FileInfo
}
type Directory struct {
size map[string]int64
mutex *sync.RWMutex
}
type HTTPStaticServer struct {
Root string
Prefix string
@@ -54,6 +60,7 @@ type HTTPStaticServer struct {
indexes []IndexFileItem
m *mux.Router
bufPool sync.Pool // use sync.Pool caching buf to reduce gc ratio
}
func NewHTTPStaticServer(root string) *HTTPStaticServer {
@@ -71,6 +78,9 @@ func NewHTTPStaticServer(root string) *HTTPStaticServer {
Root: root,
Theme: "black",
m: m,
bufPool: sync.Pool{
New: func() interface{} { return make([]byte, 32*1024) },
},
}
go func() {
@@ -137,7 +147,7 @@ func (s *HTTPStaticServer) hIndex(w http.ResponseWriter, r *http.Request) {
if r.Method == "HEAD" {
return
}
renderHTML(w, "index.html", s)
renderHTML(w, "assets/index.html", s)
} else {
if filepath.Base(path) == YAMLCONF {
auth := s.readAccessConf(realPath)
@@ -244,7 +254,12 @@ func (s *HTTPStaticServer) hUploadOrMkdir(w http.ResponseWriter, req *http.Reque
http.Error(w, "File create "+err.Error(), http.StatusInternalServerError)
return
}
_, copyErr = io.Copy(dst, file)
// Note: very large size file might cause poor performance
// _, copyErr = io.Copy(dst, file)
buf := s.bufPool.Get().([]byte)
defer s.bufPool.Put(buf)
_, copyErr = io.CopyBuffer(dst, file, buf)
dst.Close()
// }
if copyErr != nil {
@@ -413,7 +428,7 @@ func (s *HTTPStaticServer) hIpaLink(w http.ResponseWriter, r *http.Request) {
w.Header().Set("Content-Type", "text/html")
log.Println("PlistURL:", plistUrl)
renderHTML(w, "ipa-install.html", map[string]string{
renderHTML(w, "assets/ipa-install.html", map[string]string{
"Name": filepath.Base(path),
"PlistLink": plistUrl,
})
@@ -620,7 +635,7 @@ func (s *HTTPStaticServer) hJSONList(w http.ResponseWriter, r *http.Request) {
w.Write(data)
}
var dirSizeMap = make(map[string]int64)
var dirInfoSize = Directory{size: make(map[string]int64), mutex: &sync.RWMutex{}}
func (s *HTTPStaticServer) makeIndex() error {
var indexes = make([]IndexFileItem, 0)
@@ -640,21 +655,28 @@ func (s *HTTPStaticServer) makeIndex() error {
return nil
})
s.indexes = indexes
dirSizeMap = make(map[string]int64)
return err
}
func (s *HTTPStaticServer) historyDirSize(dir string) int64 {
var size int64
if size, ok := dirSizeMap[dir]; ok {
dirInfoSize.mutex.RLock()
size, ok := dirInfoSize.size[dir]
dirInfoSize.mutex.RUnlock()
if ok {
return size
}
for _, fitem := range s.indexes {
if filepath.HasPrefix(fitem.Path, dir) {
size += fitem.Info.Size()
}
}
dirSizeMap[dir] = size
dirInfoSize.mutex.Lock()
dirInfoSize.size[dir] = size
dirInfoSize.mutex.Unlock()
return size
}
@@ -719,10 +741,9 @@ func (s *HTTPStaticServer) readAccessConf(realPath string) (ac AccessConf) {
}
func deepPath(basedir, name string) string {
isDir := true
// loop max 5, incase of for loop not finished
maxDepth := 5
for depth := 0; depth <= maxDepth && isDir; depth += 1 {
for depth := 0; depth <= maxDepth; depth += 1 {
finfos, err := ioutil.ReadDir(filepath.Join(basedir, name))
if err != nil || len(finfos) != 1 {
break
@@ -774,7 +795,7 @@ var (
_tmpls = make(map[string]*template.Template)
)
func executeTemplate(w http.ResponseWriter, name string, v interface{}) {
func renderHTML(w http.ResponseWriter, name string, v interface{}) {
if t, ok := _tmpls[name]; ok {
t.Execute(w, v)
return
@@ -784,16 +805,6 @@ func executeTemplate(w http.ResponseWriter, name string, v interface{}) {
t.Execute(w, v)
}
func renderHTML(w http.ResponseWriter, name string, v interface{}) {
if _, ok := Assets.(http.Dir); ok {
log.Println("Hot load", name)
t := template.Must(template.New(name).Funcs(funcMap).Delims("[[", "]]").Parse(assetsContent(name)))
t.Execute(w, v)
} else {
executeTemplate(w, name, v)
}
}
func checkFilename(name string) error {
if strings.ContainsAny(name, "\\/:*<>|") {
return errors.New("Name should not contains \\/:*<>|")

19
main.go
View File

@@ -22,7 +22,6 @@ import (
"github.com/goji/httpauth"
"github.com/gorilla/handlers"
"github.com/gorilla/mux"
_ "github.com/shurcooL/vfsgen"
)
type Configure struct {
@@ -214,18 +213,18 @@ func main() {
hdlr = handlers.ProxyHeaders(hdlr)
}
mainRooter := mux.NewRouter()
rooter := mainRooter
mainRouter := mux.NewRouter()
router := mainRouter
if gcfg.Prefix != "" {
rooter = mainRooter.PathPrefix(gcfg.Prefix).Subrouter()
mainRooter.Handle(gcfg.Prefix, hdlr)
mainRooter.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
router = mainRouter.PathPrefix(gcfg.Prefix).Subrouter()
mainRouter.Handle(gcfg.Prefix, hdlr)
mainRouter.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
http.Redirect(w, r, gcfg.Prefix, http.StatusTemporaryRedirect)
})
}
rooter.PathPrefix("/-/assets/").Handler(http.StripPrefix(gcfg.Prefix+"/-/assets/", http.FileServer(Assets)))
rooter.HandleFunc("/-/sysinfo", func(w http.ResponseWriter, r *http.Request) {
router.PathPrefix("/-/assets/").Handler(http.StripPrefix(gcfg.Prefix+"/-/", http.FileServer(Assets)))
router.HandleFunc("/-/sysinfo", func(w http.ResponseWriter, r *http.Request) {
data, _ := json.Marshal(map[string]interface{}{
"version": VERSION,
})
@@ -233,7 +232,7 @@ func main() {
w.Header().Set("Content-Length", fmt.Sprintf("%d", len(data)))
w.Write(data)
})
rooter.PathPrefix("/").Handler(hdlr)
router.PathPrefix("/").Handler(hdlr)
if gcfg.Addr == "" {
gcfg.Addr = fmt.Sprintf(":%d", gcfg.Port)
@@ -245,7 +244,7 @@ func main() {
log.Printf("listening on %s, local address http://%s:%s\n", strconv.Quote(gcfg.Addr), getLocalIP(), port)
srv := &http.Server{
Handler: mainRooter,
Handler: mainRouter,
Addr: gcfg.Addr,
}