mirror of
https://github.com/dutchcoders/transfer.sh.git
synced 2020-11-18 19:53:40 -08:00
Compare commits
No commits in common. "master" and "v1.1.6" have entirely different histories.
89
.github/workflows/build-docker-images.yml
vendored
89
.github/workflows/build-docker-images.yml
vendored
@ -1,89 +0,0 @@
|
|||||||
name: Deploy multi-architecture Docker images for transfer.sh with buildx
|
|
||||||
|
|
||||||
on:
|
|
||||||
schedule:
|
|
||||||
- cron: '0 0 * * *' # everyday at midnight UTC
|
|
||||||
pull_request:
|
|
||||||
branches: master
|
|
||||||
push:
|
|
||||||
branches: master
|
|
||||||
tags:
|
|
||||||
- v*
|
|
||||||
|
|
||||||
jobs:
|
|
||||||
buildx:
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
steps:
|
|
||||||
-
|
|
||||||
name: Checkout
|
|
||||||
uses: actions/checkout@v2
|
|
||||||
-
|
|
||||||
name: Prepare
|
|
||||||
id: prepare
|
|
||||||
run: |
|
|
||||||
DOCKER_IMAGE=dutchcoders/transfer.sh
|
|
||||||
DOCKER_PLATFORMS=linux/amd64,linux/arm/v7,linux/arm64,linux/386
|
|
||||||
VERSION=edge
|
|
||||||
|
|
||||||
if [[ $GITHUB_REF == refs/tags/* ]]; then
|
|
||||||
VERSION=${GITHUB_REF#refs/tags/v}
|
|
||||||
fi
|
|
||||||
|
|
||||||
if [ "${{ github.event_name }}" = "schedule" ]; then
|
|
||||||
VERSION=nightly
|
|
||||||
fi
|
|
||||||
|
|
||||||
TAGS="--tag ${DOCKER_IMAGE}:${VERSION}"
|
|
||||||
|
|
||||||
if [ $VERSION = edge -o $VERSION = nightly ]; then
|
|
||||||
TAGS="$TAGS --tag ${DOCKER_IMAGE}:latest"
|
|
||||||
fi
|
|
||||||
|
|
||||||
echo ::set-output name=docker_image::${DOCKER_IMAGE}
|
|
||||||
echo ::set-output name=version::${VERSION}
|
|
||||||
echo ::set-output name=buildx_args::--platform ${DOCKER_PLATFORMS} \
|
|
||||||
--build-arg VERSION=${VERSION} \
|
|
||||||
--build-arg BUILD_DATE=$(date -u +'%Y-%m-%dT%H:%M:%SZ') \
|
|
||||||
--build-arg VCS_REF=${GITHUB_SHA::8} \
|
|
||||||
${TAGS} .
|
|
||||||
-
|
|
||||||
name: Set up QEMU
|
|
||||||
uses: docker/setup-qemu-action@v1
|
|
||||||
with:
|
|
||||||
platforms: all
|
|
||||||
-
|
|
||||||
name: Set up Docker Buildx
|
|
||||||
id: buildx
|
|
||||||
uses: docker/setup-buildx-action@v1
|
|
||||||
with:
|
|
||||||
version: latest
|
|
||||||
-
|
|
||||||
name: Available platforms
|
|
||||||
run: echo ${{ steps.buildx.outputs.platforms }}
|
|
||||||
-
|
|
||||||
name: Docker Buildx (build)
|
|
||||||
run: |
|
|
||||||
docker buildx build --no-cache --pull --output "type=image,push=false" ${{ steps.prepare.outputs.buildx_args }}
|
|
||||||
-
|
|
||||||
name: Docker Login
|
|
||||||
if: success() && github.event_name != 'pull_request'
|
|
||||||
env:
|
|
||||||
DOCKER_USERNAME: ${{ secrets.DOCKER_USERNAME }}
|
|
||||||
DOCKER_PASSWORD: ${{ secrets.DOCKER_PASSWORD }}
|
|
||||||
run: |
|
|
||||||
echo "${DOCKER_PASSWORD}" | docker login --username "${DOCKER_USERNAME}" --password-stdin
|
|
||||||
-
|
|
||||||
name: Docker Buildx (push)
|
|
||||||
if: success() && github.event_name != 'pull_request'
|
|
||||||
run: |
|
|
||||||
docker buildx build --output "type=image,push=true" ${{ steps.prepare.outputs.buildx_args }}
|
|
||||||
-
|
|
||||||
name: Docker Check Manifest
|
|
||||||
if: always() && github.event_name != 'pull_request'
|
|
||||||
run: |
|
|
||||||
docker run --rm mplatform/mquery ${{ steps.prepare.outputs.docker_image }}:${{ steps.prepare.outputs.version }}
|
|
||||||
-
|
|
||||||
name: Clear
|
|
||||||
if: always() && github.event_name != 'pull_request'
|
|
||||||
run: |
|
|
||||||
rm -f ${HOME}/.docker/config.json
|
|
@ -12,7 +12,7 @@ WORKDIR /go/src/github.com/dutchcoders/transfer.sh
|
|||||||
ENV GO111MODULE=on
|
ENV GO111MODULE=on
|
||||||
|
|
||||||
# build & install server
|
# build & install server
|
||||||
RUN go get -u ./... && CGO_ENABLED=0 go build -ldflags -a -tags netgo -ldflags '-w -extldflags "-static"' -o /go/bin/transfersh github.com/dutchcoders/transfer.sh
|
RUN go get -u ./... && CGO_ENABLED=0 GOOS=linux GOARCH=amd64 go build -ldflags -a -tags netgo -ldflags '-w -extldflags "-static"' -o /go/bin/transfersh github.com/dutchcoders/transfer.sh
|
||||||
|
|
||||||
FROM scratch AS final
|
FROM scratch AS final
|
||||||
LABEL maintainer="Andrea Spacca <andrea.spacca@gmail.com>"
|
LABEL maintainer="Andrea Spacca <andrea.spacca@gmail.com>"
|
||||||
|
66
README.md
66
README.md
@ -76,44 +76,40 @@ https://transfer.sh/1lDau/test.txt --> https://transfer.sh/inline/1lDau/test.txt
|
|||||||
|
|
||||||
Parameter | Description | Value | Env
|
Parameter | Description | Value | Env
|
||||||
--- | --- | --- | ---
|
--- | --- | --- | ---
|
||||||
listener | port to use for http (:80) | | LISTENER |
|
listener | port to use for http (:80) | |
|
||||||
profile-listener | port to use for profiler (:6060) | | PROFILE_LISTENER |
|
profile-listener | port to use for profiler (:6060)| |
|
||||||
force-https | redirect to https | false | FORCE_HTTPS
|
force-https | redirect to https | false |
|
||||||
tls-listener | port to use for https (:443) | | TLS_LISTENER |
|
tls-listener | port to use for https (:443) | |
|
||||||
tls-listener-only | flag to enable tls listener only | | TLS_LISTENER_ONLY |
|
tls-listener-only | flag to enable tls listener only | |
|
||||||
tls-cert-file | path to tls certificate | | TLS_CERT_FILE |
|
tls-cert-file | path to tls certificate | |
|
||||||
tls-private-key | path to tls private key | | TLS_PRIVATE_KEY |
|
tls-private-key | path to tls private key | |
|
||||||
http-auth-user | user for basic http auth on upload | | HTTP_AUTH_USER |
|
http-auth-user | user for basic http auth on upload | |
|
||||||
http-auth-pass | pass for basic http auth on upload | | HTTP_AUTH_PASS |
|
http-auth-pass | pass for basic http auth on upload | |
|
||||||
ip-whitelist | comma separated list of ips allowed to connect to the service | | IP_WHITELIST |
|
ip-whitelist | comma separated list of ips allowed to connect to the service | |
|
||||||
ip-blacklist | comma separated list of ips not allowed to connect to the service | | IP_BLACKLIST |
|
ip-blacklist | comma separated list of ips not allowed to connect to the service | |
|
||||||
temp-path | path to temp folder | system temp | TEMP_PATH |
|
temp-path | path to temp folder | system temp |
|
||||||
web-path | path to static web files (for development or custom front end) | | WEB_PATH |
|
web-path | path to static web files (for development or custom front end) | |
|
||||||
proxy-path | path prefix when service is run behind a proxy | | PROXY_PATH |
|
proxy-path | path prefix when service is run behind a proxy | |
|
||||||
proxy-port | port of the proxy when the service is run behind a proxy | | PROXY_PORT |
|
ga-key | google analytics key for the front end | |
|
||||||
ga-key | google analytics key for the front end | | GA_KEY |
|
uservoice-key | user voice key for the front end | |
|
||||||
uservoice-key | user voice key for the front end | | USERVOICE_KEY |
|
provider | which storage provider to use | (s3, gdrive or local) |
|
||||||
provider | which storage provider to use | (s3, gdrive or local) | PROVIDER |
|
aws-access-key | aws access key | | AWS_ACCESS_KEY
|
||||||
aws-access-key | aws access key | | AWS_ACCESS_KEY |
|
aws-secret-key | aws access key | | AWS_SECRET_KEY
|
||||||
aws-secret-key | aws access key | | AWS_SECRET_KEY |
|
bucket | aws bucket | | BUCKET
|
||||||
bucket | aws bucket | | BUCKET |
|
s3-endpoint | Custom S3 endpoint. | |
|
||||||
s3-endpoint | Custom S3 endpoint. | | S3_ENDPOINT |
|
s3-region | region of the s3 bucket | eu-west-1 | S3_REGION
|
||||||
s3-region | region of the s3 bucket | eu-west-1 | S3_REGION |
|
s3-no-multipart | disables s3 multipart upload | false | |
|
||||||
s3-no-multipart | disables s3 multipart upload | false | S3_NO_MULTIPART |
|
s3-path-style | Forces path style URLs, required for Minio. | false | |
|
||||||
s3-path-style | Forces path style URLs, required for Minio. | false | S3_PATH_STYLE |
|
basedir | path storage for local/gdrive provider| |
|
||||||
basedir | path storage for local/gdrive provider | | BASEDIR |
|
gdrive-client-json-filepath | path to oauth client json config for gdrive provider| |
|
||||||
gdrive-client-json-filepath | path to oauth client json config for gdrive provider | | GDRIVE_CLIENT_JSON_FILEPATH |
|
gdrive-local-config-path | path to store local transfer.sh config cache for gdrive provider| |
|
||||||
gdrive-local-config-path | path to store local transfer.sh config cache for gdrive provider| | GDRIVE_LOCAL_CONFIG_PATH |
|
gdrive-chunk-size | chunk size for gdrive upload in megabytes, must be lower than available memory (8 MB) | |
|
||||||
gdrive-chunk-size | chunk size for gdrive upload in megabytes, must be lower than available memory (8 MB) | | GDRIVE_CHUNK_SIZE |
|
lets-encrypt-hosts | hosts to use for lets encrypt certificates (comma seperated) | |
|
||||||
lets-encrypt-hosts | hosts to use for lets encrypt certificates (comma seperated) | | HOSTS |
|
log | path to log file| |
|
||||||
log | path to log file| | LOG |
|
|
||||||
cors-domains | comma separated list of domains for CORS, setting it enable CORS | | CORS_DOMAINS |
|
|
||||||
clamav-host | host for clamav feature | | CLAMAV_HOST |
|
|
||||||
rate-limit | request per minute | | RATE_LIMIT |
|
|
||||||
|
|
||||||
If you want to use TLS using lets encrypt certificates, set lets-encrypt-hosts to your domain, set tls-listener to :443 and enable force-https.
|
If you want to use TLS using lets encrypt certificates, set lets-encrypt-hosts to your domain, set tls-listener to :443 and enable force-https.
|
||||||
|
|
||||||
If you want to use TLS using your own certificates, set tls-listener to :443, force-https, tls-cert-file and tls-private-key.
|
If you want to use TLS using your own certificates, set tls-listener to :443, force-https, tls-cert=file and tls-private-key.
|
||||||
|
|
||||||
## Development
|
## Development
|
||||||
|
|
||||||
|
51
cmd/cmd.go
51
cmd/cmd.go
@ -12,7 +12,7 @@ import (
|
|||||||
"google.golang.org/api/googleapi"
|
"google.golang.org/api/googleapi"
|
||||||
)
|
)
|
||||||
|
|
||||||
var Version = "1.1.7"
|
var Version = "1.1.4"
|
||||||
var helpTemplate = `NAME:
|
var helpTemplate = `NAME:
|
||||||
{{.Name}} - {{.Usage}}
|
{{.Name}} - {{.Usage}}
|
||||||
|
|
||||||
@ -37,7 +37,6 @@ var globalFlags = []cli.Flag{
|
|||||||
Name: "listener",
|
Name: "listener",
|
||||||
Usage: "127.0.0.1:8080",
|
Usage: "127.0.0.1:8080",
|
||||||
Value: "127.0.0.1:8080",
|
Value: "127.0.0.1:8080",
|
||||||
EnvVar: "LISTENER",
|
|
||||||
},
|
},
|
||||||
// redirect to https?
|
// redirect to https?
|
||||||
// hostnames
|
// hostnames
|
||||||
@ -45,75 +44,57 @@ var globalFlags = []cli.Flag{
|
|||||||
Name: "profile-listener",
|
Name: "profile-listener",
|
||||||
Usage: "127.0.0.1:6060",
|
Usage: "127.0.0.1:6060",
|
||||||
Value: "",
|
Value: "",
|
||||||
EnvVar: "PROFILE_LISTENER",
|
|
||||||
},
|
},
|
||||||
cli.BoolFlag{
|
cli.BoolFlag{
|
||||||
Name: "force-https",
|
Name: "force-https",
|
||||||
Usage: "",
|
Usage: "",
|
||||||
EnvVar: "FORCE_HTTPS",
|
|
||||||
},
|
},
|
||||||
cli.StringFlag{
|
cli.StringFlag{
|
||||||
Name: "tls-listener",
|
Name: "tls-listener",
|
||||||
Usage: "127.0.0.1:8443",
|
Usage: "127.0.0.1:8443",
|
||||||
Value: "",
|
Value: "",
|
||||||
EnvVar: "TLS_LISTENER",
|
|
||||||
},
|
},
|
||||||
cli.BoolFlag{
|
cli.BoolFlag{
|
||||||
Name: "tls-listener-only",
|
Name: "tls-listener-only",
|
||||||
Usage: "",
|
Usage: "",
|
||||||
EnvVar: "TLS_LISTENER_ONLY",
|
|
||||||
},
|
},
|
||||||
cli.StringFlag{
|
cli.StringFlag{
|
||||||
Name: "tls-cert-file",
|
Name: "tls-cert-file",
|
||||||
Value: "",
|
Value: "",
|
||||||
EnvVar: "TLS_CERT_FILE",
|
|
||||||
},
|
},
|
||||||
cli.StringFlag{
|
cli.StringFlag{
|
||||||
Name: "tls-private-key",
|
Name: "tls-private-key",
|
||||||
Value: "",
|
Value: "",
|
||||||
EnvVar: "TLS_PRIVATE_KEY",
|
|
||||||
},
|
},
|
||||||
cli.StringFlag{
|
cli.StringFlag{
|
||||||
Name: "temp-path",
|
Name: "temp-path",
|
||||||
Usage: "path to temp files",
|
Usage: "path to temp files",
|
||||||
Value: os.TempDir(),
|
Value: os.TempDir(),
|
||||||
EnvVar: "TEMP_PATH",
|
|
||||||
},
|
},
|
||||||
cli.StringFlag{
|
cli.StringFlag{
|
||||||
Name: "web-path",
|
Name: "web-path",
|
||||||
Usage: "path to static web files",
|
Usage: "path to static web files",
|
||||||
Value: "",
|
Value: "",
|
||||||
EnvVar: "WEB_PATH",
|
|
||||||
},
|
},
|
||||||
cli.StringFlag{
|
cli.StringFlag{
|
||||||
Name: "proxy-path",
|
Name: "proxy-path",
|
||||||
Usage: "path prefix when service is run behind a proxy",
|
Usage: "path prefix when service is run behind a proxy",
|
||||||
Value: "",
|
Value: "",
|
||||||
EnvVar: "PROXY_PATH",
|
|
||||||
},
|
|
||||||
cli.StringFlag{
|
|
||||||
Name: "proxy-port",
|
|
||||||
Usage: "port of the proxy when the service is run behind a proxy",
|
|
||||||
Value: "",
|
|
||||||
EnvVar: "PROXY_PORT",
|
|
||||||
},
|
},
|
||||||
cli.StringFlag{
|
cli.StringFlag{
|
||||||
Name: "ga-key",
|
Name: "ga-key",
|
||||||
Usage: "key for google analytics (front end)",
|
Usage: "key for google analytics (front end)",
|
||||||
Value: "",
|
Value: "",
|
||||||
EnvVar: "GA_KEY",
|
|
||||||
},
|
},
|
||||||
cli.StringFlag{
|
cli.StringFlag{
|
||||||
Name: "uservoice-key",
|
Name: "uservoice-key",
|
||||||
Usage: "key for user voice (front end)",
|
Usage: "key for user voice (front end)",
|
||||||
Value: "",
|
Value: "",
|
||||||
EnvVar: "USERVOICE_KEY",
|
|
||||||
},
|
},
|
||||||
cli.StringFlag{
|
cli.StringFlag{
|
||||||
Name: "provider",
|
Name: "provider",
|
||||||
Usage: "s3|gdrive|local",
|
Usage: "s3|gdrive|local",
|
||||||
Value: "",
|
Value: "",
|
||||||
EnvVar: "PROVIDER",
|
|
||||||
},
|
},
|
||||||
cli.StringFlag{
|
cli.StringFlag{
|
||||||
Name: "s3-endpoint",
|
Name: "s3-endpoint",
|
||||||
@ -148,36 +129,31 @@ var globalFlags = []cli.Flag{
|
|||||||
cli.BoolFlag{
|
cli.BoolFlag{
|
||||||
Name: "s3-no-multipart",
|
Name: "s3-no-multipart",
|
||||||
Usage: "Disables S3 Multipart Puts",
|
Usage: "Disables S3 Multipart Puts",
|
||||||
EnvVar: "S3_NO_MULTIPART",
|
|
||||||
},
|
},
|
||||||
cli.BoolFlag{
|
cli.BoolFlag{
|
||||||
Name: "s3-path-style",
|
Name: "s3-path-style",
|
||||||
Usage: "Forces path style URLs, required for Minio.",
|
Usage: "Forces path style URLs, required for Minio.",
|
||||||
EnvVar: "S3_PATH_STYLE",
|
|
||||||
},
|
},
|
||||||
cli.StringFlag{
|
cli.StringFlag{
|
||||||
Name: "gdrive-client-json-filepath",
|
Name: "gdrive-client-json-filepath",
|
||||||
Usage: "",
|
Usage: "",
|
||||||
Value: "",
|
Value: "",
|
||||||
EnvVar: "GDRIVE_CLIENT_JSON_FILEPATH",
|
|
||||||
},
|
},
|
||||||
cli.StringFlag{
|
cli.StringFlag{
|
||||||
Name: "gdrive-local-config-path",
|
Name: "gdrive-local-config-path",
|
||||||
Usage: "",
|
Usage: "",
|
||||||
Value: "",
|
Value: "",
|
||||||
EnvVar: "GDRIVE_LOCAL_CONFIG_PATH",
|
|
||||||
},
|
},
|
||||||
cli.IntFlag{
|
cli.IntFlag{
|
||||||
Name: "gdrive-chunk-size",
|
Name: "gdrive-chunk-size",
|
||||||
Usage: "",
|
Usage: "",
|
||||||
Value: googleapi.DefaultUploadChunkSize / 1024 / 1024,
|
Value: googleapi.DefaultUploadChunkSize / 1024 / 1024,
|
||||||
EnvVar: "GDRIVE_CHUNK_SIZE",
|
|
||||||
},
|
},
|
||||||
cli.IntFlag{
|
cli.IntFlag{
|
||||||
Name: "rate-limit",
|
Name: "rate-limit",
|
||||||
Usage: "requests per minute",
|
Usage: "requests per minute",
|
||||||
Value: 0,
|
Value: 0,
|
||||||
EnvVar: "RATE_LIMIT",
|
EnvVar: "",
|
||||||
},
|
},
|
||||||
cli.StringFlag{
|
cli.StringFlag{
|
||||||
Name: "lets-encrypt-hosts",
|
Name: "lets-encrypt-hosts",
|
||||||
@ -189,13 +165,11 @@ var globalFlags = []cli.Flag{
|
|||||||
Name: "log",
|
Name: "log",
|
||||||
Usage: "/var/log/transfersh.log",
|
Usage: "/var/log/transfersh.log",
|
||||||
Value: "",
|
Value: "",
|
||||||
EnvVar: "LOG",
|
|
||||||
},
|
},
|
||||||
cli.StringFlag{
|
cli.StringFlag{
|
||||||
Name: "basedir",
|
Name: "basedir",
|
||||||
Usage: "path to storage",
|
Usage: "path to storage",
|
||||||
Value: "",
|
Value: "",
|
||||||
EnvVar: "BASEDIR",
|
|
||||||
},
|
},
|
||||||
cli.StringFlag{
|
cli.StringFlag{
|
||||||
Name: "clamav-host",
|
Name: "clamav-host",
|
||||||
@ -212,37 +186,26 @@ var globalFlags = []cli.Flag{
|
|||||||
cli.BoolFlag{
|
cli.BoolFlag{
|
||||||
Name: "profiler",
|
Name: "profiler",
|
||||||
Usage: "enable profiling",
|
Usage: "enable profiling",
|
||||||
EnvVar: "PROFILER",
|
|
||||||
},
|
},
|
||||||
cli.StringFlag{
|
cli.StringFlag{
|
||||||
Name: "http-auth-user",
|
Name: "http-auth-user",
|
||||||
Usage: "user for http basic auth",
|
Usage: "user for http basic auth",
|
||||||
Value: "",
|
Value: "",
|
||||||
EnvVar: "HTTP_AUTH_USER",
|
|
||||||
},
|
},
|
||||||
cli.StringFlag{
|
cli.StringFlag{
|
||||||
Name: "http-auth-pass",
|
Name: "http-auth-pass",
|
||||||
Usage: "pass for http basic auth",
|
Usage: "pass for http basic auth",
|
||||||
Value: "",
|
Value: "",
|
||||||
EnvVar: "HTTP_AUTH_PASS",
|
|
||||||
},
|
},
|
||||||
cli.StringFlag{
|
cli.StringFlag{
|
||||||
Name: "ip-whitelist",
|
Name: "ip-whitelist",
|
||||||
Usage: "comma separated list of ips allowed to connect to the service",
|
Usage: "comma separated list of ips allowed to connect to the service",
|
||||||
Value: "",
|
Value: "",
|
||||||
EnvVar: "IP_WHITELIST",
|
|
||||||
},
|
},
|
||||||
cli.StringFlag{
|
cli.StringFlag{
|
||||||
Name: "ip-blacklist",
|
Name: "ip-blacklist",
|
||||||
Usage: "comma separated list of ips not allowed to connect to the service",
|
Usage: "comma separated list of ips not allowed to connect to the service",
|
||||||
Value: "",
|
Value: "",
|
||||||
EnvVar: "IP_BLACKLIST",
|
|
||||||
},
|
|
||||||
cli.StringFlag{
|
|
||||||
Name: "cors-domains",
|
|
||||||
Usage: "comma separated list of domains allowed for CORS requests",
|
|
||||||
Value: "",
|
|
||||||
EnvVar: "CORS_DOMAINS",
|
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -251,7 +214,7 @@ type Cmd struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func VersionAction(c *cli.Context) {
|
func VersionAction(c *cli.Context) {
|
||||||
fmt.Println(color.YellowString(fmt.Sprintf("transfer.sh %s: Easy file sharing from the command line", Version)))
|
fmt.Println(color.YellowString(fmt.Sprintf("transfer.sh: Easy file sharing from the command line")))
|
||||||
}
|
}
|
||||||
|
|
||||||
func New() *Cmd {
|
func New() *Cmd {
|
||||||
@ -282,10 +245,6 @@ func New() *Cmd {
|
|||||||
options = append(options, server.Listener(v))
|
options = append(options, server.Listener(v))
|
||||||
}
|
}
|
||||||
|
|
||||||
if v := c.String("cors-domains"); v != "" {
|
|
||||||
options = append(options, server.CorsDomains(v))
|
|
||||||
}
|
|
||||||
|
|
||||||
if v := c.String("tls-listener"); v == "" {
|
if v := c.String("tls-listener"); v == "" {
|
||||||
} else if c.Bool("tls-listener-only") {
|
} else if c.Bool("tls-listener-only") {
|
||||||
options = append(options, server.TLSListener(v, true))
|
options = append(options, server.TLSListener(v, true))
|
||||||
@ -305,10 +264,6 @@ func New() *Cmd {
|
|||||||
options = append(options, server.ProxyPath(v))
|
options = append(options, server.ProxyPath(v))
|
||||||
}
|
}
|
||||||
|
|
||||||
if v := c.String("proxy-port"); v != "" {
|
|
||||||
options = append(options, server.ProxyPort(v))
|
|
||||||
}
|
|
||||||
|
|
||||||
if v := c.String("ga-key"); v != "" {
|
if v := c.String("ga-key"); v != "" {
|
||||||
options = append(options, server.GoogleAnalytics(v))
|
options = append(options, server.GoogleAnalytics(v))
|
||||||
}
|
}
|
||||||
|
1
go.mod
1
go.mod
@ -16,7 +16,6 @@ require (
|
|||||||
github.com/garyburd/redigo v1.6.0 // indirect
|
github.com/garyburd/redigo v1.6.0 // indirect
|
||||||
github.com/golang/gddo v0.0.0-20200310004957-95ce5a452273
|
github.com/golang/gddo v0.0.0-20200310004957-95ce5a452273
|
||||||
github.com/golang/protobuf v1.3.5 // indirect
|
github.com/golang/protobuf v1.3.5 // indirect
|
||||||
github.com/gorilla/handlers v1.4.2
|
|
||||||
github.com/gorilla/mux v1.7.4
|
github.com/gorilla/mux v1.7.4
|
||||||
github.com/gorilla/securecookie v1.1.1 // indirect
|
github.com/gorilla/securecookie v1.1.1 // indirect
|
||||||
github.com/hashicorp/golang-lru v0.5.3 // indirect
|
github.com/hashicorp/golang-lru v0.5.3 // indirect
|
||||||
|
2
go.sum
2
go.sum
@ -127,8 +127,6 @@ github.com/googleapis/gax-go v2.0.0+incompatible/go.mod h1:SFVmujtThgffbyetf+mdk
|
|||||||
github.com/googleapis/gax-go/v2 v2.0.4/go.mod h1:0Wqv26UfaUD9n4G6kQubkQ+KchISgw+vpHVxEJEs9eg=
|
github.com/googleapis/gax-go/v2 v2.0.4/go.mod h1:0Wqv26UfaUD9n4G6kQubkQ+KchISgw+vpHVxEJEs9eg=
|
||||||
github.com/googleapis/gax-go/v2 v2.0.5 h1:sjZBwGj9Jlw33ImPtvFviGYvseOtDM7hkSKB7+Tv3SM=
|
github.com/googleapis/gax-go/v2 v2.0.5 h1:sjZBwGj9Jlw33ImPtvFviGYvseOtDM7hkSKB7+Tv3SM=
|
||||||
github.com/googleapis/gax-go/v2 v2.0.5/go.mod h1:DWXyrwAJ9X0FpwwEdw+IPEYBICEFu5mhpdKc/us6bOk=
|
github.com/googleapis/gax-go/v2 v2.0.5/go.mod h1:DWXyrwAJ9X0FpwwEdw+IPEYBICEFu5mhpdKc/us6bOk=
|
||||||
github.com/gorilla/handlers v1.4.2 h1:0QniY0USkHQ1RGCLfKxeNHK9bkDHGRYGNDFBCS+YARg=
|
|
||||||
github.com/gorilla/handlers v1.4.2/go.mod h1:Qkdc/uu4tH4g6mTK6auzZ766c4CA0Ng8+o/OAirnOIQ=
|
|
||||||
github.com/gorilla/mux v1.7.3 h1:gnP5JzjVOuiZD07fKKToCAOjS0yOpj/qPETTXCCS6hw=
|
github.com/gorilla/mux v1.7.3 h1:gnP5JzjVOuiZD07fKKToCAOjS0yOpj/qPETTXCCS6hw=
|
||||||
github.com/gorilla/mux v1.7.3/go.mod h1:1lud6UwP+6orDFRuTfBEV8e9/aOM/c4fVVCaMa2zaAs=
|
github.com/gorilla/mux v1.7.3/go.mod h1:1lud6UwP+6orDFRuTfBEV8e9/aOM/c4fVVCaMa2zaAs=
|
||||||
github.com/gorilla/mux v1.7.4 h1:VuZ8uybHlWmqV03+zRzdwKL4tUnIp1MAQtp1mIFE1bc=
|
github.com/gorilla/mux v1.7.4 h1:VuZ8uybHlWmqV03+zRzdwKL4tUnIp1MAQtp1mIFE1bc=
|
||||||
|
@ -158,9 +158,9 @@ func (s *Server) previewHandler(w http.ResponseWriter, r *http.Request) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
relativeURL, _ := url.Parse(path.Join(s.proxyPath, token, filename))
|
relativeURL, _ := url.Parse(path.Join(s.proxyPath, token, filename))
|
||||||
resolvedURL := resolveURL(r, relativeURL, s.proxyPort)
|
resolvedURL := resolveURL(r, relativeURL)
|
||||||
relativeURLGet, _ := url.Parse(path.Join(s.proxyPath, getPathPart, token, filename))
|
relativeURLGet, _ := url.Parse(path.Join(s.proxyPath, getPathPart, token, filename))
|
||||||
resolvedURLGet := resolveURL(r, relativeURLGet, s.proxyPort)
|
resolvedURLGet := resolveURL(r, relativeURLGet)
|
||||||
var png []byte
|
var png []byte
|
||||||
png, err = qrcode.Encode(resolvedURL, qrcode.High, 150)
|
png, err = qrcode.Encode(resolvedURL, qrcode.High, 150)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -170,8 +170,8 @@ func (s *Server) previewHandler(w http.ResponseWriter, r *http.Request) {
|
|||||||
|
|
||||||
qrCode := base64.StdEncoding.EncodeToString(png)
|
qrCode := base64.StdEncoding.EncodeToString(png)
|
||||||
|
|
||||||
hostname := getURL(r, s.proxyPort).Host
|
hostname := getURL(r).Host
|
||||||
webAddress := resolveWebAddress(r, s.proxyPath, s.proxyPort)
|
webAddress := resolveWebAddress(r, s.proxyPath)
|
||||||
|
|
||||||
data := struct {
|
data := struct {
|
||||||
ContentType string
|
ContentType string
|
||||||
@ -212,8 +212,8 @@ func (s *Server) previewHandler(w http.ResponseWriter, r *http.Request) {
|
|||||||
func (s *Server) viewHandler(w http.ResponseWriter, r *http.Request) {
|
func (s *Server) viewHandler(w http.ResponseWriter, r *http.Request) {
|
||||||
// vars := mux.Vars(r)
|
// vars := mux.Vars(r)
|
||||||
|
|
||||||
hostname := getURL(r, s.proxyPort).Host
|
hostname := getURL(r).Host
|
||||||
webAddress := resolveWebAddress(r, s.proxyPath, s.proxyPort)
|
webAddress := resolveWebAddress(r, s.proxyPath)
|
||||||
|
|
||||||
data := struct {
|
data := struct {
|
||||||
Hostname string
|
Hostname string
|
||||||
@ -339,7 +339,7 @@ func (s *Server) postHandler(w http.ResponseWriter, r *http.Request) {
|
|||||||
|
|
||||||
filename = url.PathEscape(filename)
|
filename = url.PathEscape(filename)
|
||||||
relativeURL, _ := url.Parse(path.Join(s.proxyPath, token, filename))
|
relativeURL, _ := url.Parse(path.Join(s.proxyPath, token, filename))
|
||||||
fmt.Fprintln(w, getURL(r, s.proxyPort).ResolveReference(relativeURL).String())
|
fmt.Fprintln(w, getURL(r).ResolveReference(relativeURL).String())
|
||||||
|
|
||||||
cleanTmpFile(file)
|
cleanTmpFile(file)
|
||||||
}
|
}
|
||||||
@ -500,15 +500,15 @@ func (s *Server) putHandler(w http.ResponseWriter, r *http.Request) {
|
|||||||
relativeURL, _ := url.Parse(path.Join(s.proxyPath, token, filename))
|
relativeURL, _ := url.Parse(path.Join(s.proxyPath, token, filename))
|
||||||
deleteURL, _ := url.Parse(path.Join(s.proxyPath, token, filename, metadata.DeletionToken))
|
deleteURL, _ := url.Parse(path.Join(s.proxyPath, token, filename, metadata.DeletionToken))
|
||||||
|
|
||||||
w.Header().Set("X-Url-Delete", resolveURL(r, deleteURL, s.proxyPort))
|
w.Header().Set("X-Url-Delete", resolveURL(r, deleteURL))
|
||||||
|
|
||||||
fmt.Fprint(w, resolveURL(r, relativeURL, s.proxyPort))
|
fmt.Fprint(w, resolveURL(r, relativeURL))
|
||||||
}
|
}
|
||||||
|
|
||||||
func resolveURL(r *http.Request, u *url.URL, proxyPort string) string {
|
func resolveURL(r *http.Request, u *url.URL) string {
|
||||||
r.URL.Path = ""
|
r.URL.Path = ""
|
||||||
|
|
||||||
return getURL(r, proxyPort).ResolveReference(u).String()
|
return getURL(r).ResolveReference(u).String()
|
||||||
}
|
}
|
||||||
|
|
||||||
func resolveKey(key, proxyPath string) string {
|
func resolveKey(key, proxyPath string) string {
|
||||||
@ -525,8 +525,8 @@ func resolveKey(key, proxyPath string) string {
|
|||||||
return key
|
return key
|
||||||
}
|
}
|
||||||
|
|
||||||
func resolveWebAddress(r *http.Request, proxyPath string, proxyPort string) string {
|
func resolveWebAddress(r *http.Request, proxyPath string) string {
|
||||||
url := getURL(r, proxyPort)
|
url := getURL(r)
|
||||||
|
|
||||||
var webAddress string
|
var webAddress string
|
||||||
|
|
||||||
@ -544,7 +544,7 @@ func resolveWebAddress(r *http.Request, proxyPath string, proxyPort string) stri
|
|||||||
return webAddress
|
return webAddress
|
||||||
}
|
}
|
||||||
|
|
||||||
func getURL(r *http.Request, proxyPort string) *url.URL {
|
func getURL(r *http.Request) *url.URL {
|
||||||
u, _ := url.Parse(r.URL.String())
|
u, _ := url.Parse(r.URL.String())
|
||||||
|
|
||||||
if r.TLS != nil {
|
if r.TLS != nil {
|
||||||
@ -555,25 +555,16 @@ func getURL(r *http.Request, proxyPort string) *url.URL {
|
|||||||
u.Scheme = "http"
|
u.Scheme = "http"
|
||||||
}
|
}
|
||||||
|
|
||||||
if u.Host == "" {
|
if u.Host != "" {
|
||||||
host, port, err := net.SplitHostPort(r.Host)
|
} else if host, port, err := net.SplitHostPort(r.Host); err != nil {
|
||||||
if err != nil {
|
u.Host = r.Host
|
||||||
host = r.Host
|
} else {
|
||||||
port = ""
|
if port == "80" && u.Scheme == "http" {
|
||||||
}
|
u.Host = host
|
||||||
if len(proxyPort) != 0 {
|
} else if port == "443" && u.Scheme == "https" {
|
||||||
port = proxyPort
|
|
||||||
}
|
|
||||||
if len(port) == 0 {
|
|
||||||
u.Host = host
|
u.Host = host
|
||||||
} else {
|
} else {
|
||||||
if port == "80" && u.Scheme == "http" {
|
u.Host = net.JoinHostPort(host, port)
|
||||||
u.Host = host
|
|
||||||
} else if port == "443" && u.Scheme == "https" {
|
|
||||||
u.Host = host
|
|
||||||
} else {
|
|
||||||
u.Host = net.JoinHostPort(host, port)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -623,7 +614,9 @@ func (s *Server) CheckMetadata(token, filename string, increaseDownload bool) (M
|
|||||||
var metadata Metadata
|
var metadata Metadata
|
||||||
|
|
||||||
r, _, err := s.storage.Get(token, fmt.Sprintf("%s.metadata", filename))
|
r, _, err := s.storage.Get(token, fmt.Sprintf("%s.metadata", filename))
|
||||||
if err != nil {
|
if s.storage.IsNotExist(err) {
|
||||||
|
return metadata, nil
|
||||||
|
} else if err != nil {
|
||||||
return metadata, err
|
return metadata, err
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1018,7 +1011,7 @@ func (s *Server) RedirectHandler(h http.Handler) http.HandlerFunc {
|
|||||||
} else if r.Header.Get("X-Forwarded-Proto") == "https" {
|
} else if r.Header.Get("X-Forwarded-Proto") == "https" {
|
||||||
} else if r.URL.Scheme == "https" {
|
} else if r.URL.Scheme == "https" {
|
||||||
} else {
|
} else {
|
||||||
u := getURL(r, s.proxyPort)
|
u := getURL(r)
|
||||||
u.Scheme = "https"
|
u.Scheme = "https"
|
||||||
|
|
||||||
http.Redirect(w, r, u.String(), http.StatusPermanentRedirect)
|
http.Redirect(w, r, u.String(), http.StatusPermanentRedirect)
|
||||||
|
@ -26,10 +26,7 @@ package server
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"errors"
|
"errors"
|
||||||
gorillaHandlers "github.com/gorilla/handlers"
|
|
||||||
"log"
|
"log"
|
||||||
crypto_rand "crypto/rand"
|
|
||||||
"encoding/binary"
|
|
||||||
"math/rand"
|
"math/rand"
|
||||||
"mime"
|
"mime"
|
||||||
"net/http"
|
"net/http"
|
||||||
@ -88,13 +85,6 @@ func Listener(s string) OptionFn {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func CorsDomains(s string) OptionFn {
|
|
||||||
return func(srvr *Server) {
|
|
||||||
srvr.CorsDomains = s
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
func GoogleAnalytics(gaKey string) OptionFn {
|
func GoogleAnalytics(gaKey string) OptionFn {
|
||||||
return func(srvr *Server) {
|
return func(srvr *Server) {
|
||||||
srvr.gaKey = gaKey
|
srvr.gaKey = gaKey
|
||||||
@ -141,12 +131,6 @@ func ProxyPath(s string) OptionFn {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func ProxyPort(s string) OptionFn {
|
|
||||||
return func(srvr *Server) {
|
|
||||||
srvr.proxyPort = s
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TempPath(s string) OptionFn {
|
func TempPath(s string) OptionFn {
|
||||||
return func(srvr *Server) {
|
return func(srvr *Server) {
|
||||||
if s[len(s)-1:] != "/" {
|
if s[len(s)-1:] != "/" {
|
||||||
@ -286,13 +270,11 @@ type Server struct {
|
|||||||
|
|
||||||
webPath string
|
webPath string
|
||||||
proxyPath string
|
proxyPath string
|
||||||
proxyPort string
|
|
||||||
gaKey string
|
gaKey string
|
||||||
userVoiceKey string
|
userVoiceKey string
|
||||||
|
|
||||||
TLSListenerOnly bool
|
TLSListenerOnly bool
|
||||||
|
|
||||||
CorsDomains string
|
|
||||||
ListenerString string
|
ListenerString string
|
||||||
TLSListenerString string
|
TLSListenerString string
|
||||||
ProfileListenerString string
|
ProfileListenerString string
|
||||||
@ -315,11 +297,7 @@ func New(options ...OptionFn) (*Server, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
var seedBytes [8]byte
|
rand.Seed(time.Now().UTC().UnixNano())
|
||||||
if _, err := crypto_rand.Read(seedBytes[:]); err != nil {
|
|
||||||
panic("cannot obtain cryptographically secure seed")
|
|
||||||
}
|
|
||||||
rand.Seed(int64(binary.LittleEndian.Uint64(seedBytes[:])))
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *Server) Run() {
|
func (s *Server) Run() {
|
||||||
@ -435,24 +413,11 @@ func (s *Server) Run() {
|
|||||||
|
|
||||||
s.logger.Printf("Transfer.sh server started.\nusing temp folder: %s\nusing storage provider: %s", s.tempPath, s.storage.Type())
|
s.logger.Printf("Transfer.sh server started.\nusing temp folder: %s\nusing storage provider: %s", s.tempPath, s.storage.Type())
|
||||||
|
|
||||||
var cors func(http.Handler) http.Handler
|
|
||||||
if len(s.CorsDomains) > 0 {
|
|
||||||
cors = gorillaHandlers.CORS(
|
|
||||||
gorillaHandlers.AllowedHeaders([]string{"*"}),
|
|
||||||
gorillaHandlers.AllowedOrigins(strings.Split(s.CorsDomains, ",")),
|
|
||||||
gorillaHandlers.AllowedMethods([]string{"GET", "HEAD", "POST", "PUT", "DELETE", "OPTIONS"}),
|
|
||||||
)
|
|
||||||
} else {
|
|
||||||
cors = func(h http.Handler) http.Handler {
|
|
||||||
return h
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
h := handlers.PanicHandler(
|
h := handlers.PanicHandler(
|
||||||
IPFilterHandler(
|
IPFilterHandler(
|
||||||
handlers.LogHandler(
|
handlers.LogHandler(
|
||||||
LoveHandler(
|
LoveHandler(
|
||||||
s.RedirectHandler(cors(r))),
|
s.RedirectHandler(r)),
|
||||||
handlers.NewLogOptions(s.logger.Printf, "_default_"),
|
handlers.NewLogOptions(s.logger.Printf, "_default_"),
|
||||||
),
|
),
|
||||||
s.ipFilterOptions,
|
s.ipFilterOptions,
|
||||||
|
Loading…
x
Reference in New Issue
Block a user