Space.Upload (#313)

This commit is contained in:
Dominic Wong
2021-12-10 15:26:50 +00:00
committed by GitHub
parent 156042c6ea
commit f022c62a87
7 changed files with 355 additions and 149 deletions

View File

@@ -4,7 +4,6 @@ Quick and simple GIF search
Add GIFs to your project with keyword search and results in multiple sizes and formats. Add GIFs to your project with keyword search and results in multiple sizes and formats.
![Powered by GIPHY](https://raw.githubusercontent.com/micro/services/master/gifs/assets/PoweredBy_200px-White_HorizLogo.png) ![Powered by GIPHY](https://raw.githubusercontent.com/micro/services/master/gifs/assets/PoweredBy_200px-White_HorizLogo.png)
When integrating this API please follow GIPHY's attribution guidelines [here](https://developers.giphy.com/docs/sdk/#design-guidelines). When integrating this API please follow GIPHY's attribution guidelines [here](https://developers.giphy.com/docs/sdk/#design-guidelines).

View File

@@ -109,5 +109,17 @@
"url": "https://example.com/foo/bar/images/file.jpg" "url": "https://example.com/foo/bar/images/file.jpg"
} }
} }
],
"upload": [
{
"title": "Upload an object",
"run_check": false,
"request": {
"name": "images/file.jpg"
},
"response": {
"url": "https://example.com/foo/bar/images/file.jpg"
}
}
] ]
} }

View File

