initial changes

This commit is contained in:
benito 2021-05-27 15:57:32 +08:00 committed by benitogf
parent 84faa14987
commit d00435048d
7 changed files with 39 additions and 2 deletions

View File

@ -43,6 +43,10 @@ func preFinishCallback(info handler.HookEvent) error {
return hookCallback(hooks.HookPreFinish, info) return hookCallback(hooks.HookPreFinish, info)
} }
func preGetCallback(info handler.HookEvent) error {
return hookCallback(hooks.HookPreGet, info)
}
func SetupHookMetrics() { func SetupHookMetrics() {
MetricsHookErrorsTotal.WithLabelValues(string(hooks.HookPostFinish)).Add(0) MetricsHookErrorsTotal.WithLabelValues(string(hooks.HookPostFinish)).Add(0)
MetricsHookErrorsTotal.WithLabelValues(string(hooks.HookPostTerminate)).Add(0) MetricsHookErrorsTotal.WithLabelValues(string(hooks.HookPostTerminate)).Add(0)
@ -50,6 +54,7 @@ func SetupHookMetrics() {
MetricsHookErrorsTotal.WithLabelValues(string(hooks.HookPostCreate)).Add(0) MetricsHookErrorsTotal.WithLabelValues(string(hooks.HookPostCreate)).Add(0)
MetricsHookErrorsTotal.WithLabelValues(string(hooks.HookPreCreate)).Add(0) MetricsHookErrorsTotal.WithLabelValues(string(hooks.HookPreCreate)).Add(0)
MetricsHookErrorsTotal.WithLabelValues(string(hooks.HookPreFinish)).Add(0) MetricsHookErrorsTotal.WithLabelValues(string(hooks.HookPreFinish)).Add(0)
MetricsHookErrorsTotal.WithLabelValues(string(hooks.HookPreGet)).Add(0)
} }
func SetupPreHooks(config *handler.Config) error { func SetupPreHooks(config *handler.Config) error {
@ -99,6 +104,7 @@ func SetupPreHooks(config *handler.Config) error {
config.PreUploadCreateCallback = preCreateCallback config.PreUploadCreateCallback = preCreateCallback
config.PreFinishResponseCallback = preFinishCallback config.PreFinishResponseCallback = preFinishCallback
config.PreGetResponseCallback = preGetCallback
return nil return nil
} }
@ -115,6 +121,8 @@ func SetupPostHooks(handler *handler.Handler) {
invokeHookAsync(hooks.HookPostReceive, info) invokeHookAsync(hooks.HookPostReceive, info)
case info := <-handler.CreatedUploads: case info := <-handler.CreatedUploads:
invokeHookAsync(hooks.HookPostCreate, info) invokeHookAsync(hooks.HookPostCreate, info)
case info := <-handler.GetUploads:
invokeHookAsync(hooks.HookPreGet, info)
} }
} }
}() }()

View File

