Skip to content

Commit

Permalink
fix: upload memory optimization; refactor flag parsing; begin separat…
Browse files Browse the repository at this point in the history
  • Loading branch information
fsrv-xyz committed Dec 13, 2023
2 parents 1f03f15 + 7e514c2 commit 87f9055
Show file tree
Hide file tree
Showing 16 changed files with 277 additions and 186 deletions.
5 changes: 5 additions & 0 deletions .dockerignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
example
.it
.gitlab-ci.yml
.gitlab
.github
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,3 +1,6 @@
/.idea
/transfer
/coverage
/example/data/transfer
!/example/data/transfer/.gitkeep
/example/data/.minio.sys
1 change: 1 addition & 0 deletions .gitlab-ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,7 @@ Integration Tests:
artifacts: true
variables:
TESTFMT_VERSION: 1.0.2
DEFAULT_INGRESS_URL: "https://${DEFAULT_INGRESS_URL}"
before_script:
- (apt update && apt install -y curl wget) > /dev/null
- wget -q "https://github.com/bonsai-oss/testfmt/releases/download/v${TESTFMT_VERSION}/testfmt_${TESTFMT_VERSION}_linux_amd64" -O testfmt && chmod +x testfmt
Expand Down
2 changes: 1 addition & 1 deletion .it/functions.sh
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
#!/usr/bin/env bash

declare -r URL="https://${DEFAULT_INGRESS_URL}"
declare URL="${DEFAULT_INGRESS_URL}"