@@ -6,7 +6,6 @@ import (
"encoding/json" "encoding/json"
"fmt" "fmt"
"io/ioutil" "io/ioutil"
"strconv"
"strings" "strings"
"time" "time"
@@ -29,10 +28,8 @@ import (
) )
const ( const (
mdACL = "X-Amz-Acl" mdACL = "X-Amz-Acl"
mdACLPublic = "public-read" mdACLPublic = "public-read"
mdCreated = "Micro-Created"
mdVisibility = "Micro-Visibility"
visibilityPrivate = "private" visibilityPrivate = "private"
visibilityPublic = "public" visibilityPublic = "public"
@@ -115,7 +112,7 @@ func (s Space) upsert(ctx context.Context, object []byte, name, visibility, meth
} }
exists := false exists := false
hoo, err := s.client.HeadObject(&sthree.HeadObjectInput{ _, err := s.client.HeadObject(&sthree.HeadObjectInput{
Bucket: aws.String(s.conf.SpaceName), Bucket: aws.String(s.conf.SpaceName),
Key: aws.String(objectName), Key: aws.String(objectName),
}) })
@@ -132,24 +129,30 @@ func (s Space) upsert(ctx context.Context, object []byte, name, visibility, meth
return "", errors.BadRequest(method, "Object already exists") return "", errors.BadRequest(method, "Object already exists")
} }
createTime := aws.String(time.Now().Format(time.RFC3339Nano))
if exists {
createTime = hoo.Metadata[mdCreated]
}
if len(visibility) == 0 { if len(visibility) == 0 {
visibility = visibilityPrivate visibility = visibilityPrivate
} }
now := time.Now().Format(time.RFC3339Nano)
md := meta{
CreateTime: now,
ModifiedTime: now,
Visibility: visibility,
}
if exists {
m, err := s.objectMeta(objectName)
if err != nil {
log.Errorf("Error reading object meta %s", err)
return "", errors.BadRequest(method, "Error creating object")
}
md.CreateTime = m.CreateTime
}
putInput := &sthree.PutObjectInput{ putInput := &sthree.PutObjectInput{
Body: bytes.NewReader(object), Body: bytes.NewReader(object),
Key: aws.String(objectName), Key: aws.String(objectName),
Bucket: aws.String(s.conf.SpaceName), Bucket: aws.String(s.conf.SpaceName),
Metadata: map[string]*string{
mdVisibility: aws.String(visibility),
mdCreated: createTime,
},
} }
// TODO flesh out options - might want to do content-type for better serving of object
if visibility == visibilityPublic { if visibility == visibilityPublic {
putInput.ACL = aws.String(mdACLPublic) putInput.ACL = aws.String(mdACLPublic)
} }
@@ -160,14 +163,12 @@ func (s Space) upsert(ctx context.Context, object []byte, name, visibility, meth
} }
// store the metadata for easy retrieval for listing // store the metadata for easy retrieval for listing
if err := store.Write(store.NewRecord( if err := store.Write(store.NewRecord(fmt.Sprintf("%s/%s", prefixByUser, objectName), md)); err != nil {
fmt.Sprintf("%s/%s", prefixByUser, objectName),
meta{Visibility: visibility, CreateTime: *createTime, ModifiedTime: time.Now().Format(time.RFC3339Nano)})); err != nil {
log.Errorf("Error writing object to store %s", err) log.Errorf("Error writing object to store %s", err)
return "", errors.InternalServerError(method, "Error creating object") return "", errors.InternalServerError(method, "Error creating object")
} }
retUrl := "" retUrl := ""
if visibility == "public" { if visibility == visibilityPublic {
retUrl = fmt.Sprintf("%s/%s", s.conf.BaseURL, objectName) retUrl = fmt.Sprintf("%s/%s", s.conf.BaseURL, objectName)
} }
@@ -281,40 +282,39 @@ func (s Space) Head(ctx context.Context, request *pb.HeadRequest, response *pb.H
return errors.InternalServerError(method, "Error reading object") return errors.InternalServerError(method, "Error reading object")
} }
vis := visibilityPrivate md, err := s.objectMeta(objectName)
if md, ok := goo.Metadata[mdVisibility]; ok && len(*md) > 0 { if err != nil {
vis = *md log.Errorf("Error reading object meta %s", err)
} return errors.InternalServerError(method, "Error reading object")
var created string
if md, ok := goo.Metadata[mdCreated]; ok && len(*md) > 0 {
t, err := time.Parse(time.RFC3339Nano, *md)
if err != nil {
// try as unix ts
createdI, err := strconv.ParseInt(*md, 10, 64)
if err != nil {
log.Errorf("Error %s", err)
} else {
t = time.Unix(createdI, 0)
}
}
created = t.Format(time.RFC3339Nano)
} }
url := "" url := ""
if vis == "public" { if md.Visibility == visibilityPublic {
url = fmt.Sprintf("%s/%s", s.conf.BaseURL, objectName) url = fmt.Sprintf("%s/%s", s.conf.BaseURL, objectName)
} }
response.Object = &pb.HeadObject{ response.Object = &pb.HeadObject{
Name: request.Name, Name: request.Name,
Modified: goo.LastModified.Format(time.RFC3339Nano), Modified: goo.LastModified.Format(time.RFC3339Nano),
Created: created, Created: md.CreateTime,
Visibility: vis, Visibility: md.Visibility,
Url: url, Url: url,
} }
return nil return nil
} }
func (s *Space) objectMeta(objName string) (*meta, error) {
recs, err := store.Read(fmt.Sprintf("%s/%s", prefixByUser, objName))
if err != nil {
return nil, err
}
var me meta
if err := json.Unmarshal(recs[0].Value, &me); err != nil {
return nil, err
}
return &me, nil
}
func (s *Space) Read(ctx context.Context, req *pb.ReadRequest, rsp *pb.ReadResponse) error { func (s *Space) Read(ctx context.Context, req *pb.ReadRequest, rsp *pb.ReadResponse) error {
method := "space.Read" method := "space.Read"
tnt, ok := tenant.FromContext(ctx) tnt, ok := tenant.FromContext(ctx)
@@ -330,55 +330,35 @@ func (s *Space) Read(ctx context.Context, req *pb.ReadRequest, rsp *pb.ReadRespo
objectName := fmt.Sprintf("%s/%s", tnt, name) objectName := fmt.Sprintf("%s/%s", tnt, name)
goo, err := s.client.HeadObject(&sthree.HeadObjectInput{ goo, err := s.client.GetObject(&sthree.GetObjectInput{
Bucket: aws.String(s.conf.SpaceName), Bucket: aws.String(s.conf.SpaceName),
Key: aws.String(objectName), Key: aws.String(objectName),
}) })
if err != nil { if err != nil {
aerr, ok := err.(awserr.Error) aerr, ok := err.(awserr.Error)
if ok && aerr.Code() == "NotFound" { if ok && aerr.Code() == "NotSuchKey" {
return errors.BadRequest(method, "Object not found") return errors.BadRequest(method, "Object not found")
} }
log.Errorf("Error s3 %s", err) log.Errorf("Error s3 %s", err)
return errors.InternalServerError(method, "Error reading object") return errors.InternalServerError(method, "Error reading object")
} }
_, gooreq := s.client.GetObjectRequest(&sthree.GetObjectInput{ md, err := s.objectMeta(objectName)
Bucket: aws.String(s.conf.SpaceName), if err != nil {
Key: aws.String(objectName), log.Errorf("Error reading meta %s", err)
}) return errors.InternalServerError(method, "Error reading object")
vis := visibilityPrivate
if md, ok := goo.Metadata[mdVisibility]; ok && len(*md) > 0 {
vis = *md
}
var created string
if md, ok := goo.Metadata[mdCreated]; ok && len(*md) > 0 {
t, err := time.Parse(time.RFC3339Nano, *md)
if err != nil {
// try as unix ts
createdI, err := strconv.ParseInt(*md, 10, 64)
if err != nil {
log.Errorf("Error %s", err)
} else {
t = time.Unix(createdI, 0)
}
}
created = t.Format(time.RFC3339Nano)
} }
url := "" url := ""
if vis == "public" { if md.Visibility == visibilityPublic {
url = fmt.Sprintf("%s/%s", s.conf.BaseURL, objectName) url = fmt.Sprintf("%s/%s", s.conf.BaseURL, objectName)
} }
if *gooreq.ContentLength > maxReadSize { if *goo.ContentLength > maxReadSize {
return errors.BadRequest(method, "Exceeds max read size: %v bytes", maxReadSize) return errors.BadRequest(method, "Exceeds max read size: %v bytes", maxReadSize)
} }
b, err := ioutil.ReadAll(gooreq.Body) b, err := ioutil.ReadAll(goo.Body)
if err != nil { if err != nil {
return errors.InternalServerError(method, "Failed to read data") return errors.InternalServerError(method, "Failed to read data")
} }
@@ -386,8 +366,8 @@ func (s *Space) Read(ctx context.Context, req *pb.ReadRequest, rsp *pb.ReadRespo
rsp.Object = &pb.Object{ rsp.Object = &pb.Object{
Name: req.Name, Name: req.Name,
Modified: goo.LastModified.Format(time.RFC3339Nano), Modified: goo.LastModified.Format(time.RFC3339Nano),
Created: created, Created: md.CreateTime,
Visibility: vis, Visibility: md.Visibility,
Url: url, Url: url,
Data: b, Data: b,
} }
@@ -461,3 +441,65 @@ func (s *Space) Download(ctx context.Context, req *api.Request, rsp *api.Respons
return nil return nil
} }
func (s Space) Upload(ctx context.Context, request *pb.UploadRequest, response *pb.UploadResponse) error {
method := "space.Upload"
tnt, ok := tenant.FromContext(ctx)
if !ok {
return errors.Unauthorized(method, "Unauthorized")
}
if len(request.Name) == 0 {
return errors.BadRequest(method, "Missing name param")
}
objectName := fmt.Sprintf("%s/%s", tnt, request.Name)
if err := s3utils.CheckValidObjectName(objectName); err != nil {
return errors.BadRequest(method, "Invalid name")
}
_, err := s.client.HeadObject(&sthree.HeadObjectInput{
Bucket: aws.String(s.conf.SpaceName),
Key: aws.String(objectName),
})
if err != nil {
aerr, ok := err.(awserr.Error)
if !ok || aerr.Code() != "NotFound" {
return errors.InternalServerError(method, "Error creating upload URL")
}
} else {
return errors.BadRequest(method, "Object already exists")
}
createTime := aws.String(time.Now().Format(time.RFC3339Nano))
if len(request.Visibility) == 0 {
request.Visibility = visibilityPrivate
}
putInput := &sthree.PutObjectInput{
Key: aws.String(objectName),
Bucket: aws.String(s.conf.SpaceName),
}
if request.Visibility == visibilityPublic {
putInput.ACL = aws.String(mdACLPublic)
}
req, _ := s.client.PutObjectRequest(putInput)
url, err := req.Presign(5 * time.Minute)
if err != nil {
return errors.InternalServerError(method, "Error creating upload URL")
}
response.Url = url
// store the metadata for easy retrieval for listing
if err := store.Write(store.NewRecord(
fmt.Sprintf("%s/%s", prefixByUser, objectName),
meta{
Visibility: request.Visibility,
CreateTime: *createTime,
ModifiedTime: time.Now().Format(time.RFC3339Nano),
})); err != nil {
log.Errorf("Error writing object to store %s", err)
return errors.InternalServerError(method, "Error creating upload URL")
}
return nil
}

View File

@@ -105,8 +105,6 @@ func TestCreate(t *testing.T) {
put: func(input *sthree.PutObjectInput) (*sthree.PutObjectOutput, error) { put: func(input *sthree.PutObjectInput) (*sthree.PutObjectOutput, error) {
g.Expect(*input.Bucket).To(Equal("my-space")) g.Expect(*input.Bucket).To(Equal("my-space"))
g.Expect(input.ACL).To(BeNil()) g.Expect(input.ACL).To(BeNil())
g.Expect(*input.Metadata[mdVisibility]).To(Equal(visibilityPrivate))
g.Expect(input.Metadata[mdCreated]).To(Not(BeNil()))
return &sthree.PutObjectOutput{}, nil return &sthree.PutObjectOutput{}, nil
}, },
}, },
@@ -121,8 +119,6 @@ func TestCreate(t *testing.T) {
put: func(input *sthree.PutObjectInput) (*sthree.PutObjectOutput, error) { put: func(input *sthree.PutObjectInput) (*sthree.PutObjectOutput, error) {
g.Expect(*input.Bucket).To(Equal("my-space")) g.Expect(*input.Bucket).To(Equal("my-space"))
g.Expect(*input.ACL).To(Equal(mdACLPublic)) g.Expect(*input.ACL).To(Equal(mdACLPublic))
g.Expect(*input.Metadata[mdVisibility]).To(Equal(visibilityPublic))
g.Expect(input.Metadata[mdCreated]).To(Not(BeNil()))
return &sthree.PutObjectOutput{}, nil return &sthree.PutObjectOutput{}, nil
}, },
}, },
@@ -206,8 +202,6 @@ func TestUpdate(t *testing.T) {
put: func(input *sthree.PutObjectInput) (*sthree.PutObjectOutput, error) { put: func(input *sthree.PutObjectInput) (*sthree.PutObjectOutput, error) {
g.Expect(*input.Bucket).To(Equal("my-space")) g.Expect(*input.Bucket).To(Equal("my-space"))
g.Expect(input.ACL).To(BeNil()) g.Expect(input.ACL).To(BeNil())
g.Expect(*input.Metadata[mdVisibility]).To(Equal(visibilityPrivate))
g.Expect(input.Metadata[mdCreated]).To(Not(BeNil()))
return &sthree.PutObjectOutput{}, nil return &sthree.PutObjectOutput{}, nil
}, },
}, },
@@ -222,8 +216,6 @@ func TestUpdate(t *testing.T) {
put: func(input *sthree.PutObjectInput) (*sthree.PutObjectOutput, error) { put: func(input *sthree.PutObjectInput) (*sthree.PutObjectOutput, error) {
g.Expect(*input.Bucket).To(Equal("my-space")) g.Expect(*input.Bucket).To(Equal("my-space"))
g.Expect(*input.ACL).To(Equal(mdACLPublic)) g.Expect(*input.ACL).To(Equal(mdACLPublic))
g.Expect(*input.Metadata[mdVisibility]).To(Equal(visibilityPublic))
g.Expect(input.Metadata[mdCreated]).To(Not(BeNil()))
return &sthree.PutObjectOutput{}, nil return &sthree.PutObjectOutput{}, nil
}, },
}, },
@@ -238,19 +230,11 @@ func TestUpdate(t *testing.T) {
head: func(input *sthree.HeadObjectInput) (*sthree.HeadObjectOutput, error) { head: func(input *sthree.HeadObjectInput) (*sthree.HeadObjectOutput, error) {
g.Expect(*input.Bucket).To(Equal("my-space")) g.Expect(*input.Bucket).To(Equal("my-space"))
g.Expect(*input.Key).To(Equal("micro/123/foo.jpg")) g.Expect(*input.Key).To(Equal("micro/123/foo.jpg"))
return &sthree.HeadObjectOutput{ return &sthree.HeadObjectOutput{}, nil
Metadata: map[string]*string{
mdCreated: aws.String("1638541918"),
mdVisibility: aws.String(visibilityPrivate),
},
}, nil
}, },
put: func(input *sthree.PutObjectInput) (*sthree.PutObjectOutput, error) { put: func(input *sthree.PutObjectInput) (*sthree.PutObjectOutput, error) {
g.Expect(*input.Bucket).To(Equal("my-space")) g.Expect(*input.Bucket).To(Equal("my-space"))
g.Expect(input.ACL).To(BeNil()) g.Expect(input.ACL).To(BeNil())
g.Expect(*input.Metadata[mdVisibility]).To(Equal(visibilityPrivate))
// created shouuld be copied from the previous
g.Expect(*input.Metadata[mdCreated]).To(Equal("1638541918"))
return &sthree.PutObjectOutput{}, nil return &sthree.PutObjectOutput{}, nil
}, },
url: "", url: "",
@@ -261,19 +245,11 @@ func TestUpdate(t *testing.T) {
head: func(input *sthree.HeadObjectInput) (*sthree.HeadObjectOutput, error) { head: func(input *sthree.HeadObjectInput) (*sthree.HeadObjectOutput, error) {
g.Expect(*input.Bucket).To(Equal("my-space")) g.Expect(*input.Bucket).To(Equal("my-space"))
g.Expect(*input.Key).To(Equal("micro/123/foo.jpg")) g.Expect(*input.Key).To(Equal("micro/123/foo.jpg"))
return &sthree.HeadObjectOutput{ return &sthree.HeadObjectOutput{}, nil
Metadata: map[string]*string{
mdCreated: aws.String("1638541918"),
mdVisibility: aws.String(visibilityPrivate),
},
}, nil
}, },
put: func(input *sthree.PutObjectInput) (*sthree.PutObjectOutput, error) { put: func(input *sthree.PutObjectInput) (*sthree.PutObjectOutput, error) {
g.Expect(*input.Bucket).To(Equal("my-space")) g.Expect(*input.Bucket).To(Equal("my-space"))
g.Expect(*input.ACL).To(Equal(mdACLPublic)) g.Expect(*input.ACL).To(Equal(mdACLPublic))
g.Expect(*input.Metadata[mdVisibility]).To(Equal(visibilityPublic))
// created shouuld be copied from the previous
g.Expect(*input.Metadata[mdCreated]).To(Equal("1638541918"))
return &sthree.PutObjectOutput{}, nil return &sthree.PutObjectOutput{}, nil
}, },
url: "https://my-space.ams3.example.com/micro/123/foo.jpg", url: "https://my-space.ams3.example.com/micro/123/foo.jpg",
@@ -404,10 +380,10 @@ func TestList(t *testing.T) {
name: "Empty prefix", name: "Empty prefix",
}, },
} }
store.DefaultStore = memory.NewStore()
for _, tc := range tcs { for _, tc := range tcs {
t.Run(tc.name, func(t *testing.T) { t.Run(tc.name, func(t *testing.T) {
store.DefaultStore = memory.NewStore()
store.Write( store.Write(
store.NewRecord(fmt.Sprintf("%s/micro/123/file.jpg", prefixByUser), store.NewRecord(fmt.Sprintf("%s/micro/123/file.jpg", prefixByUser),
meta{ meta{
@@ -444,7 +420,7 @@ func TestList(t *testing.T) {
}, },
{ {
Key: aws.String("micro/123/file2.jpg"), Key: aws.String("micro/123/file2.jpg"),
LastModified: aws.Time(time.Unix(1257894000, 0)), LastModified: aws.Time(time.Unix(1257894001, 0)),
}, },
}, },
}, nil }, nil
@@ -469,9 +445,16 @@ func TestList(t *testing.T) {
g.Expect(err).To(BeNil()) g.Expect(err).To(BeNil())
g.Expect(rsp.Objects).To(HaveLen(2)) g.Expect(rsp.Objects).To(HaveLen(2))
g.Expect(rsp.Objects[0].Name).To(Equal("file.jpg")) g.Expect(rsp.Objects[0].Name).To(Equal("file.jpg"))
g.Expect(rsp.Objects[0].Visibility).To(Equal("public"))
g.Expect(rsp.Objects[0].Created).To(Equal("2009-11-10T23:00:00Z"))
g.Expect(rsp.Objects[0].Modified).To(Equal("2009-11-10T23:00:00Z"))
g.Expect(rsp.Objects[0].Url).To(Equal("https://my-space.ams3.example.com/micro/123/file.jpg")) g.Expect(rsp.Objects[0].Url).To(Equal("https://my-space.ams3.example.com/micro/123/file.jpg"))
g.Expect(rsp.Objects[1].Name).To(Equal("file2.jpg")) g.Expect(rsp.Objects[1].Name).To(Equal("file2.jpg"))
g.Expect(rsp.Objects[1].Url).To(Equal("")) g.Expect(rsp.Objects[1].Url).To(Equal(""))
g.Expect(rsp.Objects[1].Visibility).To(Equal("private"))
g.Expect(rsp.Objects[1].Created).To(Equal("2009-11-10T23:00:01Z"))
g.Expect(rsp.Objects[1].Modified).To(Equal("2009-11-10T23:00:01Z"))
} }
}) })
@@ -504,10 +487,6 @@ func TestHead(t *testing.T) {
return &sthree.HeadObjectOutput{ return &sthree.HeadObjectOutput{
LastModified: aws.Time(time.Unix(1257894000, 0)), LastModified: aws.Time(time.Unix(1257894000, 0)),
Metadata: map[string]*string{
mdCreated: aws.String("1257894000"),
mdVisibility: aws.String(visibilityPublic),
},
}, nil }, nil
}, },
}, },
@@ -524,10 +503,6 @@ func TestHead(t *testing.T) {
return &sthree.HeadObjectOutput{ return &sthree.HeadObjectOutput{
LastModified: aws.Time(time.Unix(1257894000, 0)), LastModified: aws.Time(time.Unix(1257894000, 0)),
Metadata: map[string]*string{
mdCreated: aws.String("2009-11-10T23:00:00Z"),
mdVisibility: aws.String("private"),
},
}, nil }, nil
}, },
}, },
@@ -544,10 +519,15 @@ func TestHead(t *testing.T) {
}, },
}, },
} }
store.DefaultStore = memory.NewStore()
for _, tc := range tcs { for _, tc := range tcs {
t.Run(tc.name, func(t *testing.T) { t.Run(tc.name, func(t *testing.T) {
store.DefaultStore = memory.NewStore()
store.Write(store.NewRecord(fmt.Sprintf("%s/micro/123/%s", prefixByUser, tc.objectName), meta{
Visibility: tc.visibility,
CreateTime: tc.created,
ModifiedTime: tc.modified,
}))
handler := Space{ handler := Space{
conf: conf{ conf: conf{
AccessKey: "access", AccessKey: "access",

View File

@@ -1,7 +1,7 @@
// Code generated by protoc-gen-go. DO NOT EDIT. // Code generated by protoc-gen-go. DO NOT EDIT.
// versions: // versions:
// protoc-gen-go v1.27.1 // protoc-gen-go v1.26.0
// protoc v3.15.6 // protoc v3.15.5
// source: proto/space.proto // source: proto/space.proto
package space package space
@@ -984,6 +984,111 @@ func (x *DownloadResponse) GetUrl() string {
return "" return ""
} }
// Upload a large object. Returns a time limited presigned URL to be used for uploading the object
type UploadRequest struct {
state protoimpl.MessageState
sizeCache protoimpl.SizeCache
unknownFields protoimpl.UnknownFields
Name string `protobuf:"bytes,1,opt,name=name,proto3" json:"name,omitempty"`
// is this object public or private
Visibility string `protobuf:"bytes,2,opt,name=visibility,proto3" json:"visibility,omitempty"`
}
func (x *UploadRequest) Reset() {
*x = UploadRequest{}
if protoimpl.UnsafeEnabled {
mi := &file_proto_space_proto_msgTypes[17]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
}
func (x *UploadRequest) String() string {
return protoimpl.X.MessageStringOf(x)
}
func (*UploadRequest) ProtoMessage() {}
func (x *UploadRequest) ProtoReflect() protoreflect.Message {
mi := &file_proto_space_proto_msgTypes[17]
if protoimpl.UnsafeEnabled && x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi)
}
return ms
}
return mi.MessageOf(x)
}
// Deprecated: Use UploadRequest.ProtoReflect.Descriptor instead.
func (*UploadRequest) Descriptor() ([]byte, []int) {
return file_proto_space_proto_rawDescGZIP(), []int{17}
}
func (x *UploadRequest) GetName() string {
if x != nil {
return x.Name
}
return ""
}
func (x *UploadRequest) GetVisibility() string {
if x != nil {
return x.Visibility
}
return ""
}
type UploadResponse struct {
state protoimpl.MessageState
sizeCache protoimpl.SizeCache
unknownFields protoimpl.UnknownFields
// a presigned url to be used for uploading
Url string `protobuf:"bytes,1,opt,name=url,proto3" json:"url,omitempty"`
}
func (x *UploadResponse) Reset() {
*x = UploadResponse{}
if protoimpl.UnsafeEnabled {
mi := &file_proto_space_proto_msgTypes[18]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
}
func (x *UploadResponse) String() string {
return protoimpl.X.MessageStringOf(x)
}
func (*UploadResponse) ProtoMessage() {}
func (x *UploadResponse) ProtoReflect() protoreflect.Message {
mi := &file_proto_space_proto_msgTypes[18]
if protoimpl.UnsafeEnabled && x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi)
}
return ms
}
return mi.MessageOf(x)
}
// Deprecated: Use UploadResponse.ProtoReflect.Descriptor instead.
func (*UploadResponse) Descriptor() ([]byte, []int) {
return file_proto_space_proto_rawDescGZIP(), []int{18}
}
func (x *UploadResponse) GetUrl() string {
if x != nil {
return x.Url
}
return ""
}
var File_proto_space_proto protoreflect.FileDescriptor var File_proto_space_proto protoreflect.FileDescriptor
var file_proto_space_proto_rawDesc = []byte{ var file_proto_space_proto_rawDesc = []byte{
@@ -1057,34 +1162,44 @@ var file_proto_space_proto_rawDesc = []byte{
0x65, 0x73, 0x74, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x65, 0x73, 0x74, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28,
0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x22, 0x24, 0x0a, 0x10, 0x44, 0x6f, 0x77, 0x6e, 0x6c, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x22, 0x24, 0x0a, 0x10, 0x44, 0x6f, 0x77, 0x6e, 0x6c,
0x6f, 0x61, 0x64, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x10, 0x0a, 0x03, 0x75, 0x6f, 0x61, 0x64, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x10, 0x0a, 0x03, 0x75,
0x72, 0x6c, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x75, 0x72, 0x6c, 0x32, 0x8a, 0x03, 0x72, 0x6c, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x75, 0x72, 0x6c, 0x22, 0x43, 0x0a,
0x0a, 0x05, 0x53, 0x70, 0x61, 0x63, 0x65, 0x12, 0x37, 0x0a, 0x06, 0x43, 0x72, 0x65, 0x61, 0x74, 0x0d, 0x55, 0x70, 0x6c, 0x6f, 0x61, 0x64, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x12,
0x65, 0x12, 0x14, 0x2e, 0x73, 0x70, 0x61, 0x63, 0x65, 0x2e, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61,
0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x15, 0x2e, 0x73, 0x70, 0x61, 0x63, 0x65, 0x2e, 0x6d, 0x65, 0x12, 0x1e, 0x0a, 0x0a, 0x76, 0x69, 0x73, 0x69, 0x62, 0x69, 0x6c, 0x69, 0x74, 0x79,
0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0a, 0x76, 0x69, 0x73, 0x69, 0x62, 0x69, 0x6c, 0x69,
0x12, 0x37, 0x0a, 0x06, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x12, 0x14, 0x2e, 0x73, 0x70, 0x61, 0x74, 0x79, 0x22, 0x22, 0x0a, 0x0e, 0x55, 0x70, 0x6c, 0x6f, 0x61, 0x64, 0x52, 0x65, 0x73, 0x70,
0x63, 0x65, 0x2e, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x10, 0x0a, 0x03, 0x75, 0x72, 0x6c, 0x18, 0x01, 0x20, 0x01, 0x28,
0x1a, 0x15, 0x2e, 0x73, 0x70, 0x61, 0x63, 0x65, 0x2e, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x52, 0x09, 0x52, 0x03, 0x75, 0x72, 0x6c, 0x32, 0xc3, 0x03, 0x0a, 0x05, 0x53, 0x70, 0x61, 0x63, 0x65,
0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x12, 0x37, 0x0a, 0x06, 0x44, 0x65, 0x6c, 0x12, 0x37, 0x0a, 0x06, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x12, 0x14, 0x2e, 0x73, 0x70, 0x61,
0x65, 0x74, 0x65, 0x12, 0x14, 0x2e, 0x73, 0x70, 0x61, 0x63, 0x65, 0x2e, 0x44, 0x65, 0x6c, 0x65, 0x63, 0x65, 0x2e, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74,
0x1a, 0x15, 0x2e, 0x73, 0x70, 0x61, 0x63, 0x65, 0x2e, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x52,
0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x12, 0x37, 0x0a, 0x06, 0x55, 0x70, 0x64,
0x61, 0x74, 0x65, 0x12, 0x14, 0x2e, 0x73, 0x70, 0x61, 0x63, 0x65, 0x2e, 0x55, 0x70, 0x64, 0x61,
0x74, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x15, 0x2e, 0x73, 0x70, 0x61, 0x63, 0x74, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x15, 0x2e, 0x73, 0x70, 0x61, 0x63,
0x65, 0x2e, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x65, 0x2e, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65,
0x22, 0x00, 0x12, 0x31, 0x0a, 0x04, 0x4c, 0x69, 0x73, 0x74, 0x12, 0x12, 0x2e, 0x73, 0x70, 0x61, 0x22, 0x00, 0x12, 0x37, 0x0a, 0x06, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x12, 0x14, 0x2e, 0x73,
0x63, 0x65, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x13, 0x70, 0x61, 0x63, 0x65, 0x2e, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65,
0x2e, 0x73, 0x70, 0x61, 0x63, 0x65, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x73, 0x74, 0x1a, 0x15, 0x2e, 0x73, 0x70, 0x61, 0x63, 0x65, 0x2e, 0x44, 0x65, 0x6c, 0x65, 0x74,
0x6e, 0x73, 0x65, 0x22, 0x00, 0x12, 0x31, 0x0a, 0x04, 0x48, 0x65, 0x61, 0x64, 0x12, 0x12, 0x2e, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x12, 0x31, 0x0a, 0x04, 0x4c,
0x73, 0x70, 0x61, 0x63, 0x65, 0x2e, 0x48, 0x65, 0x61, 0x64, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x69, 0x73, 0x74, 0x12, 0x12, 0x2e, 0x73, 0x70, 0x61, 0x63, 0x65, 0x2e, 0x4c, 0x69, 0x73, 0x74,
0x74, 0x1a, 0x13, 0x2e, 0x73, 0x70, 0x61, 0x63, 0x65, 0x2e, 0x48, 0x65, 0x61, 0x64, 0x52, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x13, 0x2e, 0x73, 0x70, 0x61, 0x63, 0x65, 0x2e,
0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x12, 0x31, 0x0a, 0x04, 0x52, 0x65, 0x61, 0x64, 0x4c, 0x69, 0x73, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x12, 0x31,
0x12, 0x12, 0x2e, 0x73, 0x70, 0x61, 0x63, 0x65, 0x2e, 0x52, 0x65, 0x61, 0x64, 0x52, 0x65, 0x71, 0x0a, 0x04, 0x48, 0x65, 0x61, 0x64, 0x12, 0x12, 0x2e, 0x73, 0x70, 0x61, 0x63, 0x65, 0x2e, 0x48,
0x75, 0x65, 0x73, 0x74, 0x1a, 0x13, 0x2e, 0x73, 0x70, 0x61, 0x63, 0x65, 0x2e, 0x52, 0x65, 0x61, 0x65, 0x61, 0x64, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x13, 0x2e, 0x73, 0x70, 0x61,
0x64, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x12, 0x3d, 0x0a, 0x08, 0x44, 0x63, 0x65, 0x2e, 0x48, 0x65, 0x61, 0x64, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22,
0x6f, 0x77, 0x6e, 0x6c, 0x6f, 0x61, 0x64, 0x12, 0x16, 0x2e, 0x73, 0x70, 0x61, 0x63, 0x65, 0x2e, 0x00, 0x12, 0x31, 0x0a, 0x04, 0x52, 0x65, 0x61, 0x64, 0x12, 0x12, 0x2e, 0x73, 0x70, 0x61, 0x63,
0x44, 0x6f, 0x77, 0x6e, 0x6c, 0x6f, 0x61, 0x64, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x65, 0x2e, 0x52, 0x65, 0x61, 0x64, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x13, 0x2e,
0x17, 0x2e, 0x73, 0x70, 0x61, 0x63, 0x65, 0x2e, 0x44, 0x6f, 0x77, 0x6e, 0x6c, 0x6f, 0x61, 0x64, 0x73, 0x70, 0x61, 0x63, 0x65, 0x2e, 0x52, 0x65, 0x61, 0x64, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e,
0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x42, 0x0f, 0x5a, 0x0d, 0x2e, 0x2f, 0x73, 0x65, 0x22, 0x00, 0x12, 0x3d, 0x0a, 0x08, 0x44, 0x6f, 0x77, 0x6e, 0x6c, 0x6f, 0x61, 0x64,
0x70, 0x72, 0x6f, 0x74, 0x6f, 0x3b, 0x73, 0x70, 0x61, 0x63, 0x65, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x12, 0x16, 0x2e, 0x73, 0x70, 0x61, 0x63, 0x65, 0x2e, 0x44, 0x6f, 0x77, 0x6e, 0x6c, 0x6f, 0x61,
0x74, 0x6f, 0x33, 0x64, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x17, 0x2e, 0x73, 0x70, 0x61, 0x63, 0x65,
0x2e, 0x44, 0x6f, 0x77, 0x6e, 0x6c, 0x6f, 0x61, 0x64, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73,
0x65, 0x22, 0x00, 0x12, 0x37, 0x0a, 0x06, 0x55, 0x70, 0x6c, 0x6f, 0x61, 0x64, 0x12, 0x14, 0x2e,
0x73, 0x70, 0x61, 0x63, 0x65, 0x2e, 0x55, 0x70, 0x6c, 0x6f, 0x61, 0x64, 0x52, 0x65, 0x71, 0x75,
0x65, 0x73, 0x74, 0x1a, 0x15, 0x2e, 0x73, 0x70, 0x61, 0x63, 0x65, 0x2e, 0x55, 0x70, 0x6c, 0x6f,
0x61, 0x64, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x42, 0x0f, 0x5a, 0x0d,
0x2e, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x3b, 0x73, 0x70, 0x61, 0x63, 0x65, 0x62, 0x06, 0x70,
0x72, 0x6f, 0x74, 0x6f, 0x33,
} }
var ( var (
@@ -1099,7 +1214,7 @@ func file_proto_space_proto_rawDescGZIP() []byte {
return file_proto_space_proto_rawDescData return file_proto_space_proto_rawDescData
} }
var file_proto_space_proto_msgTypes = make([]protoimpl.MessageInfo, 17) var file_proto_space_proto_msgTypes = make([]protoimpl.MessageInfo, 19)
var file_proto_space_proto_goTypes = []interface{}{ var file_proto_space_proto_goTypes = []interface{}{
(*CreateRequest)(nil), // 0: space.CreateRequest (*CreateRequest)(nil), // 0: space.CreateRequest
(*CreateResponse)(nil), // 1: space.CreateResponse (*CreateResponse)(nil), // 1: space.CreateResponse
@@ -1118,6 +1233,8 @@ var file_proto_space_proto_goTypes = []interface{}{
(*ReadResponse)(nil), // 14: space.ReadResponse (*ReadResponse)(nil), // 14: space.ReadResponse
(*DownloadRequest)(nil), // 15: space.DownloadRequest (*DownloadRequest)(nil), // 15: space.DownloadRequest
(*DownloadResponse)(nil), // 16: space.DownloadResponse (*DownloadResponse)(nil), // 16: space.DownloadResponse
(*UploadRequest)(nil), // 17: space.UploadRequest
(*UploadResponse)(nil), // 18: space.UploadResponse
} }
var file_proto_space_proto_depIdxs = []int32{ var file_proto_space_proto_depIdxs = []int32{
8, // 0: space.ListResponse.objects:type_name -> space.ListObject 8, // 0: space.ListResponse.objects:type_name -> space.ListObject
@@ -1130,15 +1247,17 @@ var file_proto_space_proto_depIdxs = []int32{
9, // 7: space.Space.Head:input_type -> space.HeadRequest 9, // 7: space.Space.Head:input_type -> space.HeadRequest
13, // 8: space.Space.Read:input_type -> space.ReadRequest 13, // 8: space.Space.Read:input_type -> space.ReadRequest
15, // 9: space.Space.Download:input_type -> space.DownloadRequest 15, // 9: space.Space.Download:input_type -> space.DownloadRequest
1, // 10: space.Space.Create:output_type -> space.CreateResponse 17, // 10: space.Space.Upload:input_type -> space.UploadRequest
3, // 11: space.Space.Update:output_type -> space.UpdateResponse 1, // 11: space.Space.Create:output_type -> space.CreateResponse
5, // 12: space.Space.Delete:output_type -> space.DeleteResponse 3, // 12: space.Space.Update:output_type -> space.UpdateResponse
7, // 13: space.Space.List:output_type -> space.ListResponse 5, // 13: space.Space.Delete:output_type -> space.DeleteResponse
10, // 14: space.Space.Head:output_type -> space.HeadResponse 7, // 14: space.Space.List:output_type -> space.ListResponse
14, // 15: space.Space.Read:output_type -> space.ReadResponse 10, // 15: space.Space.Head:output_type -> space.HeadResponse
16, // 16: space.Space.Download:output_type -> space.DownloadResponse 14, // 16: space.Space.Read:output_type -> space.ReadResponse
10, // [10:17] is the sub-list for method output_type 16, // 17: space.Space.Download:output_type -> space.DownloadResponse
3, // [3:10] is the sub-list for method input_type 18, // 18: space.Space.Upload:output_type -> space.UploadResponse
11, // [11:19] is the sub-list for method output_type
3, // [3:11] is the sub-list for method input_type
3, // [3:3] is the sub-list for extension type_name 3, // [3:3] is the sub-list for extension type_name
3, // [3:3] is the sub-list for extension extendee 3, // [3:3] is the sub-list for extension extendee
0, // [0:3] is the sub-list for field type_name 0, // [0:3] is the sub-list for field type_name
@@ -1354,6 +1473,30 @@ func file_proto_space_proto_init() {
return nil return nil
} }
} }
file_proto_space_proto_msgTypes[17].Exporter = func(v interface{}, i int) interface{} {
switch v := v.(*UploadRequest); i {
case 0:
return &v.state
case 1:
return &v.sizeCache
case 2:
return &v.unknownFields
default:
return nil
}
}
file_proto_space_proto_msgTypes[18].Exporter = func(v interface{}, i int) interface{} {
switch v := v.(*UploadResponse); i {
case 0:
return &v.state
case 1:
return &v.sizeCache
case 2:
return &v.unknownFields
default:
return nil
}
}
} }
type x struct{} type x struct{}
out := protoimpl.TypeBuilder{ out := protoimpl.TypeBuilder{
@@ -1361,7 +1504,7 @@ func file_proto_space_proto_init() {
GoPackagePath: reflect.TypeOf(x{}).PkgPath(), GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
RawDescriptor: file_proto_space_proto_rawDesc, RawDescriptor: file_proto_space_proto_rawDesc,
NumEnums: 0, NumEnums: 0,
NumMessages: 17, NumMessages: 19,
NumExtensions: 0, NumExtensions: 0,
NumServices: 1, NumServices: 1,
}, },

View File

@@ -49,6 +49,7 @@ type SpaceService interface {
Head(ctx context.Context, in *HeadRequest, opts ...client.CallOption) (*HeadResponse, error) Head(ctx context.Context, in *HeadRequest, opts ...client.CallOption) (*HeadResponse, error)
Read(ctx context.Context, in *ReadRequest, opts ...client.CallOption) (*ReadResponse, error) Read(ctx context.Context, in *ReadRequest, opts ...client.CallOption) (*ReadResponse, error)
Download(ctx context.Context, in *DownloadRequest, opts ...client.CallOption) (*DownloadResponse, error) Download(ctx context.Context, in *DownloadRequest, opts ...client.CallOption) (*DownloadResponse, error)
Upload(ctx context.Context, in *UploadRequest, opts ...client.CallOption) (*UploadResponse, error)
} }
type spaceService struct { type spaceService struct {
@@ -133,6 +134,16 @@ func (c *spaceService) Download(ctx context.Context, in *DownloadRequest, opts .
return out, nil return out, nil
} }
func (c *spaceService) Upload(ctx context.Context, in *UploadRequest, opts ...client.CallOption) (*UploadResponse, error) {
req := c.c.NewRequest(c.name, "Space.Upload", in)
out := new(UploadResponse)
err := c.c.Call(ctx, req, out, opts...)
if err != nil {
return nil, err
}
return out, nil
}
// Server API for Space service // Server API for Space service
type SpaceHandler interface { type SpaceHandler interface {
@@ -143,6 +154,7 @@ type SpaceHandler interface {
Head(context.Context, *HeadRequest, *HeadResponse) error Head(context.Context, *HeadRequest, *HeadResponse) error
Read(context.Context, *ReadRequest, *ReadResponse) error Read(context.Context, *ReadRequest, *ReadResponse) error
Download(context.Context, *DownloadRequest, *DownloadResponse) error Download(context.Context, *DownloadRequest, *DownloadResponse) error
Upload(context.Context, *UploadRequest, *UploadResponse) error
} }
func RegisterSpaceHandler(s server.Server, hdlr SpaceHandler, opts ...server.HandlerOption) error { func RegisterSpaceHandler(s server.Server, hdlr SpaceHandler, opts ...server.HandlerOption) error {
@@ -154,6 +166,7 @@ func RegisterSpaceHandler(s server.Server, hdlr SpaceHandler, opts ...server.Han
Head(ctx context.Context, in *HeadRequest, out *HeadResponse) error Head(ctx context.Context, in *HeadRequest, out *HeadResponse) error
Read(ctx context.Context, in *ReadRequest, out *ReadResponse) error Read(ctx context.Context, in *ReadRequest, out *ReadResponse) error
Download(ctx context.Context, in *DownloadRequest, out *DownloadResponse) error Download(ctx context.Context, in *DownloadRequest, out *DownloadResponse) error
Upload(ctx context.Context, in *UploadRequest, out *UploadResponse) error
} }
type Space struct { type Space struct {
space space
@@ -193,3 +206,7 @@ func (h *spaceHandler) Read(ctx context.Context, in *ReadRequest, out *ReadRespo
func (h *spaceHandler) Download(ctx context.Context, in *DownloadRequest, out *DownloadResponse) error { func (h *spaceHandler) Download(ctx context.Context, in *DownloadRequest, out *DownloadResponse) error {
return h.SpaceHandler.Download(ctx, in, out) return h.SpaceHandler.Download(ctx, in, out)
} }
func (h *spaceHandler) Upload(ctx context.Context, in *UploadRequest, out *UploadResponse) error {
return h.SpaceHandler.Upload(ctx, in, out)
}

View File

@@ -12,6 +12,7 @@ service Space {
rpc Head(HeadRequest) returns (HeadResponse) {} rpc Head(HeadRequest) returns (HeadResponse) {}
rpc Read(ReadRequest) returns (ReadResponse) {} rpc Read(ReadRequest) returns (ReadResponse) {}
rpc Download(DownloadRequest) returns (DownloadResponse) {} rpc Download(DownloadRequest) returns (DownloadResponse) {}
rpc Upload(UploadRequest) returns (UploadResponse) {}
} }
// Create an object. Returns error if object with this name already exists. If you want to update an existing object use the `Update` endpoint // Create an object. Returns error if object with this name already exists. If you want to update an existing object use the `Update` endpoint
@@ -134,3 +135,15 @@ message DownloadResponse {
// presigned url // presigned url
string url = 2; string url = 2;
} }
// Upload a large object. Returns a time limited presigned URL to be used for uploading the object
message UploadRequest {
string name = 1;
// is this object public or private
string visibility = 2;
}
message UploadResponse {
// a presigned url to be used for uploading
string url = 1;
}