Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
28 changes: 27 additions & 1 deletion internal/storage/filesystem/s3filesystem/aws/Aws_mock.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,10 +12,12 @@ import (
"strings"

"github.com/forceu/gokapi/internal/models"
"github.com/forceu/gokapi/internal/webserver/headers"
)

var uploadedFiles []models.File
var isCorrectLogin bool
var awsConfig models.AwsConfig

const (
region = "mock-region-1"
Expand All @@ -32,6 +34,7 @@ const IsMockApi = true

// Init reads the credentials for AWS
func Init(config models.AwsConfig) bool {
awsConfig = config
if !isValidCredentials() {
return false
}
Expand All @@ -57,6 +60,7 @@ func IsValidLogin(config models.AwsConfig) (bool, error) {

// LogOut resets the credentials
func LogOut() {
awsConfig = models.AwsConfig{}
isCorrectLogin = false
}

Expand Down Expand Up @@ -131,10 +135,32 @@ func isUploaded(file models.File) bool {
// ServeFile either redirects the user to a pre-signed download url (default) or downloads the file and serves it as a proxy (depending
// on configuration). Returns true if blocking operation (in order to set download status) or false if non-blocking.
func ServeFile(w http.ResponseWriter, r *http.Request, file models.File, forceDownload bool, forceDecryption bool) (bool, error) {
// TODO implement proxy as well
if awsConfig.ProxyDownload {
return true, proxyDownload(w, file, forceDownload)
}
return false, RedirectToDownload(w, r, file, forceDownload)
}

// proxyDownload simulates streaming the file content through the server, mirroring the
// real AWS implementation's proxy-download mode. The content is read from a local test
// fixture at "data/<sha1>", the same convention used by Stream().
func proxyDownload(w http.ResponseWriter, file models.File, forceDownload bool) error {
if !isValidCredentials() {
return errors.New("invalid credentials / invalid bucket / invalid region")
}
if !isUploaded(file) {
return errors.New("file not found")
}
data, err := os.Open("data/" + file.SHA1)
if err != nil {
return err
}
defer data.Close()
headers.Write(file, w, forceDownload, false)
_, err = io.Copy(w, data)
return err
}

// RedirectToDownload creates a presigned link that is valid for 15 seconds and redirects the
// client to this url
func RedirectToDownload(w http.ResponseWriter, r *http.Request, file models.File, forceDownload bool) error {
Expand Down
70 changes: 70 additions & 0 deletions internal/storage/filesystem/s3filesystem/aws/Aws_mock_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
//go:build !noaws && awsmock && test

package aws

import (
"net/http/httptest"
"os"
"testing"

"github.com/forceu/gokapi/internal/models"
"github.com/forceu/gokapi/internal/test"
)

func initMockCredentials(t *testing.T) {
t.Helper()
os.Setenv("GOKAPI_AWS_BUCKET", bucketName)
os.Setenv("GOKAPI_AWS_REGION", region)
os.Setenv("GOKAPI_AWS_KEY", accessId)
os.Setenv("GOKAPI_AWS_KEY_SECRET", accessKey)
ok := Init(models.AwsConfig{})
test.IsEqualBool(t, ok, true)
}

func TestServeFile_ProxyDownload(t *testing.T) {
initMockCredentials(t)
awsConfig.ProxyDownload = true
defer func() { awsConfig.ProxyDownload = false }()

file := models.File{Id: "awsTest1234567890123", SHA1: "x341354656543213246465465465432456898794"}
err := os.MkdirAll("data", 0777)
test.IsNil(t, err)
err = os.WriteFile("data/"+file.SHA1, []byte("proxy download content"), 0777)
test.IsNil(t, err)
defer os.Remove("data/" + file.SHA1)

r := httptest.NewRequest("GET", "/", nil)
w := httptest.NewRecorder()
isBlocking, err := ServeFile(w, r, file, false, false)
test.IsNil(t, err)
test.IsEqualBool(t, isBlocking, true)
test.ResponseBodyIs(t, w, "proxy download content")
}

func TestServeFile_ProxyDownload_MissingFixture(t *testing.T) {
initMockCredentials(t)
awsConfig.ProxyDownload = true
defer func() { awsConfig.ProxyDownload = false }()

// awsTest1234567890123 is registered as uploaded by Init(), but its on-disk fixture
// is never written by this test - proxyDownload must surface that as an error rather
// than panicking.
file := models.File{Id: "awsTest1234567890123", SHA1: "x341354656543213246465465465432456898794"}
r := httptest.NewRequest("GET", "/", nil)
w := httptest.NewRecorder()
_, err := ServeFile(w, r, file, false, false)
test.IsNotNil(t, err)
}

func TestServeFile_RedirectDownload(t *testing.T) {
initMockCredentials(t)
awsConfig.ProxyDownload = false

file := models.File{Id: "awsTest1234567890123", SHA1: "x341354656543213246465465465432456898794"}
r := httptest.NewRequest("GET", "/", nil)
w := httptest.NewRecorder()
isBlocking, err := ServeFile(w, r, file, false, false)
test.IsNil(t, err)
test.IsEqualBool(t, isBlocking, false)
test.ResponseBodyContains(t, w, "https://redirect.url")
}
Loading