2 Commits

Author SHA1 Message Date
2d6ebedb0f feat: Replace data fillcontent with custom reader 2022-06-16 17:36:08 +02:00
12d9acfdb3 chore: fix workflow 2022-02-13 16:11:18 +01:00
6 changed files with 156 additions and 20 deletions

View File

@ -1,5 +1,9 @@
name: Go Matrix name: Go Matrix
on: [push, pull_request] on:
push:
branches:
- master
pull_request:
jobs: jobs:

View File

@ -13,7 +13,7 @@ jobs:
runs-on: ubuntu-latest runs-on: ubuntu-latest
env: env:
GO_VERSION: 1.17 GO_VERSION: 1.17
GOLANGCI_LINT_VERSION: v1.44.0 GOLANGCI_LINT_VERSION: v1.46.2
CGO_ENABLED: 0 CGO_ENABLED: 0
steps: steps:

View File

@ -39,6 +39,7 @@ linters:
- varnamelen - varnamelen
- nilnil - nilnil
- ifshort - ifshort
- exhaustruct
issues: issues:
exclude-use-default: false exclude-use-default: false

19
app.go
View File

@ -1,7 +1,6 @@
package main package main
import ( import (
"bytes"
"crypto/tls" "crypto/tls"
"crypto/x509" "crypto/x509"
"encoding/json" "encoding/json"
@ -181,7 +180,7 @@ func dataHandler(w http.ResponseWriter, r *http.Request) {
attachment = false attachment = false
} }
content := fillContent(size) content := &contentReader{size: size}
if attachment { if attachment {
w.Header().Set("Content-Disposition", "Attachment") w.Header().Set("Content-Disposition", "Attachment")
@ -311,22 +310,6 @@ func healthHandler(w http.ResponseWriter, req *http.Request) {
} }
} }
func fillContent(length int64) io.ReadSeeker {
charset := "-ABCDEFGHIJKLMNOPQRSTUVWXYZ"
b := make([]byte, length)
for i := range b {
b[i] = charset[i%len(charset)]
}
if length > 0 {
b[0] = '|'
b[length-1] = '|'
}
return bytes.NewReader(b)
}
func getEnv(key, fallback string) string { func getEnv(key, fallback string) string {
value := os.Getenv(key) value := os.Getenv(key)
if len(value) == 0 { if len(value) == 0 {

66
content.go Normal file
View File

@ -0,0 +1,66 @@
package main
import (
"errors"
"io"
)
const contentCharset = "-ABCDEFGHIJKLMNOPQRSTUVWXYZ"
type contentReader struct {
size int64
cur int64
}
// Read implements the io.Read interface.
func (r *contentReader) Read(p []byte) (int, error) {
length := r.size - 1
if r.cur >= length {
return 0, io.EOF
}
if len(p) == 0 {
return 0, nil
}
var n int
if r.cur == 0 {
p[n] = '|'
r.cur++
n++
}
for n < len(p) && r.cur <= length {
p[n] = contentCharset[int(r.cur)%len(contentCharset)]
r.cur++
n++
}
if r.cur >= length {
p[n-1] = '|'
}
return n, nil
}
// Seek implements the io.Seek interface.
func (r *contentReader) Seek(offset int64, whence int) (int64, error) {
switch whence {
default:
return 0, errors.New("seek: invalid whence")
case io.SeekStart:
offset += 0
case io.SeekCurrent:
offset += r.cur
case io.SeekEnd:
offset += r.size - 1
}
if offset < 0 {
return 0, errors.New("seek: invalid offset")
}
r.cur = offset
return offset, nil
}

82
content_test.go Normal file
View File

@ -0,0 +1,82 @@
package main
import (
"io"
"testing"
)
func Test_contentReader_Read(t *testing.T) {
tests := []struct {
name string
size int64
content string
}{
{
name: "simple",
size: 40,
content: "|ABCDEFGHIJKLMNOPQRSTUVWXYZ-ABCDEFGHIJK|",
},
}
for _, test := range tests {
test := test
t.Run(test.name, func(t *testing.T) {
t.Parallel()
d := &contentReader{size: test.size}
b, err := io.ReadAll(d)
if err != nil {
t.Errorf("contentReader.Read() error = %v", err)
return
}
if string(b) != test.content {
t.Errorf("return content does not match expected value: got %s want %s", b, test.content)
}
})
}
}
func Test_contentReader_ReadSeek(t *testing.T) {
tests := []struct {
name string
offset int64
seekWhence int
size int64
content string
}{
{
name: "simple",
offset: 10,
seekWhence: io.SeekCurrent,
size: 40,
content: "JKLMNOPQRSTUVWXYZ-ABCDEFGHIJK|",
},
}
for _, test := range tests {
test := test
t.Run(test.name, func(t *testing.T) {
t.Parallel()
d := &contentReader{size: test.size}
_, err := d.Seek(test.offset, test.seekWhence)
if err != nil {
t.Errorf("contentReader.Seek() error = %v", err)
return
}
b, err := io.ReadAll(d)
if err != nil {
t.Errorf("contentReader.Read() error = %v", err)
return
}
if string(b) != test.content {
t.Errorf("return content does not match expected value: got %s want %s", b, test.content)
}
})
}
}