fixes #388
Responses to the pre-finish hook will be passed to the client as custom header "X-pre-finish-response"
This commit is contained in:
parent
52181920c2
commit
c611f55608
|
@ -20,27 +20,31 @@ func hookTypeInSlice(a hooks.HookType, list []hooks.HookType) bool {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
func hookCallback(typ hooks.HookType, info handler.HookEvent) error {
|
func hookCallback(typ hooks.HookType, info handler.HookEvent, captureOutput bool) (error, []byte) {
|
||||||
if output, err := invokeHookSync(typ, info, true); err != nil {
|
output, err := invokeHookSync(typ, info, true)
|
||||||
|
if err != nil {
|
||||||
if hookErr, ok := err.(hooks.HookError); ok {
|
if hookErr, ok := err.(hooks.HookError); ok {
|
||||||
return hooks.NewHookError(
|
return hooks.NewHookError(
|
||||||
fmt.Errorf("%s hook failed: %s", typ, err),
|
fmt.Errorf("%s hook failed: %s", typ, err),
|
||||||
hookErr.StatusCode(),
|
hookErr.StatusCode(),
|
||||||
hookErr.Body(),
|
hookErr.Body(),
|
||||||
)
|
), nil
|
||||||
}
|
}
|
||||||
return fmt.Errorf("%s hook failed: %s\n%s", typ, err, string(output))
|
return fmt.Errorf("%s hook failed: %s\n%s", typ, err, string(output)), nil
|
||||||
}
|
}
|
||||||
|
if captureOutput {
|
||||||
return nil
|
return nil, output
|
||||||
|
}
|
||||||
|
return nil, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func preCreateCallback(info handler.HookEvent) error {
|
func preCreateCallback(info handler.HookEvent) error {
|
||||||
return hookCallback(hooks.HookPreCreate, info)
|
err, _ := hookCallback(hooks.HookPreCreate, info, false)
|
||||||
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
func preFinishCallback(info handler.HookEvent) error {
|
func preFinishCallback(info handler.HookEvent) (error, []byte) {
|
||||||
return hookCallback(hooks.HookPreFinish, info)
|
return hookCallback(hooks.HookPreFinish, info, true)
|
||||||
}
|
}
|
||||||
|
|
||||||
func SetupHookMetrics() {
|
func SetupHookMetrics() {
|
||||||
|
|
|
@ -48,7 +48,7 @@ type Config struct {
|
||||||
// PreFinishResponseCallback will be invoked after an upload is completed but before
|
// PreFinishResponseCallback will be invoked after an upload is completed but before
|
||||||
// a response is returned to the client. Error responses from the callback will be passed
|
// a response is returned to the client. Error responses from the callback will be passed
|
||||||
// back to the client. This can be used to implement post-processing validation.
|
// back to the client. This can be used to implement post-processing validation.
|
||||||
PreFinishResponseCallback func(hook HookEvent) error
|
PreFinishResponseCallback func(hook HookEvent) (error, []byte)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (config *Config) validate() error {
|
func (config *Config) validate() error {
|
||||||
|
|
|
@ -406,7 +406,7 @@ func (handler *UnroutedHandler) PostFile(w http.ResponseWriter, r *http.Request)
|
||||||
// Directly finish the upload if the upload is empty (i.e. has a size of 0).
|
// Directly finish the upload if the upload is empty (i.e. has a size of 0).
|
||||||
// This statement is in an else-if block to avoid causing duplicate calls
|
// This statement is in an else-if block to avoid causing duplicate calls
|
||||||
// to finishUploadIfComplete if an upload is empty and contains a chunk.
|
// to finishUploadIfComplete if an upload is empty and contains a chunk.
|
||||||
if err := handler.finishUploadIfComplete(ctx, upload, info, r); err != nil {
|
if err := handler.finishUploadIfComplete(ctx, upload, info, r, w); err != nil {
|
||||||
handler.sendError(w, r, err)
|
handler.sendError(w, r, err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
@ -668,13 +668,13 @@ func (handler *UnroutedHandler) writeChunk(ctx context.Context, upload Upload, i
|
||||||
handler.Metrics.incBytesReceived(uint64(bytesWritten))
|
handler.Metrics.incBytesReceived(uint64(bytesWritten))
|
||||||
info.Offset = newOffset
|
info.Offset = newOffset
|
||||||
|
|
||||||
return handler.finishUploadIfComplete(ctx, upload, info, r)
|
return handler.finishUploadIfComplete(ctx, upload, info, r, w)
|
||||||
}
|
}
|
||||||
|
|
||||||
// finishUploadIfComplete checks whether an upload is completed (i.e. upload offset
|
// finishUploadIfComplete checks whether an upload is completed (i.e. upload offset
|
||||||
// matches upload size) and if so, it will call the data store's FinishUpload
|
// matches upload size) and if so, it will call the data store's FinishUpload
|
||||||
// function and send the necessary message on the CompleteUpload channel.
|
// function and send the necessary message on the CompleteUpload channel.
|
||||||
func (handler *UnroutedHandler) finishUploadIfComplete(ctx context.Context, upload Upload, info FileInfo, r *http.Request) error {
|
func (handler *UnroutedHandler) finishUploadIfComplete(ctx context.Context, upload Upload, info FileInfo, r *http.Request, w http.ResponseWriter) error {
|
||||||
// If the upload is completed, ...
|
// If the upload is completed, ...
|
||||||
if !info.SizeIsDeferred && info.Offset == info.Size {
|
if !info.SizeIsDeferred && info.Offset == info.Size {
|
||||||
// ... allow custom mechanism to finish and cleanup the upload
|
// ... allow custom mechanism to finish and cleanup the upload
|
||||||
|
@ -690,9 +690,13 @@ func (handler *UnroutedHandler) finishUploadIfComplete(ctx context.Context, uplo
|
||||||
handler.Metrics.incUploadsFinished()
|
handler.Metrics.incUploadsFinished()
|
||||||
|
|
||||||
if handler.config.PreFinishResponseCallback != nil {
|
if handler.config.PreFinishResponseCallback != nil {
|
||||||
if err := handler.config.PreFinishResponseCallback(newHookEvent(info, r)); err != nil {
|
err, output := handler.config.PreFinishResponseCallback(newHookEvent(info, r))
|
||||||
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
if output != nil {
|
||||||
|
w.Header().Set("X-pre-finish-response", string(output))
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue