Merge branch 'v2' of github.com:tus/tusd into v2
This commit is contained in:
commit
59e4ecd927
|
@ -18,10 +18,10 @@ func hookTypeInSlice(a hooks.HookType, list []hooks.HookType) bool {
|
|||
return false
|
||||
}
|
||||
|
||||
func preCreateCallback(event handler.HookEvent) (handler.HTTPResponse, error) {
|
||||
func preCreateCallback(event handler.HookEvent) (handler.HTTPResponse, handler.FileInfoChanges, error) {
|
||||
ok, hookRes, err := invokeHookSync(hooks.HookPreCreate, event)
|
||||
if !ok || err != nil {
|
||||
return handler.HTTPResponse{}, err
|
||||
return handler.HTTPResponse{}, handler.FileInfoChanges{}, err
|
||||
}
|
||||
|
||||
httpRes := hookRes.HTTPResponse
|
||||
|
@ -32,10 +32,12 @@ func preCreateCallback(event handler.HookEvent) (handler.HTTPResponse, error) {
|
|||
err := handler.ErrUploadRejectedByServer
|
||||
err.HTTPResponse = err.HTTPResponse.MergeWith(httpRes)
|
||||
|
||||
return handler.HTTPResponse{}, err
|
||||
return handler.HTTPResponse{}, handler.FileInfoChanges{}, err
|
||||
}
|
||||
|
||||
return httpRes, nil
|
||||
// Pass any changes regarding file info from the hook to the handler.
|
||||
changes := hookRes.ChangeFileInfo
|
||||
return httpRes, changes, nil
|
||||
}
|
||||
|
||||
func preFinishCallback(event handler.HookEvent) (handler.HTTPResponse, error) {
|
||||
|
|
|
@ -94,5 +94,12 @@ func unmarshal(res *pb.HookResponse) (hookRes HookResponse) {
|
|||
hookRes.HTTPResponse.Body = httpRes.Body
|
||||
}
|
||||
|
||||
changes := res.ChangeFileInfo
|
||||
if changes != nil {
|
||||
hookRes.ChangeFileInfo.ID = changes.Id
|
||||
hookRes.ChangeFileInfo.MetaData = changes.MetaData
|
||||
hookRes.ChangeFileInfo.Storage = changes.Storage
|
||||
}
|
||||
|
||||
return hookRes
|
||||
}
|
||||
|
|
|
@ -48,6 +48,13 @@ type HookResponse struct {
|
|||
// to the client.
|
||||
RejectUpload bool
|
||||
|
||||
// ChangeFileInfo can be set to change selected properties of an upload before
|
||||
// it has been created. See the handler.FileInfoChanges type for more details.
|
||||
// Changes are applied on a per-property basis, meaning that specifying just
|
||||
// one property leaves all others unchanged.
|
||||
// This value is only respected for pre-create hooks.
|
||||
ChangeFileInfo handler.FileInfoChanges
|
||||
|
||||
// StopUpload will cause the upload to be stopped during a PATCH request.
|
||||
// This value is only respected for post-receive hooks. For other hooks,
|
||||
// it is ignored. Use the HTTPResponse field to send details about the stop
|
||||
|
|
|
@ -1,13 +1,15 @@
|
|||
// If this file gets changed, you must recompile the generate package in pkg/proto.
|
||||
// To do this, install the Go protobuf toolchain as mentioned in
|
||||
// https://github.com/golang/protobuf#installation.
|
||||
// Then use following command to recompile it with gRPC support:
|
||||
// protoc --go_out=plugins=grpc:../../../../../pkg/proto/ v2/hook.proto
|
||||
// https://grpc.io/docs/languages/go/quickstart/#prerequisites.
|
||||
// Then use following command from the repository's root to recompile it with gRPC support:
|
||||
// protoc --go-grpc_out=./pkg/ --go_out=./pkg/ ./cmd/tusd/cli/hooks/proto/v2/hook.proto
|
||||
// In addition, it may be necessary to update the protobuf or gRPC dependencies as well.
|
||||
|
||||
syntax = "proto3";
|
||||
package v2;
|
||||
|
||||
option go_package = "proto/v2";
|
||||
|
||||
// HookRequest contains the information about the hook type, the involved upload,
|
||||
// and causing HTTP request.
|
||||
message HookRequest {
|
||||
|
@ -56,6 +58,35 @@ message FileInfo {
|
|||
map <string, string> storage = 9;
|
||||
}
|
||||
|
||||
// FileInfoChanges collects changes the should be made to a FileInfo object. This
|
||||
// can be done using the PreUploadCreateCallback to modify certain properties before
|
||||
// an upload is created. Properties which should not be modified (e.g. Size or Offset)
|
||||
// are intentionally left out here.
|
||||
message FileInfoChanges {
|
||||
// If ID is not empty, it will be passed to the data store, allowing
|
||||
// hooks to influence the upload ID. Be aware that a data store is not required to
|
||||
// respect a pre-defined upload ID and might overwrite or modify it. However,
|
||||
// all data stores in the github.com/tus/tusd package do respect pre-defined IDs.
|
||||
string id = 1;
|
||||
|
||||
// If MetaData is not nil, it replaces the entire user-defined meta data from
|
||||
// the upload creation request. You can add custom meta data fields this way
|
||||
// or ensure that only certain fields from the user-defined meta data are saved.
|
||||
// If you want to retain only specific entries from the user-defined meta data, you must
|
||||
// manually copy them into this MetaData field.
|
||||
// If you do not want to store any meta data, set this field to an empty map (`MetaData{}`).
|
||||
// If you want to keep the entire user-defined meta data, set this field to nil.
|
||||
map <string, string> metaData = 2;
|
||||
|
||||
// If Storage is not nil, it is passed to the data store to allow for minor adjustments
|
||||
// to the upload storage (e.g. destination file name). The details are specific for each
|
||||
// data store and should be looked up in their respective documentation.
|
||||
// Please be aware that this behavior is currently not supported by any data store in
|
||||
// the github.com/tus/tusd package.
|
||||
map <string, string> storage = 3;
|
||||
}
|
||||
|
||||
|
||||
// HTTPRequest contains basic details of an incoming HTTP request.
|
||||
message HTTPRequest {
|
||||
// Method is the HTTP method, e.g. POST or PATCH.
|
||||
|
@ -87,6 +118,13 @@ message HookResponse {
|
|||
// to the client.
|
||||
bool rejectUpload = 2;
|
||||
|
||||
// ChangeFileInfo can be set to change selected properties of an upload before
|
||||
// it has been created. See the handler.FileInfoChanges type for more details.
|
||||
// Changes are applied on a per-property basis, meaning that specifying just
|
||||
// one property leaves all others unchanged.
|
||||
// This value is only respected for pre-create hooks.
|
||||
FileInfoChanges changeFileInfo = 4;
|
||||
|
||||
// StopUpload will cause the upload to be stopped during a PATCH request.
|
||||
// This value is only respected for post-receive hooks. For other hooks,
|
||||
// it is ignored. Use the HTTPResponse field to send details about the stop
|
||||
|
@ -104,7 +142,6 @@ message HTTPResponse {
|
|||
string body = 3;
|
||||
}
|
||||
|
||||
|
||||
// The hook service definition.
|
||||
service HookHandler {
|
||||
// InvokeHook is invoked for every hook that is executed. HookRequest contains the
|
||||
|
|
|
@ -1,2 +1,2 @@
|
|||
hook_pb2.py:
|
||||
python -m grpc_tools.protoc --proto_path=../../../cmd/tusd/cli/hooks/proto/v2/ hook.proto --python_out=. --grpc_python_out=.
|
||||
hook_pb2.py: ../../../cmd/tusd/cli/hooks/proto/v2/hook.proto
|
||||
python3 -m grpc_tools.protoc --proto_path=../../../cmd/tusd/cli/hooks/proto/v2/ hook.proto --python_out=. --grpc_python_out=.
|
||||
|
|
|
@ -2,10 +2,9 @@
|
|||
# Generated by the protocol buffer compiler. DO NOT EDIT!
|
||||
# source: hook.proto
|
||||
"""Generated protocol buffer code."""
|
||||
from google.protobuf.internal import builder as _builder
|
||||
from google.protobuf import descriptor as _descriptor
|
||||
from google.protobuf import descriptor_pool as _descriptor_pool
|
||||
from google.protobuf import message as _message
|
||||
from google.protobuf import reflection as _reflection
|
||||
from google.protobuf import symbol_database as _symbol_database
|
||||
# @@protoc_insertion_point(imports)
|
||||
|
||||
|
@ -14,95 +13,10 @@ _sym_db = _symbol_database.Default()
|
|||
|
||||
|
||||
|
||||
DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n\nhook.proto\x12\x02v2\"5\n\x0bHookRequest\x12\x0c\n\x04type\x18\x01 \x01(\t\x12\x18\n\x05\x65vent\x18\x02 \x01(\x0b\x32\t.v2.Event\"K\n\x05\x45vent\x12\x1c\n\x06upload\x18\x01 \x01(\x0b\x32\x0c.v2.FileInfo\x12$\n\x0bhttpRequest\x18\x02 \x01(\x0b\x32\x0f.v2.HTTPRequest\"\xc3\x02\n\x08\x46ileInfo\x12\n\n\x02id\x18\x01 \x01(\t\x12\x0c\n\x04size\x18\x02 \x01(\x03\x12\x16\n\x0esizeIsDeferred\x18\x03 \x01(\x08\x12\x0e\n\x06offset\x18\x04 \x01(\x03\x12,\n\x08metaData\x18\x05 \x03(\x0b\x32\x1a.v2.FileInfo.MetaDataEntry\x12\x11\n\tisPartial\x18\x06 \x01(\x08\x12\x0f\n\x07isFinal\x18\x07 \x01(\x08\x12\x16\n\x0epartialUploads\x18\x08 \x03(\t\x12*\n\x07storage\x18\t \x03(\x0b\x32\x19.v2.FileInfo.StorageEntry\x1a/\n\rMetaDataEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\r\n\x05value\x18\x02 \x01(\t:\x02\x38\x01\x1a.\n\x0cStorageEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\r\n\x05value\x18\x02 \x01(\t:\x02\x38\x01\"\x9a\x01\n\x0bHTTPRequest\x12\x0e\n\x06method\x18\x01 \x01(\t\x12\x0b\n\x03uri\x18\x02 \x01(\t\x12\x12\n\nremoteAddr\x18\x03 \x01(\t\x12+\n\x06header\x18\x04 \x03(\x0b\x32\x1b.v2.HTTPRequest.HeaderEntry\x1a-\n\x0bHeaderEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\r\n\x05value\x18\x02 \x01(\t:\x02\x38\x01\"`\n\x0cHookResponse\x12&\n\x0chttpResponse\x18\x01 \x01(\x0b\x32\x10.v2.HTTPResponse\x12\x14\n\x0crejectUpload\x18\x02 \x01(\x08\x12\x12\n\nstopUpload\x18\x03 \x01(\x08\"\x90\x01\n\x0cHTTPResponse\x12\x12\n\nstatusCode\x18\x01 \x01(\x03\x12.\n\x07headers\x18\x02 \x03(\x0b\x32\x1d.v2.HTTPResponse.HeadersEntry\x12\x0c\n\x04\x62ody\x18\x03 \x01(\t\x1a.\n\x0cHeadersEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\r\n\x05value\x18\x02 \x01(\t:\x02\x38\x01\x32@\n\x0bHookHandler\x12\x31\n\nInvokeHook\x12\x0f.v2.HookRequest\x1a\x10.v2.HookResponse\"\x00\x62\x06proto3')
|
||||
DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n\nhook.proto\x12\x02v2\"5\n\x0bHookRequest\x12\x0c\n\x04type\x18\x01 \x01(\t\x12\x18\n\x05\x65vent\x18\x02 \x01(\x0b\x32\t.v2.Event\"K\n\x05\x45vent\x12\x1c\n\x06upload\x18\x01 \x01(\x0b\x32\x0c.v2.FileInfo\x12$\n\x0bhttpRequest\x18\x02 \x01(\x0b\x32\x0f.v2.HTTPRequest\"\xc3\x02\n\x08\x46ileInfo\x12\n\n\x02id\x18\x01 \x01(\t\x12\x0c\n\x04size\x18\x02 \x01(\x03\x12\x16\n\x0esizeIsDeferred\x18\x03 \x01(\x08\x12\x0e\n\x06offset\x18\x04 \x01(\x03\x12,\n\x08metaData\x18\x05 \x03(\x0b\x32\x1a.v2.FileInfo.MetaDataEntry\x12\x11\n\tisPartial\x18\x06 \x01(\x08\x12\x0f\n\x07isFinal\x18\x07 \x01(\x08\x12\x16\n\x0epartialUploads\x18\x08 \x03(\t\x12*\n\x07storage\x18\t \x03(\x0b\x32\x19.v2.FileInfo.StorageEntry\x1a/\n\rMetaDataEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\r\n\x05value\x18\x02 \x01(\t:\x02\x38\x01\x1a.\n\x0cStorageEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\r\n\x05value\x18\x02 \x01(\t:\x02\x38\x01\"\xe6\x01\n\x0f\x46ileInfoChanges\x12\n\n\x02id\x18\x01 \x01(\t\x12\x33\n\x08metaData\x18\x02 \x03(\x0b\x32!.v2.FileInfoChanges.MetaDataEntry\x12\x31\n\x07storage\x18\x03 \x03(\x0b\x32 .v2.FileInfoChanges.StorageEntry\x1a/\n\rMetaDataEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\r\n\x05value\x18\x02 \x01(\t:\x02\x38\x01\x1a.\n\x0cStorageEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\r\n\x05value\x18\x02 \x01(\t:\x02\x38\x01\"\x9a\x01\n\x0bHTTPRequest\x12\x0e\n\x06method\x18\x01 \x01(\t\x12\x0b\n\x03uri\x18\x02 \x01(\t\x12\x12\n\nremoteAddr\x18\x03 \x01(\t\x12+\n\x06header\x18\x04 \x03(\x0b\x32\x1b.v2.HTTPRequest.HeaderEntry\x1a-\n\x0bHeaderEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\r\n\x05value\x18\x02 \x01(\t:\x02\x38\x01\"\x8d\x01\n\x0cHookResponse\x12&\n\x0chttpResponse\x18\x01 \x01(\x0b\x32\x10.v2.HTTPResponse\x12\x14\n\x0crejectUpload\x18\x02 \x01(\x08\x12+\n\x0e\x63hangeFileInfo\x18\x04 \x01(\x0b\x32\x13.v2.FileInfoChanges\x12\x12\n\nstopUpload\x18\x03 \x01(\x08\"\x90\x01\n\x0cHTTPResponse\x12\x12\n\nstatusCode\x18\x01 \x01(\x03\x12.\n\x07headers\x18\x02 \x03(\x0b\x32\x1d.v2.HTTPResponse.HeadersEntry\x12\x0c\n\x04\x62ody\x18\x03 \x01(\t\x1a.\n\x0cHeadersEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\r\n\x05value\x18\x02 \x01(\t:\x02\x38\x01\x32@\n\x0bHookHandler\x12\x31\n\nInvokeHook\x12\x0f.v2.HookRequest\x1a\x10.v2.HookResponse\"\x00\x62\x06proto3')
|
||||
|
||||
|
||||
|
||||
_HOOKREQUEST = DESCRIPTOR.message_types_by_name['HookRequest']
|
||||
_EVENT = DESCRIPTOR.message_types_by_name['Event']
|
||||
_FILEINFO = DESCRIPTOR.message_types_by_name['FileInfo']
|
||||
_FILEINFO_METADATAENTRY = _FILEINFO.nested_types_by_name['MetaDataEntry']
|
||||
_FILEINFO_STORAGEENTRY = _FILEINFO.nested_types_by_name['StorageEntry']
|
||||
_HTTPREQUEST = DESCRIPTOR.message_types_by_name['HTTPRequest']
|
||||
_HTTPREQUEST_HEADERENTRY = _HTTPREQUEST.nested_types_by_name['HeaderEntry']
|
||||
_HOOKRESPONSE = DESCRIPTOR.message_types_by_name['HookResponse']
|
||||
_HTTPRESPONSE = DESCRIPTOR.message_types_by_name['HTTPResponse']
|
||||
_HTTPRESPONSE_HEADERSENTRY = _HTTPRESPONSE.nested_types_by_name['HeadersEntry']
|
||||
HookRequest = _reflection.GeneratedProtocolMessageType('HookRequest', (_message.Message,), {
|
||||
'DESCRIPTOR' : _HOOKREQUEST,
|
||||
'__module__' : 'hook_pb2'
|
||||
# @@protoc_insertion_point(class_scope:v2.HookRequest)
|
||||
})
|
||||
_sym_db.RegisterMessage(HookRequest)
|
||||
|
||||
Event = _reflection.GeneratedProtocolMessageType('Event', (_message.Message,), {
|
||||
'DESCRIPTOR' : _EVENT,
|
||||
'__module__' : 'hook_pb2'
|
||||
# @@protoc_insertion_point(class_scope:v2.Event)
|
||||
})
|
||||
_sym_db.RegisterMessage(Event)
|
||||
|
||||
FileInfo = _reflection.GeneratedProtocolMessageType('FileInfo', (_message.Message,), {
|
||||
|
||||
'MetaDataEntry' : _reflection.GeneratedProtocolMessageType('MetaDataEntry', (_message.Message,), {
|
||||
'DESCRIPTOR' : _FILEINFO_METADATAENTRY,
|
||||
'__module__' : 'hook_pb2'
|
||||
# @@protoc_insertion_point(class_scope:v2.FileInfo.MetaDataEntry)
|
||||
})
|
||||
,
|
||||
|
||||
'StorageEntry' : _reflection.GeneratedProtocolMessageType('StorageEntry', (_message.Message,), {
|
||||
'DESCRIPTOR' : _FILEINFO_STORAGEENTRY,
|
||||
'__module__' : 'hook_pb2'
|
||||
# @@protoc_insertion_point(class_scope:v2.FileInfo.StorageEntry)
|
||||
})
|
||||
,
|
||||
'DESCRIPTOR' : _FILEINFO,
|
||||
'__module__' : 'hook_pb2'
|
||||
# @@protoc_insertion_point(class_scope:v2.FileInfo)
|
||||
})
|
||||
_sym_db.RegisterMessage(FileInfo)
|
||||
_sym_db.RegisterMessage(FileInfo.MetaDataEntry)
|
||||
_sym_db.RegisterMessage(FileInfo.StorageEntry)
|
||||
|
||||
HTTPRequest = _reflection.GeneratedProtocolMessageType('HTTPRequest', (_message.Message,), {
|
||||
|
||||
'HeaderEntry' : _reflection.GeneratedProtocolMessageType('HeaderEntry', (_message.Message,), {
|
||||
'DESCRIPTOR' : _HTTPREQUEST_HEADERENTRY,
|
||||
'__module__' : 'hook_pb2'
|
||||
# @@protoc_insertion_point(class_scope:v2.HTTPRequest.HeaderEntry)
|
||||
})
|
||||
,
|
||||
'DESCRIPTOR' : _HTTPREQUEST,
|
||||
'__module__' : 'hook_pb2'
|
||||
# @@protoc_insertion_point(class_scope:v2.HTTPRequest)
|
||||
})
|
||||
_sym_db.RegisterMessage(HTTPRequest)
|
||||
_sym_db.RegisterMessage(HTTPRequest.HeaderEntry)
|
||||
|
||||
HookResponse = _reflection.GeneratedProtocolMessageType('HookResponse', (_message.Message,), {
|
||||
'DESCRIPTOR' : _HOOKRESPONSE,
|
||||
'__module__' : 'hook_pb2'
|
||||
# @@protoc_insertion_point(class_scope:v2.HookResponse)
|
||||
})
|
||||
_sym_db.RegisterMessage(HookResponse)
|
||||
|
||||
HTTPResponse = _reflection.GeneratedProtocolMessageType('HTTPResponse', (_message.Message,), {
|
||||
|
||||
'HeadersEntry' : _reflection.GeneratedProtocolMessageType('HeadersEntry', (_message.Message,), {
|
||||
'DESCRIPTOR' : _HTTPRESPONSE_HEADERSENTRY,
|
||||
'__module__' : 'hook_pb2'
|
||||
# @@protoc_insertion_point(class_scope:v2.HTTPResponse.HeadersEntry)
|
||||
})
|
||||
,
|
||||
'DESCRIPTOR' : _HTTPRESPONSE,
|
||||
'__module__' : 'hook_pb2'
|
||||
# @@protoc_insertion_point(class_scope:v2.HTTPResponse)
|
||||
})
|
||||
_sym_db.RegisterMessage(HTTPResponse)
|
||||
_sym_db.RegisterMessage(HTTPResponse.HeadersEntry)
|
||||
|
||||
_HOOKHANDLER = DESCRIPTOR.services_by_name['HookHandler']
|
||||
_builder.BuildMessageAndEnumDescriptors(DESCRIPTOR, globals())
|
||||
_builder.BuildTopDescriptorsAndMessages(DESCRIPTOR, 'hook_pb2', globals())
|
||||
if _descriptor._USE_C_DESCRIPTORS == False:
|
||||
|
||||
DESCRIPTOR._options = None
|
||||
|
@ -110,6 +24,10 @@ if _descriptor._USE_C_DESCRIPTORS == False:
|
|||
_FILEINFO_METADATAENTRY._serialized_options = b'8\001'
|
||||
_FILEINFO_STORAGEENTRY._options = None
|
||||
_FILEINFO_STORAGEENTRY._serialized_options = b'8\001'
|
||||
_FILEINFOCHANGES_METADATAENTRY._options = None
|
||||
_FILEINFOCHANGES_METADATAENTRY._serialized_options = b'8\001'
|
||||
_FILEINFOCHANGES_STORAGEENTRY._options = None
|
||||
_FILEINFOCHANGES_STORAGEENTRY._serialized_options = b'8\001'
|
||||
_HTTPREQUEST_HEADERENTRY._options = None
|
||||
_HTTPREQUEST_HEADERENTRY._serialized_options = b'8\001'
|
||||
_HTTPRESPONSE_HEADERSENTRY._options = None
|
||||
|
@ -124,16 +42,22 @@ if _descriptor._USE_C_DESCRIPTORS == False:
|
|||
_FILEINFO_METADATAENTRY._serialized_end=426
|
||||
_FILEINFO_STORAGEENTRY._serialized_start=428
|
||||
_FILEINFO_STORAGEENTRY._serialized_end=474
|
||||
_HTTPREQUEST._serialized_start=477
|
||||
_HTTPREQUEST._serialized_end=631
|
||||
_HTTPREQUEST_HEADERENTRY._serialized_start=586
|
||||
_HTTPREQUEST_HEADERENTRY._serialized_end=631
|
||||
_HOOKRESPONSE._serialized_start=633
|
||||
_HOOKRESPONSE._serialized_end=729
|
||||
_HTTPRESPONSE._serialized_start=732
|
||||
_HTTPRESPONSE._serialized_end=876
|
||||
_HTTPRESPONSE_HEADERSENTRY._serialized_start=830
|
||||
_HTTPRESPONSE_HEADERSENTRY._serialized_end=876
|
||||
_HOOKHANDLER._serialized_start=878
|
||||
_HOOKHANDLER._serialized_end=942
|
||||
_FILEINFOCHANGES._serialized_start=477
|
||||
_FILEINFOCHANGES._serialized_end=707
|
||||
_FILEINFOCHANGES_METADATAENTRY._serialized_start=379
|
||||
_FILEINFOCHANGES_METADATAENTRY._serialized_end=426
|
||||
_FILEINFOCHANGES_STORAGEENTRY._serialized_start=428
|
||||
_FILEINFOCHANGES_STORAGEENTRY._serialized_end=474
|
||||
_HTTPREQUEST._serialized_start=710
|
||||
_HTTPREQUEST._serialized_end=864
|
||||
_HTTPREQUEST_HEADERENTRY._serialized_start=819
|
||||
_HTTPREQUEST_HEADERENTRY._serialized_end=864
|
||||
_HOOKRESPONSE._serialized_start=867
|
||||
_HOOKRESPONSE._serialized_end=1008
|
||||
_HTTPRESPONSE._serialized_start=1011
|
||||
_HTTPRESPONSE._serialized_end=1155
|
||||
_HTTPRESPONSE_HEADERSENTRY._serialized_start=1109
|
||||
_HTTPRESPONSE_HEADERSENTRY._serialized_end=1155
|
||||
_HOOKHANDLER._serialized_start=1157
|
||||
_HOOKHANDLER._serialized_end=1221
|
||||
# @@protoc_insertion_point(module_scope)
|
||||
|
|
|
@ -27,7 +27,11 @@ class HookHandlerServicer(object):
|
|||
"""
|
||||
|
||||
def InvokeHook(self, request, context):
|
||||
"""Sends a hook
|
||||
"""InvokeHook is invoked for every hook that is executed. HookRequest contains the
|
||||
corresponding information about the hook type, the involved upload, and
|
||||
causing HTTP request.
|
||||
The return value HookResponse allows to stop or reject an upload, as well as modifying
|
||||
the HTTP response. See the documentation for HookResponse for more details.
|
||||
"""
|
||||
context.set_code(grpc.StatusCode.UNIMPLEMENTED)
|
||||
context.set_details('Method not implemented!')
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
import grpc
|
||||
from concurrent import futures
|
||||
import time
|
||||
import uuid
|
||||
import hook_pb2_grpc as pb2_grpc
|
||||
import hook_pb2 as pb2
|
||||
|
||||
|
@ -19,13 +20,22 @@ class HookHandler(pb2_grpc.HookHandlerServicer):
|
|||
|
||||
# Example: Use the pre-create hook to check if a filename has been supplied
|
||||
# using metadata. If not, the upload is rejected with a custom HTTP response.
|
||||
# In addition, a custom upload ID with a choosable prefix is supplied.
|
||||
# Metadata is configured, so that it only retains the filename meta data
|
||||
# and the creation time.
|
||||
if hook_request.type == 'pre-create':
|
||||
filename = hook_request.event.upload.metaData['filename']
|
||||
if filename == "":
|
||||
metaData = hook_request.event.upload.metaData
|
||||
isValid = 'filename' in metaData
|
||||
if not isValid:
|
||||
hook_response.rejectUpload = True
|
||||
hook_response.httpResponse.statusCode = 400
|
||||
hook_response.httpResponse.body = 'no filename provided'
|
||||
hook_response.httpResponse.headers['X-Some-Header'] = 'yes'
|
||||
else:
|
||||
hook_response.changeFileInfo.id = f'prefix-{uuid.uuid4()}'
|
||||
hook_response.changeFileInfo.metaData
|
||||
hook_response.changeFileInfo.metaData['filename'] = metaData['filename']
|
||||
hook_response.changeFileInfo.metaData['creation_time'] = time.ctime()
|
||||
|
||||
# Example: Use the post-finish hook to print information about a completed upload,
|
||||
# including its storage location.
|
||||
|
|
|
@ -2,6 +2,8 @@ from http.server import HTTPServer, BaseHTTPRequestHandler
|
|||
from io import BytesIO
|
||||
|
||||
import json
|
||||
import time
|
||||
import uuid
|
||||
|
||||
class HTTPHookHandler(BaseHTTPRequestHandler):
|
||||
|
||||
|
@ -29,13 +31,25 @@ class HTTPHookHandler(BaseHTTPRequestHandler):
|
|||
|
||||
# Example: Use the pre-create hook to check if a filename has been supplied
|
||||
# using metadata. If not, the upload is rejected with a custom HTTP response.
|
||||
# In addition, a custom upload ID with a choosable prefix is supplied.
|
||||
# Metadata is configured, so that it only retains the filename meta data
|
||||
# and the creation time.
|
||||
if hook_request['Type'] == 'pre-create':
|
||||
metaData = hook_request['Event']['Upload']['MetaData']
|
||||
if 'filename' not in metaData:
|
||||
isValid = 'filename' in metaData
|
||||
if not isValid:
|
||||
hook_response['RejectUpload'] = True
|
||||
hook_response['HTTPResponse']['StatusCode'] = 400
|
||||
hook_response['HTTPResponse']['Body'] = 'no filename provided'
|
||||
hook_response['HTTPResponse']['Headers']['X-Some-Header'] = 'yes'
|
||||
else:
|
||||
hook_response['ChangeFileInfo'] = {}
|
||||
hook_response['ChangeFileInfo']['ID'] = f'prefix-{uuid.uuid4()}'
|
||||
hook_response['ChangeFileInfo']['MetaData'] = {
|
||||
'filename': metaData['filename'],
|
||||
'creation_time': time.ctime(),
|
||||
}
|
||||
|
||||
|
||||
# Example: Use the post-finish hook to print information about a completed upload,
|
||||
# including its storage location.
|
||||
|
|
2
go.mod
2
go.mod
|
@ -13,7 +13,6 @@ require (
|
|||
github.com/felixge/fgprof v0.9.2
|
||||
github.com/goji/httpauth v0.0.0-20160601135302-2da839ab0f4d
|
||||
github.com/golang/mock v1.6.0
|
||||
github.com/golang/protobuf v1.5.3
|
||||
github.com/grpc-ecosystem/go-grpc-middleware v1.4.0
|
||||
github.com/hashicorp/go-hclog v0.14.1
|
||||
github.com/hashicorp/go-plugin v1.4.3
|
||||
|
@ -24,6 +23,7 @@ require (
|
|||
github.com/vimeo/go-util v1.4.1
|
||||
google.golang.org/api v0.125.0
|
||||
google.golang.org/grpc v1.55.0
|
||||
google.golang.org/protobuf v1.30.0
|
||||
gopkg.in/Acconut/lockfile.v1 v1.1.0
|
||||
gopkg.in/h2non/gock.v1 v1.1.2
|
||||
)
|
||||
|
|
|
@ -60,7 +60,10 @@ type Config struct {
|
|||
// If the error is non-nil, the upload will not be created. This can be used to implement
|
||||
// validation of upload metadata etc. Furthermore, HTTPResponse will be ignored and
|
||||
// the error value can contain values for the HTTP response.
|
||||
PreUploadCreateCallback func(hook HookEvent) (HTTPResponse, error)
|
||||
// If the error is nil, FileInfoChanges can be filled out to specify individual properties
|
||||
// that should be overwriten before the upload is create. See its type definition for
|
||||
// more details on its behavior. If you do not want to make any changes, return an empty struct.
|
||||
PreUploadCreateCallback func(hook HookEvent) (HTTPResponse, FileInfoChanges, error)
|
||||
// PreFinishResponseCallback will be invoked after an upload is completed but before
|
||||
// a response is returned to the client. This can be used to implement post-processing validation.
|
||||
// If the callback returns no error, optional values from HTTPResponse will be contained in the HTTP response.
|
||||
|
|
|
@ -50,6 +50,34 @@ func (f FileInfo) StopUpload() {
|
|||
}
|
||||
}
|
||||
|
||||
// FileInfoChanges collects changes the should be made to a FileInfo struct. This
|
||||
// can be done using the PreUploadCreateCallback to modify certain properties before
|
||||
// an upload is created. Properties which should not be modified (e.g. Size or Offset)
|
||||
// are intentionally left out here.
|
||||
type FileInfoChanges struct {
|
||||
// If ID is not empty, it will be passed to the data store, allowing
|
||||
// hooks to influence the upload ID. Be aware that a data store is not required to
|
||||
// respect a pre-defined upload ID and might overwrite or modify it. However,
|
||||
// all data stores in the github.com/tus/tusd package do respect pre-defined IDs.
|
||||
ID string
|
||||
|
||||
// If MetaData is not nil, it replaces the entire user-defined meta data from
|
||||
// the upload creation request. You can add custom meta data fields this way
|
||||
// or ensure that only certain fields from the user-defined meta data are saved.
|
||||
// If you want to retain only specific entries from the user-defined meta data, you must
|
||||
// manually copy them into this MetaData field.
|
||||
// If you do not want to store any meta data, set this field to an empty map (`MetaData{}`).
|
||||
// If you want to keep the entire user-defined meta data, set this field to nil.
|
||||
MetaData MetaData
|
||||
|
||||
// If Storage is not nil, it is passed to the data store to allow for minor adjustments
|
||||
// to the upload storage (e.g. destination file name). The details are specific for each
|
||||
// data store and should be looked up in their respective documentation.
|
||||
// Please be aware that this behavior is currently not supported by any data store in
|
||||
// the github.com/tus/tusd package.
|
||||
Storage map[string]string
|
||||
}
|
||||
|
||||
type Upload interface {
|
||||
// Write the chunk read from src into the file specified by the id at the
|
||||
// given offset. The handler will take care of validating the offset and
|
||||
|
|
|
@ -322,12 +322,25 @@ func (handler *UnroutedHandler) PostFile(w http.ResponseWriter, r *http.Request)
|
|||
}
|
||||
|
||||
if handler.config.PreUploadCreateCallback != nil {
|
||||
resp2, err := handler.config.PreUploadCreateCallback(newHookEvent(info, r))
|
||||
resp2, changes, err := handler.config.PreUploadCreateCallback(newHookEvent(info, r))
|
||||
if err != nil {
|
||||
handler.sendError(c, err)
|
||||
return
|
||||
}
|
||||
resp = resp.MergeWith(resp2)
|
||||
|
||||
// Apply changes returned from the pre-create hook.
|
||||
if changes.ID != "" {
|
||||
info.ID = changes.ID
|
||||
}
|
||||
|
||||
if changes.MetaData != nil {
|
||||
info.MetaData = changes.MetaData
|
||||
}
|
||||
|
||||
if changes.Storage != nil {
|
||||
info.Storage = changes.Storage
|
||||
}
|
||||
}
|
||||
|
||||
upload, err := handler.composer.Core.NewUpload(c, info)
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,115 @@
|
|||
// Code generated by protoc-gen-go-grpc. DO NOT EDIT.
|
||||
// versions:
|
||||
// - protoc-gen-go-grpc v1.2.0
|
||||
// - protoc v3.21.12
|
||||
// source: cmd/tusd/cli/hooks/proto/v2/hook.proto
|
||||
|
||||
package v2
|
||||
|
||||
import (
|
||||
context "context"
|
||||
grpc "google.golang.org/grpc"
|
||||
codes "google.golang.org/grpc/codes"
|
||||
status "google.golang.org/grpc/status"
|
||||
)
|
||||
|
||||
// This is a compile-time assertion to ensure that this generated file
|
||||
// is compatible with the grpc package it is being compiled against.
|
||||
// Requires gRPC-Go v1.32.0 or later.
|
||||
const _ = grpc.SupportPackageIsVersion7
|
||||
|
||||
// HookHandlerClient is the client API for HookHandler service.
|
||||
//
|
||||
// For semantics around ctx use and closing/ending streaming RPCs, please refer to https://pkg.go.dev/google.golang.org/grpc/?tab=doc#ClientConn.NewStream.
|
||||
type HookHandlerClient interface {
|
||||
// InvokeHook is invoked for every hook that is executed. HookRequest contains the
|
||||
// corresponding information about the hook type, the involved upload, and
|
||||
// causing HTTP request.
|
||||
// The return value HookResponse allows to stop or reject an upload, as well as modifying
|
||||
// the HTTP response. See the documentation for HookResponse for more details.
|
||||
InvokeHook(ctx context.Context, in *HookRequest, opts ...grpc.CallOption) (*HookResponse, error)
|
||||
}
|
||||
|
||||
type hookHandlerClient struct {
|
||||
cc grpc.ClientConnInterface
|
||||
}
|
||||
|
||||
func NewHookHandlerClient(cc grpc.ClientConnInterface) HookHandlerClient {
|
||||
return &hookHandlerClient{cc}
|
||||
}
|
||||
|
||||
func (c *hookHandlerClient) InvokeHook(ctx context.Context, in *HookRequest, opts ...grpc.CallOption) (*HookResponse, error) {
|
||||
out := new(HookResponse)
|
||||
err := c.cc.Invoke(ctx, "/v2.HookHandler/InvokeHook", in, out, opts...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return out, nil
|
||||
}
|
||||
|
||||
// HookHandlerServer is the server API for HookHandler service.
|
||||
// All implementations must embed UnimplementedHookHandlerServer
|
||||
// for forward compatibility
|
||||
type HookHandlerServer interface {
|
||||
// InvokeHook is invoked for every hook that is executed. HookRequest contains the
|
||||
// corresponding information about the hook type, the involved upload, and
|
||||
// causing HTTP request.
|
||||
// The return value HookResponse allows to stop or reject an upload, as well as modifying
|
||||
// the HTTP response. See the documentation for HookResponse for more details.
|
||||
InvokeHook(context.Context, *HookRequest) (*HookResponse, error)
|
||||
mustEmbedUnimplementedHookHandlerServer()
|
||||
}
|
||||
|
||||
// UnimplementedHookHandlerServer must be embedded to have forward compatible implementations.
|
||||
type UnimplementedHookHandlerServer struct {
|
||||
}
|
||||
|
||||
func (UnimplementedHookHandlerServer) InvokeHook(context.Context, *HookRequest) (*HookResponse, error) {
|
||||
return nil, status.Errorf(codes.Unimplemented, "method InvokeHook not implemented")
|
||||
}
|
||||
func (UnimplementedHookHandlerServer) mustEmbedUnimplementedHookHandlerServer() {}
|
||||
|
||||
// UnsafeHookHandlerServer may be embedded to opt out of forward compatibility for this service.
|
||||
// Use of this interface is not recommended, as added methods to HookHandlerServer will
|
||||
// result in compilation errors.
|
||||
type UnsafeHookHandlerServer interface {
|
||||
mustEmbedUnimplementedHookHandlerServer()
|
||||
}
|
||||
|
||||
func RegisterHookHandlerServer(s grpc.ServiceRegistrar, srv HookHandlerServer) {
|
||||
s.RegisterService(&HookHandler_ServiceDesc, srv)
|
||||
}
|
||||
|
||||
func _HookHandler_InvokeHook_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
|
||||
in := new(HookRequest)
|
||||
if err := dec(in); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if interceptor == nil {
|
||||
return srv.(HookHandlerServer).InvokeHook(ctx, in)
|
||||
}
|
||||
info := &grpc.UnaryServerInfo{
|
||||
Server: srv,
|
||||
FullMethod: "/v2.HookHandler/InvokeHook",
|
||||
}
|
||||
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
|
||||
return srv.(HookHandlerServer).InvokeHook(ctx, req.(*HookRequest))
|
||||
}
|
||||
return interceptor(ctx, in, info, handler)
|
||||
}
|
||||
|
||||
// HookHandler_ServiceDesc is the grpc.ServiceDesc for HookHandler service.
|
||||
// It's only intended for direct use with grpc.RegisterService,
|
||||
// and not to be introspected or modified (even as a copy)
|
||||
var HookHandler_ServiceDesc = grpc.ServiceDesc{
|
||||
ServiceName: "v2.HookHandler",
|
||||
HandlerType: (*HookHandlerServer)(nil),
|
||||
Methods: []grpc.MethodDesc{
|
||||
{
|
||||
MethodName: "InvokeHook",
|
||||
Handler: _HookHandler_InvokeHook_Handler,
|
||||
},
|
||||
},
|
||||
Streams: []grpc.StreamDesc{},
|
||||
Metadata: "cmd/tusd/cli/hooks/proto/v2/hook.proto",
|
||||
}
|
Loading…
Reference in New Issue