mirror of
https://github.com/gmemstr/sliproad.git
synced 2024-09-20 00:21:15 +01:00
Rewrite file provider to proxy data download (rather than redirect)
Reworked the fileprovider to proxy data directly from the provider rather than attempt to funkily redirect when needed, since it was overly complex and wouldn't work well in the long run. Temporarily added "file" as constant return for determining the filetype through Backblaze. Added a Makefile to make life easier as well, and rewrote the README to reflect the refactor/rewrite and new approach to providers.
This commit is contained in:
parent
bf1f06b79c
commit
ea1075cb5b
10
Makefile
Normal file
10
Makefile
Normal file
|
@ -0,0 +1,10 @@
|
||||||
|
.DEFAULT_GOAL := build
|
||||||
|
|
||||||
|
build:
|
||||||
|
go build
|
||||||
|
|
||||||
|
pi:
|
||||||
|
env GOOS=linux GOARCH=arm GOARM=5 go build
|
||||||
|
|
||||||
|
run:
|
||||||
|
go run webserver.go
|
43
README.md
43
README.md
|
@ -3,19 +3,38 @@ small go nas platform for my raspberry pi
|
||||||
|
|
||||||
## usage
|
## usage
|
||||||
|
|
||||||
```
|
### configuration
|
||||||
cp assets/config/config.example.json assets/config/config.json
|
|
||||||
# edit config file with your hot/cold storage locations
|
unlike the initial version of this project, the current build uses _providers_ to determine how to handle various
|
||||||
nano assets/config/config.json
|
functions related to files. currently, two are implemented, `disk` and `backblaze`, since they are the primary providers
|
||||||
# run
|
i use myself. the providers you would like to use can be added to `providers.yml` alongside the binary.
|
||||||
go run webserver.go
|
|
||||||
# or build and run
|
for example, here is a sample configuration implementing both of them:
|
||||||
go build; ./nas
|
|
||||||
|
```yaml
|
||||||
|
disk:
|
||||||
|
provider: disk
|
||||||
|
path: /tmp/nas
|
||||||
|
backblaze:
|
||||||
|
provider: backblaze
|
||||||
|
config:
|
||||||
|
appKeyId: APP_KEY_ID
|
||||||
|
appId: APP_ID
|
||||||
|
bucket: BUCKET_ID
|
||||||
```
|
```
|
||||||
|
|
||||||
you can also optionally use the `build-pi.sh` to build it for a raspberry pi (tested with raspberry pi 3 model b+)
|
(read more here: [#providers](#providers))
|
||||||
|
|
||||||
then navigate to `localhost:3000`
|
### running
|
||||||
|
|
||||||
|
after adding the providers you would like to use, the application can be run simply with `./nas`.
|
||||||
|
|
||||||
|
### building
|
||||||
|
|
||||||
|
this project uses go modules and a makefile, so building should be relatively straightforward.
|
||||||
|
|
||||||
|
- `make` will build the project for your system's architecture.
|
||||||
|
- `make pi` will build the project with the `GOOS=linux GOARCH=arm GOARM=5 go` flags set for raspberry pis.
|
||||||
|
|
||||||
## api
|
## api
|
||||||
|
|
||||||
|
@ -23,6 +42,10 @@ initially the heavy lifting was done by the server, but the need for a better fr
|
||||||
|
|
||||||
full documentation coming soon once actual functionality has been nailed down.
|
full documentation coming soon once actual functionality has been nailed down.
|
||||||
|
|
||||||
|
## providers
|
||||||
|
|
||||||
|
// todo
|
||||||
|
|
||||||
## credits
|
## credits
|
||||||
|
|
||||||
svg icons via https://iconsvg.xyz
|
svg icons via https://iconsvg.xyz
|
||||||
|
|
|
@ -1 +0,0 @@
|
||||||
env GOOS=linux GOARCH=arm GOARM=5 go build
|
|
|
@ -12,12 +12,14 @@ import (
|
||||||
type BackblazeProvider struct {
|
type BackblazeProvider struct {
|
||||||
FileProvider
|
FileProvider
|
||||||
Bucket string
|
Bucket string
|
||||||
|
DownloadLocation string
|
||||||
}
|
}
|
||||||
|
|
||||||
type BackblazeAuthPayload struct {
|
type BackblazeAuthPayload struct {
|
||||||
AccountId string `json:"accountId"`
|
AccountId string `json:"accountId"`
|
||||||
AuthToken string `json:"authorizationToken"`
|
AuthToken string `json:"authorizationToken"`
|
||||||
ApiUrl string `json:"apiUrl"`
|
ApiUrl string `json:"apiUrl"`
|
||||||
|
DownloadUrl string `json:"downloadUrl"`
|
||||||
}
|
}
|
||||||
|
|
||||||
type BackblazeFile struct {
|
type BackblazeFile struct {
|
||||||
|
@ -32,6 +34,15 @@ type BackblazeFilePayload struct {
|
||||||
Files []BackblazeFile `json:"files"`
|
Files []BackblazeFile `json:"files"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type BackblazeBucketInfo struct {
|
||||||
|
BucketId string `json:"bucketId"`
|
||||||
|
BucketName string `json:"bucketName"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type BackblazeBucketInfoPayload struct {
|
||||||
|
Buckets []BackblazeBucketInfo `json:"buckets"`
|
||||||
|
}
|
||||||
|
|
||||||
// Call Backblaze API endpoint to authorize and gather facts.
|
// Call Backblaze API endpoint to authorize and gather facts.
|
||||||
func (bp *BackblazeProvider) Authorize(appKeyId string, appKey string) error {
|
func (bp *BackblazeProvider) Authorize(appKeyId string, appKey string) error {
|
||||||
client := &http.Client{}
|
client := &http.Client{}
|
||||||
|
@ -60,7 +71,8 @@ func (bp *BackblazeProvider) Authorize(appKeyId string, appKey string) error {
|
||||||
}
|
}
|
||||||
bp.Authentication = data.AuthToken
|
bp.Authentication = data.AuthToken
|
||||||
bp.Location = data.ApiUrl
|
bp.Location = data.ApiUrl
|
||||||
bp.Name = "Backblaze|" + data.AccountId
|
bp.Name = data.AccountId
|
||||||
|
bp.DownloadLocation = data.DownloadUrl
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
@ -111,10 +123,50 @@ func (bp *BackblazeProvider) GetDirectory(path string) Directory {
|
||||||
return finalDir
|
return finalDir
|
||||||
}
|
}
|
||||||
|
|
||||||
func (bp *BackblazeProvider) ViewFile(path string) string {
|
func (bp *BackblazeProvider) ViewFile(path string) []byte {
|
||||||
return ""
|
client := &http.Client{}
|
||||||
|
// Get bucket name >:(
|
||||||
|
bucketIdPayload := fmt.Sprintf(`{"accountId": "%s", "bucketId": "%s"}`, bp.Name, bp.Bucket)
|
||||||
|
|
||||||
|
req, err := http.NewRequest("POST", bp.Location + "/b2api/v2/b2_list_buckets",
|
||||||
|
bytes.NewBuffer([]byte(bucketIdPayload)))
|
||||||
|
req.Header.Add("Authorization", bp.Authentication)
|
||||||
|
|
||||||
|
res, err := client.Do(req)
|
||||||
|
bucketData, err := ioutil.ReadAll(res.Body)
|
||||||
|
|
||||||
|
var data BackblazeBucketInfoPayload
|
||||||
|
json.Unmarshal(bucketData, &data)
|
||||||
|
ourBucket := data.Buckets[0].BucketName
|
||||||
|
// Get file and write over to client.
|
||||||
|
url := strings.Join([]string{bp.DownloadLocation,"file",ourBucket,path}, "/")
|
||||||
|
req, err = http.NewRequest("GET",
|
||||||
|
url,
|
||||||
|
bytes.NewBuffer([]byte("")))
|
||||||
|
if err != nil {
|
||||||
|
fmt.Println(err.Error())
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
req.Header.Add("Authorization", bp.Authentication)
|
||||||
|
file, err := client.Do(req)
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
fmt.Println(err.Error())
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
fileBytes, err := ioutil.ReadAll(file.Body)
|
||||||
|
if err != nil {
|
||||||
|
fmt.Println(err.Error())
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
return fileBytes
|
||||||
}
|
}
|
||||||
|
|
||||||
func (bp *BackblazeProvider) SaveFile(contents []byte, path string) bool {
|
func (bp *BackblazeProvider) SaveFile(contents []byte, path string) bool {
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (bp *BackblazeProvider) DetermineType(path string) string {
|
||||||
|
return "file"
|
||||||
|
}
|
|
@ -36,8 +36,13 @@ func (dp *DiskProvider) GetDirectory(path string) Directory {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (dp *DiskProvider) ViewFile(path string) string {
|
func (dp *DiskProvider) ViewFile(path string) []byte {
|
||||||
return strings.Join([]string{dp.Location,path}, "/")
|
file := strings.Join([]string{dp.Location,path}, "/")
|
||||||
|
fileContents, err := ioutil.ReadFile(file)
|
||||||
|
if err != nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
return fileContents
|
||||||
}
|
}
|
||||||
|
|
||||||
func (dp *DiskProvider) SaveFile(contents []byte, path string) bool {
|
func (dp *DiskProvider) SaveFile(contents []byte, path string) bool {
|
||||||
|
@ -47,3 +52,16 @@ func (dp *DiskProvider) SaveFile(contents []byte, path string) bool {
|
||||||
}
|
}
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (dp *DiskProvider) DetermineType(path string) string {
|
||||||
|
rp := strings.Join([]string{dp.Location,path}, "/")
|
||||||
|
file, err := os.Stat(rp)
|
||||||
|
if err != nil {
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
if file.IsDir() {
|
||||||
|
return "directory"
|
||||||
|
}
|
||||||
|
|
||||||
|
return "file"
|
||||||
|
}
|
|
@ -4,6 +4,7 @@ import "fmt"
|
||||||
|
|
||||||
type FileProvider struct {
|
type FileProvider struct {
|
||||||
Name string `yaml:"name"`
|
Name string `yaml:"name"`
|
||||||
|
Provider string `yaml:"provider"`
|
||||||
Authentication string `yaml:"authentication"`
|
Authentication string `yaml:"authentication"`
|
||||||
Location string `yaml:"path"`
|
Location string `yaml:"path"`
|
||||||
Config map[string]string `yaml:"config"`
|
Config map[string]string `yaml:"config"`
|
||||||
|
@ -22,10 +23,16 @@ type FileInfo struct {
|
||||||
|
|
||||||
var Providers map[string]FileProvider
|
var Providers map[string]FileProvider
|
||||||
|
|
||||||
|
type FileContents struct {
|
||||||
|
Content []byte
|
||||||
|
IsUrl bool
|
||||||
|
}
|
||||||
|
|
||||||
type FileProviderInterface interface {
|
type FileProviderInterface interface {
|
||||||
GetDirectory(path string) Directory
|
GetDirectory(path string) Directory
|
||||||
ViewFile(path string) string
|
ViewFile(path string) []byte
|
||||||
SaveFile(contents []byte, path string) bool
|
SaveFile(contents []byte, path string) bool
|
||||||
|
DetermineType(path string) string
|
||||||
}
|
}
|
||||||
|
|
||||||
func TranslateProvider(codename string, i *FileProviderInterface) {
|
func TranslateProvider(codename string, i *FileProviderInterface) {
|
||||||
|
@ -35,7 +42,7 @@ func TranslateProvider(codename string, i *FileProviderInterface) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
if codename == "backblaze" {
|
if codename == "backblaze" {
|
||||||
bbProv := &BackblazeProvider{provider, provider.Config["bucket"]}
|
bbProv := &BackblazeProvider{provider, provider.Config["bucket"], ""}
|
||||||
|
|
||||||
err := bbProv.Authorize(provider.Config["appKeyId"], provider.Config["appId"])
|
err := bbProv.Authorize(provider.Config["appKeyId"], provider.Config["appId"])
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -52,10 +59,14 @@ func (f FileProvider) GetDirectory(path string) Directory {
|
||||||
return Directory{}
|
return Directory{}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (f FileProvider) ViewFile(path string) string {
|
func (f FileProvider) ViewFile(path string) []byte {
|
||||||
return ""
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (f FileProvider) SaveFile(contents []byte, path string) bool {
|
func (f FileProvider) SaveFile(contents []byte, path string) bool {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (f FileProvider) DetermineType(path string) string {
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
|
|
@ -19,6 +19,16 @@ func HandleProvider() common.Handler {
|
||||||
|
|
||||||
fileList := provider.GetDirectory("")
|
fileList := provider.GetDirectory("")
|
||||||
if vars["file"] != "" {
|
if vars["file"] != "" {
|
||||||
|
fileType := provider.DetermineType(vars["file"])
|
||||||
|
if fileType == "" {
|
||||||
|
w.Write([]byte("file not found"))
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
if fileType == "file" {
|
||||||
|
file := provider.ViewFile(vars["file"])
|
||||||
|
w.Write(file)
|
||||||
|
return nil
|
||||||
|
}
|
||||||
fileList = provider.GetDirectory(vars["file"])
|
fileList = provider.GetDirectory(vars["file"])
|
||||||
}
|
}
|
||||||
data, err := json.Marshal(fileList)
|
data, err := json.Marshal(fileList)
|
||||||
|
|
Loading…
Reference in a new issue