@@ -3,95 +3,25 @@ package cli
3
3
import (
4
4
"strings"
5
5
6
- "github.com/tus/tusd/v2/cmd/tusd/cli/hooks"
7
6
"github.com/tus/tusd/v2/pkg/handler"
7
+ "github.com/tus/tusd/v2/pkg/hooks"
8
+ "github.com/tus/tusd/v2/pkg/hooks/file"
9
+ "github.com/tus/tusd/v2/pkg/hooks/grpc"
10
+ "github.com/tus/tusd/v2/pkg/hooks/http"
11
+ "github.com/tus/tusd/v2/pkg/hooks/plugin"
8
12
)
9
13
10
- var hookHandler hooks.HookHandler = nil
11
-
12
- func hookTypeInSlice (a hooks.HookType , list []hooks.HookType ) bool {
13
- for _ , b := range list {
14
- if b == a {
15
- return true
16
- }
17
- }
18
- return false
19
- }
20
-
21
- func preCreateCallback (event handler.HookEvent ) (handler.HTTPResponse , handler.FileInfoChanges , error ) {
22
- ok , hookRes , err := invokeHookSync (hooks .HookPreCreate , event )
23
- if ! ok || err != nil {
24
- return handler.HTTPResponse {}, handler.FileInfoChanges {}, err
25
- }
26
-
27
- httpRes := hookRes .HTTPResponse
28
-
29
- // If the hook response includes the instruction to reject the upload, reuse the error code
30
- // and message from ErrUploadRejectedByServer, but also include custom HTTP response values.
31
- if hookRes .RejectUpload {
32
- err := handler .ErrUploadRejectedByServer
33
- err .HTTPResponse = err .HTTPResponse .MergeWith (httpRes )
34
-
35
- return handler.HTTPResponse {}, handler.FileInfoChanges {}, err
36
- }
37
-
38
- // Pass any changes regarding file info from the hook to the handler.
39
- changes := hookRes .ChangeFileInfo
40
- return httpRes , changes , nil
41
- }
42
-
43
- func preFinishCallback (event handler.HookEvent ) (handler.HTTPResponse , error ) {
44
- ok , hookRes , err := invokeHookSync (hooks .HookPreFinish , event )
45
- if ! ok || err != nil {
46
- return handler.HTTPResponse {}, err
47
- }
48
-
49
- httpRes := hookRes .HTTPResponse
50
- return httpRes , nil
51
- }
52
-
53
- func postReceiveCallback (event handler.HookEvent ) {
54
- ok , hookRes , _ := invokeHookSync (hooks .HookPostReceive , event )
55
- // invokeHookSync already logs the error, if any occurs. So by checking `ok`, we can ensure
56
- // that the hook finished successfully
57
- if ! ok {
58
- return
59
- }
60
-
61
- if hookRes .StopUpload {
62
- logEv (stdout , "HookStopUpload" , "id" , event .Upload .ID )
63
-
64
- // TODO: Control response for PATCH request
65
- event .Upload .StopUpload ()
66
- }
67
- }
68
-
69
- func SetupHookMetrics () {
70
- MetricsHookErrorsTotal .WithLabelValues (string (hooks .HookPostFinish )).Add (0 )
71
- MetricsHookErrorsTotal .WithLabelValues (string (hooks .HookPostTerminate )).Add (0 )
72
- MetricsHookErrorsTotal .WithLabelValues (string (hooks .HookPostReceive )).Add (0 )
73
- MetricsHookErrorsTotal .WithLabelValues (string (hooks .HookPostCreate )).Add (0 )
74
- MetricsHookErrorsTotal .WithLabelValues (string (hooks .HookPreCreate )).Add (0 )
75
- MetricsHookErrorsTotal .WithLabelValues (string (hooks .HookPreFinish )).Add (0 )
76
- MetricsHookInvocationsTotal .WithLabelValues (string (hooks .HookPostFinish )).Add (0 )
77
- MetricsHookInvocationsTotal .WithLabelValues (string (hooks .HookPostTerminate )).Add (0 )
78
- MetricsHookInvocationsTotal .WithLabelValues (string (hooks .HookPostReceive )).Add (0 )
79
- MetricsHookInvocationsTotal .WithLabelValues (string (hooks .HookPostCreate )).Add (0 )
80
- MetricsHookInvocationsTotal .WithLabelValues (string (hooks .HookPreCreate )).Add (0 )
81
- MetricsHookInvocationsTotal .WithLabelValues (string (hooks .HookPreFinish )).Add (0 )
82
- }
83
-
84
- func SetupPreHooks (config * handler.Config ) error {
14
+ func getHookHandler (config * handler.Config ) hooks.HookHandler {
85
15
if Flags .FileHooksDir != "" {
86
16
stdout .Printf ("Using '%s' for hooks" , Flags .FileHooksDir )
87
17
88
- hookHandler = & hooks .FileHook {
18
+ return & file .FileHook {
89
19
Directory : Flags .FileHooksDir ,
90
20
}
91
21
} else if Flags .HttpHooksEndpoint != "" {
92
22
stdout .Printf ("Using '%s' as the endpoint for hooks" , Flags .HttpHooksEndpoint )
93
23
94
- hookHandler = & hooks .HttpHook {
24
+ return & http .HttpHook {
95
25
Endpoint : Flags .HttpHooksEndpoint ,
96
26
MaxRetries : Flags .HttpHooksRetry ,
97
27
Backoff : Flags .HttpHooksBackoff ,
@@ -100,97 +30,18 @@ func SetupPreHooks(config *handler.Config) error {
100
30
} else if Flags .GrpcHooksEndpoint != "" {
101
31
stdout .Printf ("Using '%s' as the endpoint for gRPC hooks" , Flags .GrpcHooksEndpoint )
102
32
103
- hookHandler = & hooks .GrpcHook {
33
+ return & grpc .GrpcHook {
104
34
Endpoint : Flags .GrpcHooksEndpoint ,
105
35
MaxRetries : Flags .GrpcHooksRetry ,
106
36
Backoff : Flags .GrpcHooksBackoff ,
107
37
}
108
38
} else if Flags .PluginHookPath != "" {
109
39
stdout .Printf ("Using '%s' to load plugin for hooks" , Flags .PluginHookPath )
110
40
111
- hookHandler = & hooks .PluginHook {
41
+ return & plugin .PluginHook {
112
42
Path : Flags .PluginHookPath ,
113
43
}
114
44
} else {
115
45
return nil
116
46
}
117
-
118
- var enabledHooksString []string
119
- for _ , h := range Flags .EnabledHooks {
120
- enabledHooksString = append (enabledHooksString , string (h ))
121
- }
122
-
123
- stdout .Printf ("Enabled hook events: %s" , strings .Join (enabledHooksString , ", " ))
124
-
125
- if err := hookHandler .Setup (); err != nil {
126
- return err
127
- }
128
-
129
- config .PreUploadCreateCallback = preCreateCallback
130
- config .PreFinishResponseCallback = preFinishCallback
131
-
132
- return nil
133
- }
134
-
135
- func SetupPostHooks (handler * handler.Handler ) {
136
- go func () {
137
- for {
138
- select {
139
- case event := <- handler .CompleteUploads :
140
- invokeHookAsync (hooks .HookPostFinish , event )
141
- case event := <- handler .TerminatedUploads :
142
- invokeHookAsync (hooks .HookPostTerminate , event )
143
- case event := <- handler .CreatedUploads :
144
- invokeHookAsync (hooks .HookPostCreate , event )
145
- case event := <- handler .UploadProgress :
146
- go postReceiveCallback (event )
147
- }
148
- }
149
- }()
150
- }
151
-
152
- func invokeHookAsync (typ hooks.HookType , event handler.HookEvent ) {
153
- go func () {
154
- // Error handling is taken care by the function.
155
- _ , _ , _ = invokeHookSync (typ , event )
156
- }()
157
- }
158
-
159
- // invokeHookSync executes a hook of the given type with the given event data. If
160
- // the hook was not executed properly (e.g. an error occurred or not handler is installed),
161
- // `ok` will be false and `res` is not filled. `err` can contain the underlying error.
162
- // If `ok` is true, `res` contains the response as retrieved from the hook.
163
- // Therefore, a caller should always check `ok` and `err` before assuming that the
164
- // hook completed successfully.
165
- func invokeHookSync (typ hooks.HookType , event handler.HookEvent ) (ok bool , res hooks.HookResponse , err error ) {
166
- // Stop, if no hook handler is installed or this hook event is not enabled
167
- if hookHandler == nil || ! hookTypeInSlice (typ , Flags .EnabledHooks ) {
168
- return false , hooks.HookResponse {}, nil
169
- }
170
-
171
- MetricsHookInvocationsTotal .WithLabelValues (string (typ )).Add (1 )
172
-
173
- id := event .Upload .ID
174
-
175
- if Flags .VerboseOutput {
176
- logEv (stdout , "HookInvocationStart" , "type" , string (typ ), "id" , id )
177
- }
178
-
179
- res , err = hookHandler .InvokeHook (hooks.HookRequest {
180
- Type : typ ,
181
- Event : event ,
182
- })
183
- if err != nil {
184
- // If an error occurs during the hook execution, we log and track the error, but do not
185
- // return a hook response.
186
- logEv (stderr , "HookInvocationError" , "type" , string (typ ), "id" , id , "error" , err .Error ())
187
- MetricsHookErrorsTotal .WithLabelValues (string (typ )).Add (1 )
188
- return false , hooks.HookResponse {}, err
189
- }
190
-
191
- if Flags .VerboseOutput {
192
- logEv (stdout , "HookInvocationFinish" , "type" , string (typ ), "id" , id )
193
- }
194
-
195
- return true , res , nil
196
47
}
0 commit comments