function generate_test_file() {
local -r file_name="$1"
Expand Down
2 changes: 1 addition & 1 deletion .it/kubernetes/deployment.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ spec:
command:
- /app/transfer
args:
- -link.prefix
- --link.prefix
- https
ports:
- containerPort: 8080
Expand Down
2 changes: 1 addition & 1 deletion Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -21,4 +21,4 @@ ENV AWS_ACCESS_KEY_ID="minio"
ENV AWS_SECRET_ACCESS_KEY="minio123"
COPY --from=builder /build/transfer /app/transfer
COPY --from=certs /etc/ssl/certs/ca-certificates.crt /etc/ssl/certs/
CMD ["/app/transfer", "-web.listen-address", ":8080", "-metrics.listen-address", ":8081"]
CMD ["/app/transfer", "--web.listen-address", ":8080", "--metrics.listen-address", ":8081"]
7 changes: 5 additions & 2 deletions example/docker-compose.yml
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
version: '3.7'
services:
minio:
image: quay.io/minio/minio:RELEASE.2021-11-09T03-21-45Z
image: quay.io/minio/minio:latest
command: server --console-address ":9001" /data
hostname: minio
environment:
Expand All @@ -17,7 +17,10 @@ services:
retries: 3

transfer:
image: fsrv/transfer@sha256:3954c1425f289288b4b868ed339f9964e64b3454dd40781a73ff5f5ad51dddf3
build: ../
hostname: transfer
environment:
S3_SECURE: 'false'
ports:
- "8080:8080"
- "8081:8081"
24 changes: 13 additions & 11 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ module transfer
go 1.21

require (
github.com/alecthomas/kingpin/v2 v2.4.0
github.com/bonsai-oss/mux v1.8.1
github.com/fsrv-xyz/version v0.0.1
github.com/getsentry/sentry-go v0.25.0
Expand All @@ -12,27 +13,28 @@ require (
)

require (
github.com/alecthomas/units v0.0.0-20231202071711-9a357b53e9c9 // indirect
github.com/beorn7/perks v1.0.1 // indirect
github.com/cespare/xxhash/v2 v2.2.0 // indirect
github.com/dustin/go-humanize v1.0.1 // indirect
github.com/golang/protobuf v1.5.3 // indirect
github.com/json-iterator/go v1.1.12 // indirect
github.com/klauspost/compress v1.16.7 // indirect
github.com/klauspost/cpuid/v2 v2.2.5 // indirect
github.com/matttproud/golang_protobuf_extensions v1.0.4 // indirect
github.com/klauspost/compress v1.17.4 // indirect
github.com/klauspost/cpuid/v2 v2.2.6 // indirect
github.com/matttproud/golang_protobuf_extensions/v2 v2.0.0 // indirect
github.com/minio/md5-simd v1.1.2 // indirect
github.com/minio/sha256-simd v1.0.1 // indirect
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect
github.com/modern-go/reflect2 v1.0.2 // indirect
github.com/prometheus/client_model v0.4.1-0.20230718164431-9a2bf3000d16 // indirect
github.com/prometheus/common v0.44.0 // indirect
github.com/prometheus/procfs v0.11.1 // indirect
github.com/prometheus/client_model v0.5.0 // indirect
github.com/prometheus/common v0.45.0 // indirect
github.com/prometheus/procfs v0.12.0 // indirect
github.com/rs/xid v1.5.0 // indirect
github.com/sirupsen/logrus v1.9.3 // indirect
golang.org/x/crypto v0.14.0 // indirect
golang.org/x/net v0.17.0 // indirect
golang.org/x/sys v0.13.0 // indirect
golang.org/x/text v0.13.0 // indirect
github.com/xhit/go-str2duration/v2 v2.1.0 // indirect
golang.org/x/crypto v0.16.0 // indirect
golang.org/x/net v0.19.0 // indirect
golang.org/x/sys v0.15.0 // indirect
golang.org/x/text v0.14.0 // indirect
google.golang.org/protobuf v1.31.0 // indirect
gopkg.in/ini.v1 v1.67.0 // indirect
)
53 changes: 28 additions & 25 deletions go.sum
Original file line number Diff line number Diff line change
@@ -1,3 +1,7 @@
github.com/alecthomas/kingpin/v2 v2.4.0 h1:f48lwail6p8zpO1bC4TxtqACaGqHYA22qkHjHpqDjYY=
github.com/alecthomas/kingpin/v2 v2.4.0/go.mod h1:0gyi0zQnjuFk8xrkNKamJoyUo382HRL7ATRpFZCw6tE=
github.com/alecthomas/units v0.0.0-20231202071711-9a357b53e9c9 h1:ez/4by2iGztzR4L0zgAOR8lTQK9VlyBVVd7G4omaOQs=
github.com/alecthomas/units v0.0.0-20231202071711-9a357b53e9c9/go.mod h1:OMCwj8VM1Kc9e19TLln2VL61YJF0x1XFtfdL4JdbSyE=
github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM=
github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw=
github.com/bonsai-oss/mux v1.8.1 h1:+oCx4bLXEkn6O8Gyse39m2XH7AWWH/u9Rn9vSO3dwYU=
Expand All @@ -15,10 +19,7 @@ github.com/getsentry/sentry-go v0.25.0 h1:q6Eo+hS+yoJlTO3uu/azhQadsD8V+jQn2D8VvX
github.com/getsentry/sentry-go v0.25.0/go.mod h1:lc76E2QywIyW8WuBnwl8Lc4bkmQH4+w1gwTf25trprY=
github.com/go-errors/errors v1.4.2 h1:J6MZopCL4uSllY1OfXM374weqZFFItUbrImctkmUxIA=
github.com/go-errors/errors v1.4.2/go.mod h1:sIVyrIiJhuEF+Pj9Ebtd6P/rEYROXFi3BopGUQ5a5Og=
github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk=
github.com/golang/protobuf v1.5.3 h1:KhyjKVUg7Usr/dYsdSqoFveMYd5ko72D+zANwlG1mmg=
github.com/golang/protobuf v1.5.3/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY=
github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/go-cmp v0.5.9 h1:O2Tfq5qg4qc4AmwVlvv0oLiVAGB7enBSJ2x2DqQFi38=
github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
Expand All @@ -27,13 +28,13 @@ github.com/google/uuid v1.4.0 h1:MtMxsa51/r9yyhkyLsVeVt0B+BGQZzpQiTQ4eHZ8bc4=
github.com/google/uuid v1.4.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
github.com/json-iterator/go v1.1.12 h1:PV8peI4a0ysnczrg+LtxykD8LfKY9ML6u2jnxaEnrnM=
github.com/json-iterator/go v1.1.12/go.mod h1:e30LSqwooZae/UwlEbR2852Gd8hjQvJoHmT4TnhNGBo=
github.com/klauspost/compress v1.16.7 h1:2mk3MPGNzKyxErAw8YaohYh69+pa4sIQSC0fPGCFR9I=
github.com/klauspost/compress v1.16.7/go.mod h1:ntbaceVETuRiXiv4DpjP66DpAtAGkEQskQzEyD//IeE=
github.com/klauspost/compress v1.17.4 h1:Ej5ixsIri7BrIjBkRZLTo6ghwrEtHFk7ijlczPW4fZ4=
github.com/klauspost/compress v1.17.4/go.mod h1:/dCuZOvVtNoHsyb+cuJD3itjs3NbnF6KH9zAO4BDxPM=
github.com/klauspost/cpuid/v2 v2.0.1/go.mod h1:FInQzS24/EEf25PyTYn52gqo7WaD8xa0213Md/qVLRg=
github.com/klauspost/cpuid/v2 v2.2.5 h1:0E5MSMDEoAulmXNFquVs//DdoomxaoTY1kUhbc/qbZg=
github.com/klauspost/cpuid/v2 v2.2.5/go.mod h1:Lcz8mBdAVJIBVzewtcLocK12l3Y+JytZYpaMropDUws=
github.com/matttproud/golang_protobuf_extensions v1.0.4 h1:mmDVorXM7PCGKw94cs5zkfA9PSy5pEvNWRP0ET0TIVo=
github.com/matttproud/golang_protobuf_extensions v1.0.4/go.mod h1:BSXmuO+STAnVfrANrmjBb36TMTDstsz7MSK+HVaYKv4=
github.com/klauspost/cpuid/v2 v2.2.6 h1:ndNyv040zDGIDh8thGkXYjnFtiN02M1PVVF+JE/48xc=
github.com/klauspost/cpuid/v2 v2.2.6/go.mod h1:Lcz8mBdAVJIBVzewtcLocK12l3Y+JytZYpaMropDUws=
github.com/matttproud/golang_protobuf_extensions/v2 v2.0.0 h1:jWpvCLoY8Z/e3VKvlsiIGKtc+UG6U5vzxaoagmhXfyg=
github.com/matttproud/golang_protobuf_extensions/v2 v2.0.0/go.mod h1:QUyp042oQthUoa9bqDv0ER0wrtXnBruoNd7aNjkbP+k=
github.com/minio/md5-simd v1.1.2 h1:Gdi1DZK69+ZVMoNHRXJyNcxrMA4dSxoYHZSQbirFg34=
github.com/minio/md5-simd v1.1.2/go.mod h1:MzdKDxYpY2BT9XQFocsiZf/NKVtR7nkE4RoEpN+20RM=
github.com/minio/minio-go/v7 v7.0.65 h1:sOlB8T3nQK+TApTpuN3k4WD5KasvZIE3vVFzyyCa0go=
Expand All @@ -53,40 +54,42 @@ 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/prometheus/client_golang v1.17.0 h1:rl2sfwZMtSthVU752MqfjQozy7blglC+1SOtjMAMh+Q=
github.com/prometheus/client_golang v1.17.0/go.mod h1:VeL+gMmOAxkS2IqfCq0ZmHSL+LjWfWDUmp1mBz9JgUY=
github.com/prometheus/client_model v0.4.1-0.20230718164431-9a2bf3000d16 h1:v7DLqVdK4VrYkVD5diGdl4sxJurKJEMnODWRJlxV9oM=
github.com/prometheus/client_model v0.4.1-0.20230718164431-9a2bf3000d16/go.mod h1:oMQmHW1/JoDwqLtg57MGgP/Fb1CJEYF2imWWhWtMkYU=
github.com/prometheus/common v0.44.0 h1:+5BrQJwiBB9xsMygAB3TNvpQKOwlkc25LbISbrdOOfY=
github.com/prometheus/common v0.44.0/go.mod h1:ofAIvZbQ1e/nugmZGz4/qCb9Ap1VoSTIO7x0VV9VvuY=
github.com/prometheus/procfs v0.11.1 h1:xRC8Iq1yyca5ypa9n1EZnWZkt7dwcoRPQwX/5gwaUuI=
github.com/prometheus/procfs v0.11.1/go.mod h1:eesXgaPo1q7lBpVMoMy0ZOFTth9hBn4W/y0/p/ScXhY=
github.com/prometheus/client_model v0.5.0 h1:VQw1hfvPvk3Uv6Qf29VrPF32JB6rtbgI6cYPYQjL0Qw=
github.com/prometheus/client_model v0.5.0/go.mod h1:dTiFglRmd66nLR9Pv9f0mZi7B7fk5Pm3gvsjB5tr+kI=
github.com/prometheus/common v0.45.0 h1:2BGz0eBc2hdMDLnO/8n0jeB3oPrt2D08CekT0lneoxM=
github.com/prometheus/common v0.45.0/go.mod h1:YJmSTw9BoKxJplESWWxlbyttQR4uaEcGyv9MZjVOJsY=
github.com/prometheus/procfs v0.12.0 h1:jluTpSng7V9hY0O2R9DzzJHYb2xULk9VTR1V1R/k6Bo=
github.com/prometheus/procfs v0.12.0/go.mod h1:pcuDEFsWDnvcgNzo4EEweacyhjeA9Zk3cnaOZAZEfOo=
github.com/rs/xid v1.5.0 h1:mKX4bl4iPYJtEIxp6CYiUuLQ/8DYMoz0PUdtGgMFRVc=
github.com/rs/xid v1.5.0/go.mod h1:trrq9SKmegXys3aeAKXMUTdJsYXVwGY3RLcfgqegfbg=
github.com/sirupsen/logrus v1.9.3 h1:dueUQJ1C2q9oE3F7wvmSGAaVtTmUizReu6fjN8uqzbQ=
github.com/sirupsen/logrus v1.9.3/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ=
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4=
github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
github.com/stretchr/testify v1.8.2 h1:+h33VjcLVPDHtOdpUCuF+7gSuG3yGIftsP1YvFihtJ8=
github.com/stretchr/testify v1.8.2/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4=
golang.org/x/crypto v0.14.0 h1:wBqGXzWJW6m1XrIKlAH0Hs1JJ7+9KBwnIO8v66Q9cHc=
golang.org/x/crypto v0.14.0/go.mod h1:MVFd36DqK4CsrnJYDkBA3VC4m2GkXAM0PvzMCn4JQf4=
golang.org/x/net v0.17.0 h1:pVaXccu2ozPjCXewfr1S7xza/zcXTity9cCdXQYSjIM=
golang.org/x/net v0.17.0/go.mod h1:NxSsAGuq816PNPmqtQdLE42eU2Fs7NoRIZrHJAlaCOE=
golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
github.com/xhit/go-str2duration/v2 v2.1.0 h1:lxklc02Drh6ynqX+DdPyp5pCKLUQpRT8bp8Ydu2Bstc=
github.com/xhit/go-str2duration/v2 v2.1.0/go.mod h1:ohY8p+0f07DiV6Em5LKB0s2YpLtXVyJfNt1+BlmyAsU=
golang.org/x/crypto v0.16.0 h1:mMMrFzRSCF0GvB7Ne27XVtVAaXLrPmgPC7/v0tkwHaY=
golang.org/x/crypto v0.16.0/go.mod h1:gCAAfMLgwOJRpTjQ2zCCt2OcSfYMTeZVSRtQlPC7Nq4=
golang.org/x/net v0.19.0 h1:zTwKpTd2XuCqf8huc7Fo2iSy+4RHPd10s4KzeTnVr1c=
golang.org/x/net v0.19.0/go.mod h1:CfAk/cbD4CthTvqiEl8NpboMuiuOYsAr/7NOjZJtv1U=
golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.13.0 h1:Af8nKPmuFypiUBjVoU9V20FiaFXOcuZI21p0ycVYYGE=
golang.org/x/sys v0.13.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/text v0.13.0 h1:ablQoSUd0tRdKxZewP80B+BaqeKJuVhuRxj/dkrun3k=
golang.org/x/text v0.13.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE=
golang.org/x/sys v0.15.0 h1:h48lPFYpsTvQJZF4EKyI4aLHaev3CxivZmv7yZig9pc=
golang.org/x/sys v0.15.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
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/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw=
google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc=
google.golang.org/protobuf v1.31.0 h1:g0LDEJHgrBl9N9r17Ru3sqWhkIx2NB67okBHPwC7hs8=
google.golang.org/protobuf v1.31.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/ini.v1 v1.67.0 h1:Dgnx+6+nfE+IfzjUEISNeydPJh9AXNNsWbGP9KzCsOA=
gopkg.in/ini.v1 v1.67.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k=
gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
86 changes: 51 additions & 35 deletions handler.go
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
package main

import (
"bytes"
"crypto/sha512"
"encoding/hex"
"fmt"
Expand All @@ -15,6 +14,8 @@ import (
"github.com/google/uuid"
"github.com/minio/minio-go/v7"
"github.com/prometheus/client_golang/prometheus"

"transfer/internal/metrics"
)

func (c *Config) HealthCheckHandler(w http.ResponseWriter, _ *http.Request) {
Expand Down Expand Up @@ -53,7 +54,7 @@ func (c *Config) DownloadHandler(w http.ResponseWriter, r *http.Request) {
statSpan.Status = sentry.SpanStatusOK

filePath := fmt.Sprintf("%s/%s", id, filename)
object, err := c.minioClient.StatObject(r.Context(), p.S3BucketName, filePath, minio.StatObjectOptions{})
object, err := c.minioClient.StatObject(statSpan.Context(), p.S3BucketName, filePath, minio.StatObjectOptions{})
if err != nil {
switch minio.ToErrorResponse(err).StatusCode {
case http.StatusNotFound:
Expand All @@ -76,7 +77,7 @@ func (c *Config) DownloadHandler(w http.ResponseWriter, r *http.Request) {

// only return checksum when called in sum mode
if sumMode {
metricObjectAction.With(prometheus.Labels{"action": "sum"}).Inc()
metrics.ObjectAction.With(prometheus.Labels{metrics.LabelAction: "sum"}).Inc()
_, httpResponseError := fmt.Fprintf(w, "%s %s\n", object.UserMetadata[ChecksumMetadataFieldName], filename)
if httpResponseError != nil {
sentry.CaptureMessage(fmt.Sprintf("%s: %s", err.Error(), r.URL.String()))
Expand All @@ -90,7 +91,7 @@ func (c *Config) DownloadHandler(w http.ResponseWriter, r *http.Request) {
w.Header().Set("Content-Disposition", "attachment; filename="+filename)

objectGetSpan := handlerMainSpan.StartChild("object.get")
reader, err := c.minioClient.GetObject(r.Context(), p.S3BucketName, object.Key, minio.GetObjectOptions{})
reader, err := c.minioClient.GetObject(objectGetSpan.Context(), p.S3BucketName, object.Key, minio.GetObjectOptions{})
if err != nil {
objectGetSpan.Status = sentry.SpanStatusInternalError
objectGetSpan.Finish()
Expand All @@ -100,7 +101,7 @@ func (c *Config) DownloadHandler(w http.ResponseWriter, r *http.Request) {
}
objectGetSpan.Finish()

metricObjectAction.With(prometheus.Labels{"action": "download"}).Inc()
metrics.ObjectAction.With(prometheus.Labels{metrics.LabelAction: "download"}).Inc()

objectCopySpan := handlerMainSpan.StartChild("object.copy")
defer objectCopySpan.Finish()
Expand All @@ -127,58 +128,73 @@ func (c *Config) UploadHandler(w http.ResponseWriter, r *http.Request) {
}

if !ok || filename == "" {
w.WriteHeader(http.StatusBadRequest)
http.Error(w, "filename not provided", http.StatusBadRequest)
return
}
if r.ContentLength > p.UploadLimitGB*GB {
if r.ContentLength > p.UploadLimitGB*metrics.GB {
sentry.CaptureMessage("upload too large")
w.WriteHeader(http.StatusNotAcceptable)
http.Error(w, "upload too large", http.StatusRequestEntityTooLarge)
return
}

metadata := make(map[string]string)
sha512SumGenerator := sha512.New()

buf := &bytes.Buffer{}
tee := io.TeeReader(r.Body, buf)
pipeReader, pipeWriter := io.Pipe()
multiWriter := io.MultiWriter(sha512SumGenerator, pipeWriter)

copySpan := handlerMainSpan.StartChild("object.copy")
go func() {
copySpan := handlerMainSpan.StartChild("object.copy")
defer copySpan.Finish()
_, err := io.CopyN(multiWriter, r.Body, r.ContentLength)
pipeWriter.CloseWithError(err)
}()

written, err := io.CopyN(sha512SumGenerator, tee, r.ContentLength)
if written != r.ContentLength {
traceLog(c.logger, err)
sentry.CaptureException(err)
copySpan.Status = sentry.SpanStatusInternalError
copySpan.Finish()
w.WriteHeader(http.StatusInternalServerError)
objectForwardSpan := handlerMainSpan.StartChild("object.put")

prefixId := uuid.NewString()

uploadedObject, uploadError := c.minioClient.PutObject(objectForwardSpan.Context(), p.S3BucketName, prefixId+"/"+filename, pipeReader, r.ContentLength, minio.PutObjectOptions{
ContentType: selectContentType(filename),
})

if uploadError != nil {
traceLog(c.logger, uploadError)
sentry.CaptureException(uploadError)
objectForwardSpan.Status = sentry.SpanStatusInternalError
w.WriteHeader(minio.ToErrorResponse(uploadError).StatusCode)
return
}
metadata[ChecksumMetadataFieldName] = hex.EncodeToString(sha512SumGenerator.Sum(nil))
copySpan.Finish()

objectForwardSpan := handlerMainSpan.StartChild("object.put")
id := uuid.New()
_, err = c.minioClient.PutObject(r.Context(), p.S3BucketName, id.String()+"/"+filename, buf, r.ContentLength, minio.PutObjectOptions{
ContentType: selectContentType(filename),
UserMetadata: metadata,
metadata[ChecksumMetadataFieldName] = hex.EncodeToString(sha512SumGenerator.Sum(nil))
objectMetadataSpan := handlerMainSpan.StartChild("object.put.metadata")
_, copyError := c.minioClient.CopyObject(objectMetadataSpan.Context(), minio.CopyDestOptions{
Bucket: p.S3BucketName,
Object: uploadedObject.Key,
UserMetadata: metadata,
ReplaceMetadata: true,
}, minio.CopySrcOptions{
Bucket: uploadedObject.Bucket,
Object: uploadedObject.Key,
})
objectForwardSpan.Finish()

if err != nil {
traceLog(c.logger, err)
sentry.CaptureException(err)
objectMetadataSpan.Finish()
if copyError != nil {
traceLog(c.logger, copyError)
sentry.CaptureException(copyError)
objectForwardSpan.Status = sentry.SpanStatusInternalError
w.WriteHeader(minio.ToErrorResponse(err).StatusCode)
w.WriteHeader(minio.ToErrorResponse(copyError).StatusCode)
return
}

metricObjectSize.Observe(float64(r.ContentLength))
metricObjectAction.With(prometheus.Labels{"action": "upload"}).Inc()
objectForwardSpan.Finish()

metrics.ObjectSize.Observe(float64(r.ContentLength))
metrics.ObjectAction.With(prometheus.Labels{metrics.LabelAction: "upload"}).Inc()

downloadLink := fmt.Sprintf("%s://%s/%s/%s\n", p.DownloadLinkPrefix, r.Host, id.String(), filename)
downloadLink := fmt.Sprintf("%s://%s/%s/%s\n", p.DownloadLinkPrefix, r.Host, prefixId, filename)

// generate download link
_, downloadLinkResponseError := fmt.Fprintf(w, downloadLink)
_, downloadLinkResponseError := fmt.Fprint(w, downloadLink)
handlerMainSpan.Data = map[string]interface{}{
"download_link": downloadLink,
}
Expand Down
22 changes: 0 additions & 22 deletions helper.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,30 +7,8 @@ import (
"path"
"regexp"
"runtime"
"time"

"github.com/prometheus/client_golang/prometheus"
)

// apiMiddleware - logging and metrics for api endpoints
func apiMiddleware(handler http.HandlerFunc, logger *log.Logger, endpointName string) http.HandlerFunc {
if logger == nil {
logger = log.Default()
}
fn := func(w http.ResponseWriter, r *http.Request) {
metricEndpointRequests.With(prometheus.Labels{"endpoint": endpointName}).Inc()
start := time.Now()

// serve http request
handler.ServeHTTP(w, r)
duration := time.Since(start)
metricOperationDuration.With(prometheus.Labels{"endpoint": endpointName}).Observe(duration.Seconds())

logger.Printf("%v %v %v", r.Method, r.RequestURI, duration)
}
return fn
}

// selectContentType - parse file extension and determine content type
func selectContentType(filename string) string {
extension := path.Ext(filename)
Expand Down
Loading

0 comments on commit 87f9055

Please sign in to comment.