Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[WIP] Tus dataprovider #661

Closed
wants to merge 6 commits into from
Closed

Conversation

butonic
Copy link
Contributor

@butonic butonic commented Apr 15, 2020

revival of #286

I also added tus.io create extension support for dataprovider so a /bif.txt with content bar can be created with:

$ echo -n /bif.txt | base64
L2JpZi50eHQ=
$ curl -X POST -H "Tus-Resumable: 1.0.0" -H "Content-Length: 3" -H "Upload-Length: 3" http://localhost:9156/data -v -u einstein:relativity -H "Content-Type: application/offset+octet-stream" -d "bar" -H "Upload-Metadata: filename L2JpZi50eHQ="
  • implement upload for eos fs
  • implement upload for local fs
  • implement upload for s3 fs
  • refactor owncloud fs NewUpload and InitiateUpload. The share 99% of the code
  • check if chunking v2 now works? AFAICT the ocdav endpoint should support chunking v2 and use tus to upload the file to the dataprovider
  • pass on tus.io requests in the ocdav handler to allow clients to use tus directly? The endpoint then becomes /remote.php/dav/uploads but how do we determine which storage to use? For the dataprovider the path must be relative to its root. we may need to use the datagateway to lookup the correct dataprovider based on the path in the tus Upload-Metadata header.

@PVince81
Copy link
Contributor

frontend bits, might help for testing: owncloud/web#3345

@butonic
Copy link
Contributor Author

butonic commented Apr 16, 2020

I made every collection in the webdav endpoint accept tus.io POST requests that can be used to start an upload. It currently returns a Location header with the port of the dataprovider. I tested it with the go-tus client https://github.com/eventials/go-tus

This is my test code to upload a file:

package main

import (
	"crypto/tls"
	"encoding/base64"
	"net/http"
	"os"

	"github.com/eventials/go-tus"
	"github.com/eventials/go-tus/memorystore"
)

func basicAuth(username, password string) string {
	auth := username + ":" + password
	return base64.StdEncoding.EncodeToString([]byte(auth))
}

func main() {
	f, err := os.Open("my-file.bin")
	if err != nil {
		panic(err)
	}

	defer f.Close()

	http.DefaultTransport.(*http.Transport).TLSClientConfig = &tls.Config{InsecureSkipVerify: true}
	c := tus.DefaultConfig()
	c.Resume = true
	c.Store, err = memorystore.NewMemoryStore()
	if err != nil {
		panic(err)
	}

	c.Header.Add("Authorization", "Basic "+basicAuth("einstein", "relativity"))

	// create the tus client.
	client, err := tus.NewClient("https://localhost:9200/remote.php/dav/files/einstein/", c)
	if err != nil {
		panic(err)
	}

	// create an upload from a file.
	upload, err := tus.NewUploadFromFile(f)
	if err != nil {
		panic(err)
	}

	// create the uploader.
	uploader, err := client.CreateUpload(upload)
	if err != nil {
		panic(err)
	}

	// start the uploading process.
	err = uploader.Upload()
	if err != nil {
		panic(err)
	}
}

https://localhost:9200 is ocis, but it should work against an ocdav endpoint with plain reva as well.

That the Location header points to a different port might be problematic for deployments that only allow a single port to the outside world. In those cases we can either register different routes in the proxy or use the datagateway to route requests ... something to track ... until we tested tus in general

I'll test this tomorrow with @PVince81 and @LukasHirt

Another bash script to see what needs to be done to create an upload:

#!/bin/bash -x
UNAME=einstein
PASS=relativity
SOURCE=bin/ocis
BASE="https://localhost:9200/remote.php/dav"
DESTINATION_DIR="$BASE/files/$UNAME/" 
ID=`uuidgen`
DESTINATION_FILE="testchunk-$ID.bin"
METADATA="filename `echo -n $DESTINATION_FILE | base64`"
UPLOAD_LENGTH="11534336"

# check tus support using HEAD, result MUST have the "Tus-Resumable: 1.0.0" header
curl --head $DESTINATION_DIR -u $UNAME:$PASS -k 

# POST to the dir
curl -X POST $DESTINATION_DIR -u $UNAME:$PASS -k -v -H "Tus-Resumable: 1.0.0" -H "Upload-Length: $UPLOAD_LENGTH" -H "Upload-Metadata: $METADATA"

I stopped here, because I would have had to parse the headers to follow the location ... and my bash-fu is not up to the task, so I used the above go code.

@labkode
Copy link
Member

labkode commented Apr 17, 2020

@butonic nice progress. So the Tus-Resumable header is the one that says: Hi, this is TUS request? Is very important to be explicit on the ocdav part of what is accepted.

@PVince81
Copy link
Contributor

@butonic I think we're missing a "Tus-Resumable: 1.0.0" response header for the POST.
Seems the JS lib is not strict about this though.

Signed-off-by: Jörn Friedrich Dreyer <jfd@butonic.de>
Signed-off-by: Jörn Friedrich Dreyer <jfd@butonic.de>
Signed-off-by: Jörn Friedrich Dreyer <jfd@butonic.de>
Signed-off-by: Jörn Friedrich Dreyer <jfd@butonic.de>
Signed-off-by: Jörn Friedrich Dreyer <jfd@butonic.de>
Signed-off-by: Jörn Friedrich Dreyer <jfd@butonic.de>
LogEvent(h.logger, eventName, details...)
}

func LogEvent(logger *log.Logger, eventName string, details ...string) {
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

exported function LogEvent should have comment or be unexported

}

var (
ErrUnsupportedVersion = NewHTTPError(errors.New("unsupported version"), http.StatusPreconditionFailed)
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

exported var ErrUnsupportedVersion should have comment or be unexported

}

var (
ErrUnsupportedVersion = NewHTTPError(errors.New("unsupported version"), http.StatusPreconditionFailed)
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

exported var ErrUnsupportedVersion should have comment or be unexported

@butonic
Copy link
Contributor Author

butonic commented Apr 24, 2020

this branch also contains an initial oc chunking v2 implementation, but it needs to be restarted on #674

and better yet, after having sorted out how to stream directly to eos

@butonic butonic closed this Apr 24, 2020
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants