Skip to content

Commit 6f62f42

Browse files
committed
webdav: implement parseTimeout.
Change-Id: Ieb3d550d06adc7457ed6870b0dd5fbbfede7c488 Reviewed-on: https://go-review.googlesource.com/3074 Reviewed-by: Dave Cheney <dave@cheney.net>
1 parent d46df1a commit 6f62f42

File tree

3 files changed

+128
-5
lines changed

3 files changed

+128
-5
lines changed

webdav/lock.go

+30
Original file line numberDiff line numberDiff line change
@@ -287,3 +287,33 @@ type memLSNode struct {
287287
// held is whether this node's lock is actively held by a Confirm call.
288288
held bool
289289
}
290+
291+
const infiniteTimeout = -1
292+
293+
// parseTimeout parses the Timeout HTTP header, as per section 10.7. If s is
294+
// empty, an infiniteTimeout is returned.
295+
func parseTimeout(s string) (time.Duration, error) {
296+
if s == "" {
297+
return infiniteTimeout, nil
298+
}
299+
if i := strings.IndexByte(s, ','); i >= 0 {
300+
s = s[:i]
301+
}
302+
s = strings.TrimSpace(s)
303+
if s == "Infinite" {
304+
return infiniteTimeout, nil
305+
}
306+
const pre = "Second-"
307+
if !strings.HasPrefix(s, pre) {
308+
return 0, errInvalidTimeout
309+
}
310+
s = s[len(pre):]
311+
if s == "" || s[0] < '0' || '9' < s[0] {
312+
return 0, errInvalidTimeout
313+
}
314+
n, err := strconv.ParseInt(s, 10, 64)
315+
if err != nil || 1<<32-1 < n {
316+
return 0, errInvalidTimeout
317+
}
318+
return time.Duration(n) * time.Second, nil
319+
}

webdav/lock_test.go

+97
Original file line numberDiff line numberDiff line change
@@ -251,3 +251,100 @@ func (m *memLS) consistent() error {
251251
}
252252
return nil
253253
}
254+
255+
func TestParseTimeout(t *testing.T) {
256+
testCases := []struct {
257+
s string
258+
want time.Duration
259+
wantErr error
260+
}{{
261+
"",
262+
infiniteTimeout,
263+
nil,
264+
}, {
265+
"Infinite",
266+
infiniteTimeout,
267+
nil,
268+
}, {
269+
"Infinitesimal",
270+
0,
271+
errInvalidTimeout,
272+
}, {
273+
"infinite",
274+
0,
275+
errInvalidTimeout,
276+
}, {
277+
"Second-0",
278+
0 * time.Second,
279+
nil,
280+
}, {
281+
"Second-123",
282+
123 * time.Second,
283+
nil,
284+
}, {
285+
" Second-456 ",
286+
456 * time.Second,
287+
nil,
288+
}, {
289+
"Second-4100000000",
290+
4100000000 * time.Second,
291+
nil,
292+
}, {
293+
"junk",
294+
0,
295+
errInvalidTimeout,
296+
}, {
297+
"Second-",
298+
0,
299+
errInvalidTimeout,
300+
}, {
301+
"Second--1",
302+
0,
303+
errInvalidTimeout,
304+
}, {
305+
"Second--123",
306+
0,
307+
errInvalidTimeout,
308+
}, {
309+
"Second-+123",
310+
0,
311+
errInvalidTimeout,
312+
}, {
313+
"Second-0x123",
314+
0,
315+
errInvalidTimeout,
316+
}, {
317+
"second-123",
318+
0,
319+
errInvalidTimeout,
320+
}, {
321+
"Second-4294967295",
322+
4294967295 * time.Second,
323+
nil,
324+
}, {
325+
// Section 10.7 says that "The timeout value for TimeType "Second"
326+
// must not be greater than 2^32-1."
327+
"Second-4294967296",
328+
0,
329+
errInvalidTimeout,
330+
}, {
331+
// This test case comes from section 9.10.9 of the spec. It says,
332+
//
333+
// "In this request, the client has specified that it desires an
334+
// infinite-length lock, if available, otherwise a timeout of 4.1
335+
// billion seconds, if available."
336+
//
337+
// The Go WebDAV package always supports infinite length locks,
338+
// and ignores the fallback after the comma.
339+
"Infinite, Second-4100000000",
340+
infiniteTimeout,
341+
nil,
342+
}}
343+
344+
for _, tc := range testCases {
345+
got, gotErr := parseTimeout(tc.s)
346+
if got != tc.want || gotErr != tc.wantErr {
347+
t.Errorf("parsing %q:\ngot %v, %v\nwant %v, %v", tc.s, got, gotErr, tc.want, tc.wantErr)
348+
}
349+
}
350+
}

webdav/webdav.go

+1-5
Original file line numberDiff line numberDiff line change
@@ -323,11 +323,6 @@ func parseDepth(s string) int {
323323
return invalidDepth
324324
}
325325

326-
func parseTimeout(s string) (time.Duration, error) {
327-
// TODO: implement.
328-
return 1 * time.Second, nil
329-
}
330-
331326
// http://www.webdav.org/specs/rfc4918.html#status.code.extensions.to.http11
332327
const (
333328
StatusMulti = 207
@@ -360,6 +355,7 @@ var (
360355
errInvalidLockInfo = errors.New("webdav: invalid lock info")
361356
errInvalidLockToken = errors.New("webdav: invalid lock token")
362357
errInvalidPropfind = errors.New("webdav: invalid propfind")
358+
errInvalidTimeout = errors.New("webdav: invalid timeout")
363359
errNoFileSystem = errors.New("webdav: no file system")
364360
errNoLockSystem = errors.New("webdav: no lock system")
365361
errNotADirectory = errors.New("webdav: not a directory")

0 commit comments

Comments
 (0)