Chromium Code Reviews| Index: logdog/common/types/url.go |
| diff --git a/logdog/common/types/url.go b/logdog/common/types/url.go |
| new file mode 100644 |
| index 0000000000000000000000000000000000000000..75135e31191409267ca05247c8bbeb5c4160adcc |
| --- /dev/null |
| +++ b/logdog/common/types/url.go |
| @@ -0,0 +1,80 @@ |
| +// Copyright 2017 The LUCI Authors. All rights reserved. |
| +// Use of this source code is governed under the Apache License, Version 2.0 |
| +// that can be found in the LICENSE file. |
| + |
| +package types |
| + |
| +import ( |
| + "net/url" |
| + "strings" |
| + |
| + "github.com/luci/luci-go/common/errors" |
| + "github.com/luci/luci-go/luci_config/common/cfgtypes" |
| +) |
| + |
| +const logDogURLScheme = "logdog" |
| + |
| +// Stream is a fully-qualified LogDog stream definition. |
| +type Stream struct { |
|
hinoka
2017/02/16 02:08:21
StreamAddr
dnj
2017/02/16 02:20:51
Done.
|
| + // Host is the LogDog host. |
| + Host string |
| + |
| + // Project is the LUCI project name that this log belongs to. |
| + Project cfgtypes.ProjectName |
| + |
| + // Path is the LogDog stream path. |
| + Path StreamPath |
| +} |
| + |
| +// URL returns a LogDog URL that represents this Stream. |
| +func (s *Stream) URL() *url.URL { |
| + return &url.URL{ |
| + Scheme: logDogURLScheme, |
| + Host: s.Host, |
| + Path: strings.Join([]string{"", string(s.Project), string(s.Path)}, "/"), |
| + } |
| +} |
| + |
| +// ParseURL parses a LogDog URL into a Stream. If the URL is malformed, or |
| +// if the host, project, or path is invalid, an error will be returned. |
| +// |
| +// A LogDog URL has the form: |
| +// logdog://<host>/<project>/<prefix>/+/<name> |
| +func ParseURL(v string) (*Stream, error) { |
| + u, err := url.Parse(v) |
| + if err != nil { |
| + return nil, errors.Annotate(err).Reason("failed to parse URL").Err() |
| + } |
| + |
| + // Validate Scheme. |
| + if u.Scheme != logDogURLScheme { |
| + return nil, errors.Reason("URL scheme %(scheme)q is not "+logDogURLScheme). |
| + D("scheme", u.Scheme). |
| + Err() |
| + } |
| + def := Stream{ |
| + Host: u.Host, |
| + } |
| + |
| + parts := strings.SplitN(u.Path, "/", 3) |
| + if len(parts) != 3 || len(parts[0]) != 0 { |
| + return nil, errors.Reason("URL path does not include both project and path components: %(path)s"). |
| + D("path", u.Path). |
| + Err() |
| + } |
| + |
| + def.Project, def.Path = cfgtypes.ProjectName(parts[1]), StreamPath(parts[2]) |
| + if err := def.Project.Validate(); err != nil { |
| + return nil, errors.Annotate(err).Reason("invalid project name: %(project)q"). |
| + D("project", def.Project). |
| + Err() |
| + } |
| + |
| + if err := def.Path.Validate(); err != nil { |
| + return nil, errors.Annotate(err).Reason("invalid stream path: %(path)q"). |
| + D("path", def.Path). |
| + Err() |
| + } |
| + |
| + return &def, nil |
| +} |