45 Commits

Author SHA1 Message Date
孙圣翔²⁰₂₁
fdd6ff9435 fix for goreleaser 2024-12-04 08:57:52 +08:00
codeskyblue
29bd44ac0c Merge pull request #212 from black-06/master
feat: support for multiple http users
2024-12-04 08:36:52 +08:00
codeskyblue
4b9be2fd12 Merge pull request #210 from NaturezzZ/master
[feat] directly play video
2024-12-04 08:33:57 +08:00
black-06
2d7a0f1aaf feat: support for multiple http users 2024-10-28 19:20:44 +08:00
NaturezzZ
23f70c844a [feat] directly play video 2024-10-19 14:36:26 +08:00
codeskyblue
6d8af0af8f Merge pull request #202 from codeskyblue/dependabot/go_modules/golang.org/x/net-0.23.0 2024-05-14 13:55:34 +08:00
dependabot[bot]
189100b3af Bump golang.org/x/net from 0.17.0 to 0.23.0
Bumps [golang.org/x/net](https://github.com/golang/net) from 0.17.0 to 0.23.0.
- [Commits](https://github.com/golang/net/compare/v0.17.0...v0.23.0)

---
updated-dependencies:
- dependency-name: golang.org/x/net
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-04-19 12:32:20 +00:00
codeskyblue
75eb27f9c9 merge pr 2023-12-19 11:43:27 +08:00
dependabot[bot]
e31775af89 Bump golang.org/x/net from 0.7.0 to 0.17.0
Bumps [golang.org/x/net](https://github.com/golang/net) from 0.7.0 to 0.17.0.
- [Commits](https://github.com/golang/net/compare/v0.7.0...v0.17.0)

---
updated-dependencies:
- dependency-name: golang.org/x/net
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-12-19 11:41:36 +08:00
Gary Marigliano
2a0e1f7400 Add no-index option to disable indexing and search 2023-12-19 11:41:18 +08:00
dependabot[bot]
dbd0e06c73 Bump golang.org/x/net from 0.0.0-20201021035429-f5854403a974 to 0.7.0
Bumps [golang.org/x/net](https://github.com/golang/net) from 0.0.0-20201021035429-f5854403a974 to 0.7.0.
- [Release notes](https://github.com/golang/net/releases)
- [Commits](https://github.com/golang/net/commits/v0.7.0)

---
updated-dependencies:
- dependency-name: golang.org/x/net
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-12-19 11:38:34 +08:00
Kushal Azim Ekram
bd2d79953d Added alpine and upx based container build. Much smaller size ~14mb 2023-12-19 11:38:34 +08:00
Jiawen Geng
dd8692b656 fix docker build
3.612 E: Failed to fetch http://deb.debian.org/debian/dists/stretch-updates/main/binary-amd64/Packages  404  Not Found [IP: 151.101.202.132 80]
3.612 E: Some index files failed to download. They have been ignored, or old ones used instead.
------
Dockerfile:10
--------------------
   8 |     WORKDIR /app
   9 |     RUN mkdir -p /app/public
  10 | >>> RUN apt-get update && apt-get install -y ca-certificates
2023-12-19 11:38:34 +08:00
codeskyblue
eacf2d1dc3 cors enable by default 2023-12-19 11:38:34 +08:00
codeskyblue
08e2cf764d limit cors only get, head, options 2023-12-19 11:38:34 +08:00
codeskyblue
a400a028ff Merge pull request #193 from codeskyblue/dependabot/go_modules/golang.org/x/net-0.17.0
Bump golang.org/x/net from 0.7.0 to 0.17.0
2023-12-19 11:17:21 +08:00
codeskyblue
f2fb06ae18 Merge pull request #174 from krypty/add-option-to-disable-index
Add no-index option to disable indexing and search
2023-12-19 11:16:48 +08:00
dependabot[bot]
71957e4947 Bump golang.org/x/net from 0.7.0 to 0.17.0
Bumps [golang.org/x/net](https://github.com/golang/net) from 0.7.0 to 0.17.0.
- [Commits](https://github.com/golang/net/compare/v0.7.0...v0.17.0)

---
updated-dependencies:
- dependency-name: golang.org/x/net
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-12-19 03:15:17 +00:00
codeskyblue
5fab10ed10 Merge pull request #170 from codeskyblue/dependabot/go_modules/golang.org/x/net-0.7.0
Bump golang.org/x/net from 0.0.0-20201021035429-f5854403a974 to 0.7.0
2023-12-19 11:14:42 +08:00
codeskyblue
30e4b86595 Merge pull request #173 from kforeverisback/alpine-small-build
Smaller Build using Alpine and UPX
2023-12-19 11:12:10 +08:00
codeskyblue
5bcbcd0bac Merge pull request #185 from gengjiawen/patch-3
fix docker build
2023-12-19 11:11:14 +08:00
codeskyblue
2a5610bb74 Merge pull request #192 from codeskyblue/add-cors
cors enable by default
2023-12-19 11:07:02 +08:00
codeskyblue
b86e0e623e cors enable by default 2023-12-19 11:05:52 +08:00
codeskyblue
bca7b842f5 Merge pull request #191 from codeskyblue/limit-cors
limit cors only get, head, options
2023-12-19 10:38:43 +08:00
codeskyblue
ea7272437d limit cors only get, head, options 2023-12-19 10:37:39 +08:00
Jiawen Geng
6de7ca4676 fix docker build
3.612 E: Failed to fetch http://deb.debian.org/debian/dists/stretch-updates/main/binary-amd64/Packages  404  Not Found [IP: 151.101.202.132 80]
3.612 E: Some index files failed to download. They have been ignored, or old ones used instead.
------
Dockerfile:10
--------------------
   8 |     WORKDIR /app
   9 |     RUN mkdir -p /app/public
  10 | >>> RUN apt-get update && apt-get install -y ca-certificates
2023-10-07 16:54:56 +08:00
Gary Marigliano
88433ea55e Add no-index option to disable indexing and search 2023-03-13 10:17:42 +01:00
Kushal Azim Ekram
d874ba59cf Added alpine and upx based container build. Much smaller size ~14mb 2023-03-11 21:16:26 -08:00
Gary Marigliano
5dc0040375 Make deep path depth configurable
Allow to configure with --deep-path-max-depth the depth of paths to combine
when listing the folders. The default is still 5.
2023-03-09 11:48:20 +01:00
dependabot[bot]
034215a031 Bump golang.org/x/net from 0.0.0-20201021035429-f5854403a974 to 0.7.0
Bumps [golang.org/x/net](https://github.com/golang/net) from 0.0.0-20201021035429-f5854403a974 to 0.7.0.
- [Release notes](https://github.com/golang/net/releases)
- [Commits](https://github.com/golang/net/commits/v0.7.0)

---
updated-dependencies:
- dependency-name: golang.org/x/net
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-02-25 01:35:46 +00:00
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
19 changed files with 342 additions and 192 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
env:
GITHUB_TOKEN: ${{ secrets.TOKEN }}

1
.gitignore vendored
View File

@@ -31,3 +31,4 @@ assets_vfsdata.go
*.swp
dist/
.DS_Store

View File

@@ -1,13 +1,11 @@
version: 2
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
@@ -19,8 +17,16 @@ builds:
- "386"
goarm:
- "6"
brews:
- tap:
owner: codeskyblue
name: homebrew-tap
folder: Formula
archives:
- format: tar.gz
# use zip for windows archives
format_overrides:
- goos: windows
format: zip
# brews:
# - tap:
# owner: codeskyblue
# name: homebrew-tap
# folder: Formula

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,21 +83,21 @@ 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
--auth-type http --auth-http username1:password1 --auth-http username2:password2
```
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,15 +105,15 @@ 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
- Enable basic http authentication
```sh
$ gohttpserver --auth-type http --auth-http username:password
$ gohttpserver --auth-type http --auth-http username1:password1 --auth-http username2:password2
```
- Use openid auth
@@ -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:
@@ -270,7 +268,7 @@ Usage example:
```bash
# for gohttpserver
./gohttpserver --prefox /foo --addr :8200 --xheaders
$ gohttpserver --prefix /foo --addr :8200 --xheaders
```
**Nginx settigns**
@@ -308,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".
@@ -335,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

@@ -64,6 +64,8 @@
</template>
[[end]]
</ul>
[[if not .NoIndex ]]
<form class="navbar-form navbar-right">
<div class="input-group">
<input type="text" name="search" class="form-control" placeholder="Search text" v-bind:value="search"
@@ -75,6 +77,7 @@
</span>
</div>
</form>
[[end]]
<ul id="nav-right-bar" class="nav navbar-nav navbar-right">
</ul>
</div>
@@ -129,7 +132,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 +145,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 +259,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,10 +236,18 @@ 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;
// check whether the file is video
var videoExtensions = ['mp4', 'webm', 'ogg', 'mov', 'avi', 'mkv'];
var fileExtension = getExtention(f.name).toLowerCase();
if (videoExtensions.includes(fileExtension)) {
window.location.href = '/-/video-player' + reqPath;
} else {
window.location.href = reqPath;
}
e.preventDefault()
return;
}
loadFileOrDir(reqPath);
@@ -253,7 +260,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 +287,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 +301,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 +441,7 @@ $(function () {
loadFileList(location.pathname + location.search)
// update version
$.getJSON(URL_PREFIX + "/-/sysinfo", function (res) {
$.getJSON("/-/sysinfo", function (res) {
vm.version = res.version;
})

49
assets/video-player.html Normal file
View File

@@ -0,0 +1,49 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Video Player - [[.FileName]]</title>
<style>
body, html {
margin: 0;
padding: 0;
height: 100%;
width: 100%;
overflow: hidden;
background-color: #000;
}
.video-container {
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
height: 100%;
}
video {
max-width: 100%;
max-height: 100%;
}
h1 {
color: #fff;
font-size: 24px;
margin-bottom: 20px;
}
</style>
</head>
<body>
<div class="video-container">
<video id="videoPlayer" controls autoplay>
<source src="[[.VideoURL]]" type="video/[[.Extension]]">
Your browser does not support the video tag.
</video>
</div>
<script>
document.addEventListener('DOMContentLoaded', function() {
var video = document.getElementById('videoPlayer');
video.focus();
});
</script>
</body>
</html>

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

View File

@@ -3,7 +3,7 @@ WORKDIR /app/gohttpserver
ADD . /app/gohttpserver
RUN CGO_ENABLED=0 GOOS=linux go build -ldflags '-X main.VERSION=docker' -o gohttpserver
FROM debian:stretch
FROM debian:stable
WORKDIR /app
RUN mkdir -p /app/public
RUN apt-get update && apt-get install -y ca-certificates

19
docker/Dockerfile.alpine Normal file
View File

@@ -0,0 +1,19 @@
FROM golang:1.16.0-alpine as build
WORKDIR /app
COPY go.mod .
COPY go.sum .
RUN go mod download
# Binary Compression
RUN apk add upx --no-cache
# Build app and pack using upx
ADD . /app
RUN CGO_ENABLED=0 GOOS=linux GOARCH=amd64 go build -ldflags '-s -w -X main.VERSION=docker' -o gohttpserver && upx gohttpserver
FROM alpine:3
WORKDIR /app
ADD assets /usr/local/bin/assets
COPY --from=build /app/gohttpserver /usr/local/bin/gohttpserver
EXPOSE 8000
ENTRYPOINT [ "/usr/local/bin/gohttpserver" ]

6
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/text v0.3.3
golang.org/x/tools v0.1.0 // indirect
golang.org/x/net v0.23.0 // indirect
golang.org/x/text v0.14.0
howett.net/plist v0.0.0-20201203080718-1454fab16a06 // indirect
)

56
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,53 @@ 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=
github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY=
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/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
golang.org/x/crypto v0.19.0/go.mod h1:Iy9bg/ha4yyC70EfRS8jz+B6ybOBKMaSxLj6P6oBDfU=
golang.org/x/crypto v0.21.0/go.mod h1:0BP7YvVV9gBbVKyeTG0Gyn+gZm94bibOW5BjDEYAOMs=
golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4=
golang.org/x/mod v0.8.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs=
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/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c=
golang.org/x/net v0.6.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs=
golang.org/x/net v0.10.0/go.mod h1:0qNGK6F8kojg2nk9dLZ2mShWaEBan6FAoqfSigmmuDg=
golang.org/x/net v0.21.0/go.mod h1:bIjVDfnllIU7BJ2DNgfnXvpSvtn8VRwhlsaeUTyUS44=
golang.org/x/net v0.23.0 h1:7EYJ93RZ9vYSZAIb2x3lnuvqO5zneoD6IvWjuhfxjTs=
golang.org/x/net v0.23.0/go.mod h1:JKghWKKOSdJwpW2GEx0Ja7fmaKnMsbu+MWVZTokSYmg=
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/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.1.0/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/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.17.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
golang.org/x/sys v0.18.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k=
golang.org/x/term v0.8.0/go.mod h1:xPskH00ivmX89bAKVGSKKtLOWNx2+17Eiy94tnKShWo=
golang.org/x/term v0.17.0/go.mod h1:lLRBjIVuehSbZlaOtGMbcMncT+aqLLLmKrsjNrUguwk=
golang.org/x/term v0.18.0/go.mod h1:ILwASektA3OnRv7amZ1xhE/KTR+u50pbXfZ03+6Nx58=
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/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=
golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8=
golang.org/x/text v0.9.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8=
golang.org/x/text v0.14.0 h1:ScX5w1eTa3QqT8oi6+ziP7dTV1S2+ALU0bI+0zXKWiQ=
golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU=
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/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc=
golang.org/x/tools v0.6.0/go.mod h1:Xwgl3UAJ/d3gWutnCtw505GrjyAbvKui8lOU390QaIU=
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

@@ -42,23 +42,30 @@ type IndexFileItem struct {
Info os.FileInfo
}
type Directory struct {
size map[string]int64
mutex *sync.RWMutex
}
type HTTPStaticServer struct {
Root string
Prefix string
Upload bool
Delete bool
Title string
Theme string
PlistProxy string
GoogleTrackerID string
AuthType string
Root string
Prefix string
Upload bool
Delete bool
Title string
Theme string
PlistProxy string
GoogleTrackerID string
AuthType string
DeepPathMaxDepth int
NoIndex bool
indexes []IndexFileItem
m *mux.Router
bufPool sync.Pool // use sync.Pool caching buf to reduce gc ratio
}
func NewHTTPStaticServer(root string) *HTTPStaticServer {
func NewHTTPStaticServer(root string, noIndex bool) *HTTPStaticServer {
// if root == "" {
// root = "./"
// }
@@ -76,23 +83,27 @@ func NewHTTPStaticServer(root string) *HTTPStaticServer {
bufPool: sync.Pool{
New: func() interface{} { return make([]byte, 32*1024) },
},
NoIndex: noIndex,
}
go func() {
time.Sleep(1 * time.Second)
for {
startTime := time.Now()
log.Println("Started making search index")
s.makeIndex()
log.Printf("Completed search index in %v", time.Since(startTime))
//time.Sleep(time.Second * 1)
time.Sleep(time.Minute * 10)
}
}()
if !noIndex {
go func() {
time.Sleep(1 * time.Second)
for {
startTime := time.Now()
log.Println("Started making search index")
s.makeIndex()
log.Printf("Completed search index in %v", time.Since(startTime))
//time.Sleep(time.Second * 1)
time.Sleep(time.Minute * 10)
}
}()
}
// routers for Apple *.ipa
m.HandleFunc("/-/ipa/plist/{path:.*}", s.hPlist)
m.HandleFunc("/-/ipa/link/{path:.*}", s.hIpaLink)
m.HandleFunc("/-/video-player/{path:.*}", s.hVideoPlayer)
m.HandleFunc("/{path:.*}", s.hIndex).Methods("GET", "HEAD")
m.HandleFunc("/{path:.*}", s.hUploadOrMkdir).Methods("POST")
@@ -142,7 +153,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)
@@ -423,7 +434,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,
})
@@ -566,6 +577,7 @@ func (s *HTTPStaticServer) hJSONList(w http.ResponseWriter, r *http.Request) {
auth := s.readAccessConf(realPath)
auth.Upload = auth.canUpload(r)
auth.Delete = auth.canDelete(r)
maxDepth := s.DeepPathMaxDepth
// path string -> info os.FileInfo
fileInfoMap := make(map[string]os.FileInfo, 0)
@@ -610,7 +622,7 @@ func (s *HTTPStaticServer) hJSONList(w http.ResponseWriter, r *http.Request) {
lr.Name = filepath.ToSlash(name) // fix for windows
}
if info.IsDir() {
name := deepPath(realPath, info.Name())
name := deepPath(realPath, info.Name(), maxDepth)
lr.Name = name
lr.Path = filepath.Join(filepath.Dir(path), name)
lr.Type = "dir"
@@ -630,7 +642,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)
@@ -650,21 +662,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
}
@@ -728,11 +747,9 @@ func (s *HTTPStaticServer) readAccessConf(realPath string) (ac AccessConf) {
return
}
func deepPath(basedir, name string) string {
isDir := true
func deepPath(basedir, name string, maxDepth int) string {
// 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
@@ -784,7 +801,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
@@ -794,19 +811,34 @@ 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 \\/:*<>|")
}
return nil
}
func (s *HTTPStaticServer) hVideoPlayer(w http.ResponseWriter, r *http.Request) {
path := mux.Vars(r)["path"]
realPath := s.getRealPath(r)
extension := strings.ToLower(strings.TrimPrefix(filepath.Ext(path), "."))
if _, err := os.Stat(realPath); os.IsNotExist(err) {
http.Error(w, "File not found", http.StatusNotFound)
return
}
fileName := filepath.Base(path)
scheme := "http"
if r.TLS != nil {
scheme = "https"
}
videoURL := fmt.Sprintf("%s://%s/%s", scheme, r.Host, path)
renderHTML(w, "assets/video-player.html", map[string]interface{}{
"FileName": fileName,
"VideoURL": videoURL,
"Extension": extension,
})
}

74
main.go
View File

@@ -2,6 +2,8 @@ package main
import (
"bytes"
"crypto/sha256"
"crypto/subtle"
"encoding/json"
"fmt"
"io/ioutil"
@@ -22,7 +24,6 @@ import (
"github.com/goji/httpauth"
"github.com/gorilla/handlers"
"github.com/gorilla/mux"
_ "github.com/shurcooL/vfsgen"
)
type Configure struct {
@@ -34,7 +35,6 @@ type Configure struct {
HTTPAuth string `yaml:"httpauth"`
Cert string `yaml:"cert"`
Key string `yaml:"key"`
Cors bool `yaml:"cors"`
Theme string `yaml:"theme"`
XHeaders bool `yaml:"xheaders"`
Upload bool `yaml:"upload"`
@@ -44,12 +44,14 @@ type Configure struct {
Debug bool `yaml:"debug"`
GoogleTrackerID string `yaml:"google-tracker-id"`
Auth struct {
Type string `yaml:"type"` // openid|http|github
OpenID string `yaml:"openid"`
HTTP string `yaml:"http"`
ID string `yaml:"id"` // for oauth2
Secret string `yaml:"secret"` // for oauth2
Type string `yaml:"type"` // openid|http|github
OpenID string `yaml:"openid"`
HTTP []string `yaml:"http"`
ID string `yaml:"id"` // for oauth2
Secret string `yaml:"secret"` // for oauth2
} `yaml:"auth"`
DeepPathMaxDepth int `yaml:"deep-path-max-depth"`
NoIndex bool `yaml:"no-index"`
}
type httpLogger struct{}
@@ -100,6 +102,8 @@ func parseFlags() error {
gcfg.Auth.OpenID = defaultOpenID
gcfg.GoogleTrackerID = "UA-81205425-2"
gcfg.Title = "Go HTTP File Server"
gcfg.DeepPathMaxDepth = 5
gcfg.NoIndex = false
kingpin.HelpFlag.Short('h')
kingpin.Version(versionMessage())
@@ -111,17 +115,18 @@ func parseFlags() error {
kingpin.Flag("cert", "tls cert.pem path").StringVar(&gcfg.Cert)
kingpin.Flag("key", "tls key.pem path").StringVar(&gcfg.Key)
kingpin.Flag("auth-type", "Auth type <http|openid>").StringVar(&gcfg.Auth.Type)
kingpin.Flag("auth-http", "HTTP basic auth (ex: user:pass)").StringVar(&gcfg.Auth.HTTP)
kingpin.Flag("auth-http", "HTTP basic auth (ex: user:pass)").StringsVar(&gcfg.Auth.HTTP)
kingpin.Flag("auth-openid", "OpenID auth identity url").StringVar(&gcfg.Auth.OpenID)
kingpin.Flag("theme", "web theme, one of <black|green>").StringVar(&gcfg.Theme)
kingpin.Flag("upload", "enable upload support").BoolVar(&gcfg.Upload)
kingpin.Flag("delete", "enable delete support").BoolVar(&gcfg.Delete)
kingpin.Flag("xheaders", "used when behide nginx").BoolVar(&gcfg.XHeaders)
kingpin.Flag("cors", "enable cross-site HTTP request").BoolVar(&gcfg.Cors)
kingpin.Flag("debug", "enable debug mode").BoolVar(&gcfg.Debug)
kingpin.Flag("plistproxy", "plist proxy when server is not https").Short('p').StringVar(&gcfg.PlistProxy)
kingpin.Flag("title", "server title").StringVar(&gcfg.Title)
kingpin.Flag("google-tracker-id", "set to empty to disable it").StringVar(&gcfg.GoogleTrackerID)
kingpin.Flag("deep-path-max-depth", "set to -1 to not combine dirs").IntVar(&gcfg.DeepPathMaxDepth)
kingpin.Flag("no-index", "disable indexing").BoolVar(&gcfg.NoIndex)
kingpin.Parse() // first parse conf
@@ -149,6 +154,41 @@ func fixPrefix(prefix string) string {
return prefix
}
func cors(next http.Handler) http.Handler {
// access control and CORS middleware
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
w.Header().Set("Access-Control-Allow-Origin", "*")
w.Header().Set("Access-Control-Allow-Methods", "*")
w.Header().Set("Access-Control-Allow-Headers", "*")
if r.Method == "OPTIONS" {
return
}
next.ServeHTTP(w, r)
})
}
func multiBasicAuth(auths []string) func(http.Handler) http.Handler {
userPassMap := make(map[string]string)
for _, auth := range auths {
userpass := strings.SplitN(auth, ":", 2)
if len(userpass) == 2 {
userPassMap[userpass[0]] = userpass[1]
}
}
return httpauth.BasicAuth(httpauth.AuthOptions{
Realm: "Restricted",
AuthFunc: func(user, pass string, request *http.Request) bool {
password, ok := userPassMap[user]
if !ok {
return false
}
givenPass := sha256.Sum256([]byte(pass))
requiredPass := sha256.Sum256([]byte(password))
return subtle.ConstantTimeCompare(givenPass[:], requiredPass[:]) == 1
},
})
}
func main() {
if err := parseFlags(); err != nil {
log.Fatal(err)
@@ -165,7 +205,7 @@ func main() {
log.Printf("url prefix: %s", gcfg.Prefix)
}
ss := NewHTTPStaticServer(gcfg.Root)
ss := NewHTTPStaticServer(gcfg.Root, gcfg.NoIndex)
ss.Prefix = gcfg.Prefix
ss.Theme = gcfg.Theme
ss.Title = gcfg.Title
@@ -173,6 +213,7 @@ func main() {
ss.Upload = gcfg.Upload
ss.Delete = gcfg.Delete
ss.AuthType = gcfg.Auth.Type
ss.DeepPathMaxDepth = gcfg.DeepPathMaxDepth
if gcfg.PlistProxy != "" {
u, err := url.Parse(gcfg.PlistProxy)
@@ -191,13 +232,9 @@ func main() {
hdlr = accesslog.NewLoggingHandler(hdlr, logger)
// HTTP Basic Authentication
userpass := strings.SplitN(gcfg.Auth.HTTP, ":", 2)
switch gcfg.Auth.Type {
case "http":
if len(userpass) == 2 {
user, pass := userpass[0], userpass[1]
hdlr = httpauth.SimpleBasicAuth(user, pass)(hdlr)
}
hdlr = multiBasicAuth(gcfg.Auth.HTTP)(hdlr)
case "openid":
handleOpenID(gcfg.Auth.OpenID, false) // FIXME(ssx): set secure default to false
// case "github":
@@ -207,9 +244,8 @@ func main() {
}
// CORS
if gcfg.Cors {
hdlr = handlers.CORS()(hdlr)
}
hdlr = cors(hdlr)
if gcfg.XHeaders {
hdlr = handlers.ProxyHeaders(hdlr)
}
@@ -224,7 +260,7 @@ func main() {
})
}
router.PathPrefix("/-/assets/").Handler(http.StripPrefix(gcfg.Prefix+"/-/assets/", http.FileServer(Assets)))
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,

1
testdata/filetypes/script.js vendored Normal file
View File

@@ -0,0 +1 @@
document.write("Hello world!")