Skip to content

Commit

Permalink
Merge pull request #246 from yamamoto-febc/fix/grpcutil
Browse files Browse the repository at this point in the history
Improved address parsing
  • Loading branch information
yamamoto-febc committed Dec 9, 2021
2 parents c28d9c2 + 827afc0 commit 5491a3d
Show file tree
Hide file tree
Showing 2 changed files with 22 additions and 65 deletions.
14 changes: 6 additions & 8 deletions grpcutil/server.go
Original file line number Diff line number Diff line change
Expand Up @@ -32,23 +32,21 @@ type ListenerOption struct {

// Server 指定のオプションでリッスン構成をした後でリッスンし、*grpc.Serverとクリーンアップ用のfuncを返す
func Server(opt *ListenerOption) (*grpc.Server, net.Listener, func(), error) {
target := ParseTarget(opt.Address, false)

schema := "tcp"
if target.Scheme == "unix" || target.Scheme == "unix-abstract" { // nolint:staticcheck
schema = "unix"
schema, endpoint, err := parseTarget(opt.Address)
if err != nil {
return nil, nil, nil, fmt.Errorf("parseTarget failed: %s", err)
}

listener, err := net.Listen(schema, target.Endpoint) // nolint:staticcheck
listener, err := net.Listen(schema, endpoint)
if err != nil {
return nil, nil, nil, fmt.Errorf("net.Listen failed: %s", err)
}

cleanup := func() {
listener.Close() // nolint
if schema == "unix" {
if _, err := os.Stat(target.Endpoint); err == nil { // nolint:staticcheck
if err := os.RemoveAll(target.Endpoint); err != nil { // nolint:staticcheck
if _, err := os.Stat(endpoint); err == nil {
if err := os.RemoveAll(endpoint); err != nil {
log.Printf("cleanup failed: %s", err) // nolint
}
}
Expand Down
73 changes: 16 additions & 57 deletions grpcutil/target.go
Original file line number Diff line number Diff line change
Expand Up @@ -24,69 +24,28 @@
package grpcutil

import (
"net/url"
"strings"

"google.golang.org/grpc/resolver"
)

// split2 returns the values from strings.SplitN(s, sep, 2).
// If sep is not found, it returns ("", "", false) instead.
func split2(s, sep string) (string, string, bool) {
spl := strings.SplitN(s, sep, 2)
if len(spl) < 2 {
return "", "", false
func parseTarget(target string) (string, string, error) {
if !strings.HasPrefix(target, "unix:") && !strings.HasPrefix(target, "unix-abstract:") {
target = "tcp:" + target
}
return spl[0], spl[1], true
}

// ParseTarget splits target into a resolver.Target struct containing scheme,
// authority and endpoint. skipUnixColonParsing indicates that the parse should
// not parse "unix:[path]" cases. This should be true in cases where a custom
// dialer is present, to prevent a behavior change.
//
// If target is not a valid scheme://authority/endpoint as specified in
// https://github.com/grpc/grpc/blob/master/doc/naming.md,
// it returns {Endpoint: target}.
func ParseTarget(target string, skipUnixColonParsing bool) (ret resolver.Target) {
var ok bool
if strings.HasPrefix(target, "unix-abstract:") {
if strings.HasPrefix(target, "unix-abstract://") {
// Maybe, with Authority specified, try to parse it
var remain string
ret.Scheme, remain, _ = split2(target, "://") // nolint:staticcheck
ret.Authority, ret.Endpoint, ok = split2(remain, "/") // nolint:staticcheck
if !ok {
// No Authority, add the "//" back
ret.Endpoint = "//" + remain // nolint:staticcheck
} else {
// Found Authority, add the "/" back
ret.Endpoint = "/" + ret.Endpoint // nolint:staticcheck
}
} else {
// Without Authority specified, split target on ":"
ret.Scheme, ret.Endpoint, _ = split2(target, ":") // nolint:staticcheck
}
return ret
}
ret.Scheme, ret.Endpoint, ok = split2(target, "://") // nolint:staticcheck
if !ok {
if strings.HasPrefix(target, "unix:") && !skipUnixColonParsing {
// Handle the "unix:[local/path]" and "unix:[/absolute/path]" cases,
// because splitting on :// only handles the
// "unix://[/absolute/path]" case. Only handle if the dialer is nil,
// to avoid a behavior change with custom dialers.
return resolver.Target{Scheme: "unix", Endpoint: target[len("unix:"):]} // nolint:staticcheck
}
return resolver.Target{Endpoint: target} // nolint:staticcheck
u, err := url.Parse(target)
if err != nil {
return "", "", err
}
ret.Authority, ret.Endpoint, ok = split2(ret.Endpoint, "/") // nolint:staticcheck
if !ok {
return resolver.Target{Endpoint: target} // nolint:staticcheck

schema := "tcp"
if u.Scheme == "unix" || u.Scheme == "unix-abstract" {
schema = "unix"
}
if ret.Scheme == "unix" { // nolint:staticcheck
// Add the "/" back in the unix case, so the unix resolver receives the
// actual endpoint in the "unix://[/absolute/path]" case.
ret.Endpoint = "/" + ret.Endpoint // nolint:staticcheck

endpoint := u.Path
if endpoint == "" {
endpoint = u.Opaque
}
return ret
return schema, endpoint, nil
}

0 comments on commit 5491a3d

Please sign in to comment.