@@ -2,6 +2,7 @@ package internal
2
2
3
3
import (
4
4
"fmt"
5
+ "github.com/bmizerany/pat"
5
6
"github.com/docopt/docopt-go"
6
7
"github.com/jackhftang/tusc/internal/util"
7
8
"github.com/tus/tusd"
@@ -24,10 +25,12 @@ Usage:
24
25
tusc (server|s) --help
25
26
26
27
Options:
27
- -h --host HOST Host to bind HTTP server to [default: 0.0.0.0]
28
+ -u --url URL Url of HTTP server [default: http://localhost:1080]
29
+ -b --bind ADDR Address to bind HTTP server to [default: 0.0.0.0]
28
30
-p --port PORT Port to bind HTTP server to [default: 1080]
29
31
-d --dir PATH Directory to store uploads in [default: ./data]
30
- --base-path PATH Basepath of the HTTP server [default: /files/]
32
+ --listing-endpoint PATH Http path for flies listing [default: /]
33
+ --files-endpoint PATH Http path for files [default: /files/]
31
34
--unix-sock PATH If set will listen to a UNIX socket at this location instead of a TCP socket
32
35
--max-size SIZE Maximum size of a single upload in bytes [default: 0]
33
36
--store-size BYTE Size of space allowed for storage [default: 0]
@@ -36,16 +39,17 @@ Options:
36
39
`
37
40
38
41
type ServerConf struct {
39
- httpHost string
40
- httpPort string
41
- httpSock string
42
- maxSize int64
43
- uploadDir string
44
- storeSize int64
45
- listingEndpoint string
46
- uploadEndpoint string
47
- timeout int64
48
- isBehindProxy bool
42
+ Url string `docopt:"--url"`
43
+ BindAddr string `docopt:"--bind"`
44
+ Port string `docopt:"--port"`
45
+ HttpSock string `docopt:"--unix-sock"`
46
+ MaxSize int64 `docopt:"--max-size"`
47
+ UploadDir string `docopt:"--dir"`
48
+ StoreSize int64 `docopt:"--store-size"`
49
+ ListingEndpoint string `docopt:"--listing-endpoint"`
50
+ FilesEndpoint string `docopt:"--files-endpoint"`
51
+ Timeout int64 `docopt:"--timeout"`
52
+ IsBehindProxy bool `docopt:"--behind-proxy"`
49
53
}
50
54
51
55
var stdout = log .New (os .Stdout , "[tusd] " , log .Ldate | log .Ltime )
@@ -58,61 +62,62 @@ func logEv(logOutput *log.Logger, eventName string, details ...string) {
58
62
func Server () {
59
63
var conf ServerConf
60
64
arguments , _ := docopt .ParseDoc (serverUsage )
61
- conf .httpHost , _ = arguments .String ("--host" )
62
- conf .httpPort , _ = arguments .String ("--port" )
63
- conf .httpSock , _ = arguments .String ("--unix-sock" )
64
- conf .maxSize = util .GetInt64 (arguments , "--max-size" )
65
- conf .uploadDir , _ = arguments .String ("--dir" )
66
- conf .storeSize = util .GetInt64 (arguments , "--store-size" )
67
- conf .listingEndpoint = "/"
68
- conf .uploadEndpoint , _ = arguments .String ("--base-path" )
69
- conf .timeout = util .GetInt64 (arguments , "--timeout" )
70
- conf .isBehindProxy , _ = arguments .Bool ("--behind-proxy" )
65
+ //arguments.Bind(&conf) // todo: bug
66
+ conf .Url , _ = arguments .String ("--url" )
67
+ conf .BindAddr , _ = arguments .String ("--bind" )
68
+ conf .Port , _ = arguments .String ("--port" )
69
+ conf .HttpSock , _ = arguments .String ("--unix-sock" )
70
+ conf .MaxSize = util .GetInt64 (arguments , "--max-size" )
71
+ conf .UploadDir , _ = arguments .String ("--dir" )
72
+ conf .StoreSize = util .GetInt64 (arguments , "--store-size" )
73
+ conf .ListingEndpoint , _ = arguments .String ("--listing-endpoint" )
74
+ conf .FilesEndpoint , _ = arguments .String ("--files-endpoint" )
75
+ conf .Timeout = util .GetInt64 (arguments , "--timeout" )
76
+ conf .IsBehindProxy , _ = arguments .Bool ("--behind-proxy" )
77
+ fmt .Println (conf )
71
78
72
79
storeCompoesr := tusd .NewStoreComposer ()
73
80
74
- stdout .Printf ("Using '%s' as directory storage.\n " , conf .uploadDir )
75
- if err := os .MkdirAll (conf .uploadDir , os .FileMode (0774 )); err != nil {
81
+ stdout .Printf ("Using '%s' as directory storage.\n " , conf .UploadDir )
82
+ if err := os .MkdirAll (conf .UploadDir , os .FileMode (0774 )); err != nil {
76
83
stderr .Fatalf ("Unable to ensure directory exists: %s" , err )
77
84
}
78
- store := filestore .New (conf .uploadDir )
85
+ store := filestore .New (conf .UploadDir )
79
86
store .UseIn (storeCompoesr )
80
87
81
- if conf .storeSize > 0 {
82
- limitedstore .New (conf .storeSize , storeCompoesr .Core , storeCompoesr .Terminater ).UseIn (storeCompoesr )
83
- stdout .Printf ("Using %.2fMB as storage size.\n " , float64 (conf .storeSize )/ 1024 / 1024 )
88
+ if conf .StoreSize > 0 {
89
+ limitedstore .New (conf .StoreSize , storeCompoesr .Core , storeCompoesr .Terminater ).UseIn (storeCompoesr )
90
+ stdout .Printf ("Using %.2fMB as storage size.\n " , float64 (conf .StoreSize )/ 1024 / 1024 )
84
91
85
92
// We need to ensure that a single upload can fit into the storage size
86
- if conf .maxSize > conf .storeSize || conf .maxSize == 0 {
87
- conf .maxSize = conf .storeSize
93
+ if conf .MaxSize > conf .StoreSize || conf .MaxSize == 0 {
94
+ conf .MaxSize = conf .StoreSize
88
95
}
89
96
}
90
97
91
- stdout .Printf ("Using %.2fMB as maximum size.\n " , float64 (conf .maxSize )/ 1024 / 1024 )
92
-
93
- // Serve
98
+ stdout .Printf ("Using %.2fMB as maximum size.\n " , float64 (conf .MaxSize )/ 1024 / 1024 )
94
99
95
100
// Address
96
101
address := ""
97
- if conf .httpSock != "" {
98
- address = conf .httpSock
102
+ if conf .HttpSock != "" {
103
+ address = conf .HttpSock
99
104
stdout .Printf ("Using %s as socket to listen.\n " , address )
100
105
} else {
101
- address = conf .httpHost + ":" + conf .httpPort
106
+ address = conf .BindAddr + ":" + conf .Port
102
107
stdout .Printf ("Using %s as address to listen.\n " , address )
103
108
}
104
109
105
110
// Base path
106
- stdout .Printf ("Using %s as the base path.\n " , conf .uploadEndpoint )
111
+ stdout .Printf ("Using %s as the base path.\n " , conf .FilesEndpoint )
107
112
108
113
// show capabilities
109
114
stdout .Printf (storeCompoesr .Capabilities ())
110
115
111
116
// tus handler
112
117
handler , err := tusd .NewHandler (tusd.Config {
113
- MaxSize : conf .maxSize ,
114
- BasePath : conf .uploadEndpoint ,
115
- RespectForwardedHeaders : conf .isBehindProxy ,
118
+ MaxSize : conf .MaxSize ,
119
+ BasePath : conf .FilesEndpoint ,
120
+ RespectForwardedHeaders : conf .IsBehindProxy ,
116
121
StoreComposer : storeCompoesr ,
117
122
NotifyCompleteUploads : false ,
118
123
NotifyTerminatedUploads : false ,
@@ -123,31 +128,34 @@ func Server() {
123
128
stderr .Fatalf ("Unable to create handler: %s" , err )
124
129
}
125
130
126
- http .Handle (conf .uploadEndpoint , http .StripPrefix (conf .uploadEndpoint , handler ))
127
- if conf .listingEndpoint != conf .uploadEndpoint {
128
- http .Handle (conf .listingEndpoint , http .StripPrefix (conf .listingEndpoint , homepage (store )))
131
+ if conf .ListingEndpoint != conf .FilesEndpoint {
132
+ mux := pat .New ()
133
+ mux .Get ("/" , listingHandler (conf , store ))
134
+ http .Handle (conf .ListingEndpoint , mux )
129
135
}
136
+ http .Handle (conf .FilesEndpoint , http .StripPrefix (conf .FilesEndpoint , handler ))
137
+
130
138
131
139
var listener net.Listener
132
- timeoutDuration := time .Duration (conf .timeout ) * time .Millisecond
140
+ timeoutDuration := time .Duration (conf .Timeout ) * time .Millisecond
133
141
134
- if conf .httpSock != "" {
142
+ if conf .HttpSock != "" {
135
143
if listener , err = util .NewUnixListener (address , timeoutDuration , timeoutDuration ); err != nil {
136
144
stderr .Fatalf ("Unable to create listener: %s" , err )
137
145
}
138
- stdout .Printf ("You can now upload files to: http://%s%s" , address , conf .uploadEndpoint )
139
146
} else {
140
147
if listener , err = util .NewListener (address , timeoutDuration , timeoutDuration ); err != nil {
141
148
stderr .Fatalf ("Unable to create listener: %s" , err )
142
149
}
150
+ stdout .Printf ("You can now upload files to: http://%s%s" , address , conf .FilesEndpoint )
143
151
}
144
152
145
153
if err = http .Serve (listener , nil ); err != nil {
146
154
stderr .Fatalf ("Unable to serve: %s" , err )
147
155
}
148
156
}
149
157
150
- func homepage ( store filestore.FileStore ) http.HandlerFunc {
158
+ func listingHandler ( conf ServerConf , store filestore.FileStore ) http.HandlerFunc {
151
159
t , err := template .New ("foo" ).Parse (`{{define "listing"}}<html><head><title>File Listing</title><style>
152
160
* {
153
161
font-family: monospace;
178
186
padding: 0;
179
187
}
180
188
</style></head><body><ul>
181
- {{ range . }}<li><a href="http://127.0.0.1:1080/files/ {{ .ID }}">{{ index .MetaData "filename" }}</a></li>{{ end }}
189
+ {{ range .Infos }}<li><a href="{{ $.Conf.Url }}{{ $.Conf.FilesEndpoint }} {{ .ID }}">{{ index .MetaData "filename" }}</a></li>{{ end }}
182
190
</ul>
183
191
</body>
184
192
</html>{{end}}` )
189
197
return http .HandlerFunc (func (w http.ResponseWriter , r * http.Request ) {
190
198
var err error
191
199
var fileInfos []os.FileInfo
200
+
201
+ // todo: here read once, calling GetInfo read another once
192
202
if fileInfos , err = ioutil .ReadDir (store .Path ); err != nil {
193
203
http .Error (w , "" , 500 )
194
204
return
@@ -217,7 +227,11 @@ li {
217
227
sort .Slice (infos , func (i , j int ) bool {
218
228
return infos [i ].MetaData ["filename" ] < infos [j ].MetaData ["filename" ]
219
229
})
220
- if err = t .ExecuteTemplate (w , "listing" , infos ); err != nil {
230
+ data := struct {
231
+ Infos []tusd.FileInfo
232
+ Conf ServerConf
233
+ }{infos , conf ,}
234
+ if err = t .ExecuteTemplate (w , "listing" , data ); err != nil {
221
235
//stderr.Fatalf("Unable to render template: %s", err)
222
236
http .Error (w , "" , 500 )
223
237
return
0 commit comments