@ -18,9 +18,10 @@ const (
HookPostCreate HookType = "post-create" HookPostCreate HookType = "post-create"
HookPreCreate HookType = "pre-create" HookPreCreate HookType = "pre-create"
HookPreFinish HookType = "pre-finish" HookPreFinish HookType = "pre-finish"
HookPreGet HookType = "pre-get"
) )
var AvailableHooks []HookType = []HookType{HookPreCreate, HookPostCreate, HookPostReceive, HookPostTerminate, HookPostFinish, HookPreFinish} var AvailableHooks []HookType = []HookType{HookPreCreate, HookPostCreate, HookPostReceive, HookPostTerminate, HookPostFinish, HookPreFinish, HookPreGet}
type hookDataStore struct { type hookDataStore struct {
handler.DataStore handler.DataStore

View File

@ -14,6 +14,7 @@ type PluginHookHandler interface {
PostFinish(info handler.HookEvent) error PostFinish(info handler.HookEvent) error
PostTerminate(info handler.HookEvent) error PostTerminate(info handler.HookEvent) error
PreFinish(info handler.HookEvent) error PreFinish(info handler.HookEvent) error
PreGet(info handler.HookEvent) error
} }
type PluginHook struct { type PluginHook struct {
@ -57,6 +58,8 @@ func (h PluginHook) InvokeHook(typ HookType, info handler.HookEvent, captureOutp
err = h.handler.PreCreate(info) err = h.handler.PreCreate(info)
case HookPreFinish: case HookPreFinish:
err = h.handler.PreFinish(info) err = h.handler.PreFinish(info)
case HookPreGet:
err = h.handler.PreGet(info)
default: default:
err = fmt.Errorf("hooks: unknown hook named %s", typ) err = fmt.Errorf("hooks: unknown hook named %s", typ)
} }

View File

@ -13,7 +13,7 @@ If not otherwise noted, all hooks are invoked in a *non-blocking* way, meaning t
## Blocking Hooks ## Blocking Hooks
On the other hand, there are a few *blocking* hooks, such as caused by the `pre-create` and `pre-finish` events. Because their exit code will dictate whether tusd will accept the current incoming request, tusd will wait until the hook process has exited. Therefore, in order to keep the response times low, one should avoid to make time-consuming operations inside the processes for blocking hooks. On the other hand, there are a few *blocking* hooks, such as caused by the `pre-create`, `pre-get` and `pre-finish` events. Because their exit code will dictate whether tusd will accept the current incoming request, tusd will wait until the hook process has exited. Therefore, in order to keep the response times low, one should avoid to make time-consuming operations inside the processes for blocking hooks.
### Blocking File Hooks ### Blocking File Hooks
@ -39,6 +39,12 @@ This event will be triggered after an upload is fully finished but before a resp
This is a blocking hook, as such it can be used to validate or post-process an uploaded file. This is a blocking hook, as such it can be used to validate or post-process an uploaded file.
A non-zero exit code or HTTP response greater than `400` will return a HTTP 500 error to the client. A non-zero exit code or HTTP response greater than `400` will return a HTTP 500 error to the client.
### pre-get
This event will be triggered before an upload read returned to the client.
This is a blocking hook, as such it can be used to validate access limits.
A non-zero exit code or HTTP response greater than `400` will return a HTTP 500 error to the client.
### post-finish ### post-finish
This event will be triggered after an upload is fully finished, meaning that all chunks have been transfered and saved in the storage. After this point, no further modifications, except possible deletion, can be made to the upload entity and it may be desirable to use the file for further processing or notify other applications of the completions of this upload. This event will be triggered after an upload is fully finished, meaning that all chunks have been transfered and saved in the storage. After this point, no further modifications, except possible deletion, can be made to the upload entity and it may be desirable to use the file for further processing or notify other applications of the completions of this upload.

7
examples/hooks/pre-get Normal file
View File

@ -0,0 +1,7 @@
#!/bin/sh
filename=$(cat /dev/stdin | jq .MetaData.filename)
if [[ $filename != "public" ]; then
echo "Error: access unauthorized"
exit 1
fi

View File

@ -40,6 +40,11 @@ type Config struct {
// potentially set by proxies when generating an absolute URL in the // potentially set by proxies when generating an absolute URL in the
// response to POST requests. // response to POST requests.
RespectForwardedHeaders bool RespectForwardedHeaders bool
// PreGetCallback will be invoked before an upload is read, if the
// property is supplied. If the callback returns nil, the upload will be sent.
// Otherwise the HTTP request will be aborted. This can be used to implement
// accesss limits.
PreGetCallback func(hook HookEvent) error
// PreUploadCreateCallback will be invoked before a new upload is created, if the // PreUploadCreateCallback will be invoked before a new upload is created, if the
// property is supplied. If the callback returns nil, the upload will be created. // property is supplied. If the callback returns nil, the upload will be created.
// Otherwise the HTTP request will be aborted. This can be used to implement // Otherwise the HTTP request will be aborted. This can be used to implement

View File

@ -741,6 +741,13 @@ func (handler *UnroutedHandler) GetFile(w http.ResponseWriter, r *http.Request)
return return
} }
if handler.config.PreGetCallback != nil {
if err := handler.config.PreGetCallback(newHookEvent(info, r)); err != nil {
handler.sendError(w, r, err)
return
}
}
// Set headers before sending responses // Set headers before sending responses
w.Header().Set("Content-Length", strconv.FormatInt(info.Offset, 10)) w.Header().Set("Content-Length", strconv.FormatInt(info.Offset, 10))