Repository: qpid-proton
Updated Branches:
  refs/heads/master ce79d1ca2 -> 4bb26814c


PROTON-1303: Replace go binding URL parser with version that doesn't use the 
Proton URL parser


Project: http://git-wip-us.apache.org/repos/asf/qpid-proton/repo
Commit: http://git-wip-us.apache.org/repos/asf/qpid-proton/commit/26e7ff80
Tree: http://git-wip-us.apache.org/repos/asf/qpid-proton/tree/26e7ff80
Diff: http://git-wip-us.apache.org/repos/asf/qpid-proton/diff/26e7ff80

Branch: refs/heads/master
Commit: 26e7ff804783ff34b2d8e86f737f048b3aa0778c
Parents: 4487520
Author: Andrew Stitcher <astitc...@apache.org>
Authored: Fri Sep 9 13:59:02 2016 -0400
Committer: Andrew Stitcher <astitc...@apache.org>
Committed: Thu Sep 15 14:49:39 2016 -0400

----------------------------------------------------------------------
 .../bindings/go/src/qpid.apache.org/amqp/url.go | 118 ++++++++++---------
 .../go/src/qpid.apache.org/amqp/url_test.go     |  12 +-
 2 files changed, 72 insertions(+), 58 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/26e7ff80/proton-c/bindings/go/src/qpid.apache.org/amqp/url.go
----------------------------------------------------------------------
diff --git a/proton-c/bindings/go/src/qpid.apache.org/amqp/url.go 
b/proton-c/bindings/go/src/qpid.apache.org/amqp/url.go
index 70545d2..d507c62 100644
--- a/proton-c/bindings/go/src/qpid.apache.org/amqp/url.go
+++ b/proton-c/bindings/go/src/qpid.apache.org/amqp/url.go
@@ -19,78 +19,86 @@ under the License.
 
 package amqp
 
-/*
-#include <stdlib.h>
-#include <string.h>
-#include <proton/url.h>
-
-// Helper function for setting URL fields.
-typedef void (*setter_fn)(pn_url_t* url, const char* value);
-inline void    set(pn_url_t *url, setter_fn s, const char* value) {
-  s(url, value);
-}
-*/
-import "C"
-
 import (
-       "fmt"
+       "errors"
        "net"
        "net/url"
-       "unsafe"
+       "strings"
 )
 
 const (
        amqp  string = "amqp"
        amqps        = "amqps"
+       defaulthost  = "localhost"
 )
 
-// ParseUrl parses an AMQP URL string and returns a net/url.Url.
-//
-// It is more forgiving than net/url.Parse and allows most of the parts of the
-// URL to be missing, assuming AMQP defaults.
-//
-func ParseURL(s string) (u *url.URL, err error) {
-       cstr := C.CString(s)
-       defer C.free(unsafe.Pointer(cstr))
-       pnUrl := C.pn_url_parse(cstr)
-       if pnUrl == nil {
-               return nil, fmt.Errorf("bad URL %#v", s)
+// The way this is used it can only get a hostport already validated by
+// the URL parser, so this means we can skip some error checks
+func splitHostPort(hostport string) (string, string, error) {
+       if hostport == "" {
+               return "", "", nil
        }
-       defer C.pn_url_free(pnUrl)
-
-       scheme := C.GoString(C.pn_url_get_scheme(pnUrl))
-       username := C.GoString(C.pn_url_get_username(pnUrl))
-       password := C.GoString(C.pn_url_get_password(pnUrl))
-       host := C.GoString(C.pn_url_get_host(pnUrl))
-       port := C.GoString(C.pn_url_get_port(pnUrl))
-       path := C.GoString(C.pn_url_get_path(pnUrl))
+       if hostport[0] == '[' {
+               // There must be a matching ']' as already validated
+               if l := strings.LastIndexByte(hostport, ']'); len(hostport) == 
l+1 {
+                       // trim off '[' and ']'
+                       return hostport[1:l], "", nil
+               }
+       } else if strings.IndexByte(hostport, ':') < 0 {
+               return hostport, "", nil
+       }
+       return net.SplitHostPort(hostport)
+}
 
+func UpdateURL(in *url.URL) (err error) {
+       // Detect form without "amqp://" and stick it on front
+       // to make it match the usual proton defaults
+       u := new (url.URL)
+       *u = *in
+       if (u.Scheme != "" && u.Opaque != "") ||
+          (u.Scheme == "" && u.Host == "") {
+               input := u.String()
+               input = "amqp://" + input
+               u, err = url.Parse(input)
+               if err != nil {
+                       return
+               }
+       }
+       // If Scheme is still "" then default to amqp
+       if u.Scheme == "" {
+               u.Scheme = amqp
+       }
+       // Error if the scheme is not an amqp scheme
+       if u.Scheme != amqp && u.Scheme != amqps {
+               return errors.New("invalid amqp scheme")
+       }
+       // Decompose Host into host and port
+       host, port, err := splitHostPort(u.Host)
        if err != nil {
-               return nil, fmt.Errorf("bad URL %#v: %s", s, err)
+               return
        }
-       if scheme == "" {
-               scheme = amqp
+       if host == "" {
+               host = defaulthost
        }
        if port == "" {
-               if scheme == amqps {
-                       port = amqps
-               } else {
-                       port = amqp
-               }
-       }
-       var user *url.Userinfo
-       if password != "" {
-               user = url.UserPassword(username, password)
-       } else if username != "" {
-               user = url.User(username)
+               port = u.Scheme
        }
+       u.Host = net.JoinHostPort(host, port)
+       *in = *u
+       return nil
+}
 
-       u = &url.URL{
-               Scheme: scheme,
-               User:   user,
-               Host:   net.JoinHostPort(host, port),
-               Path:   path,
+// ParseUrl parses an AMQP URL string and returns a net/url.Url.
+//
+// It is more forgiving than net/url.Parse and allows most of the parts of the
+// URL to be missing, assuming AMQP defaults.
+//
+func ParseURL(s string) (u *url.URL, err error) {
+       if u, err = url.Parse(s); err != nil {
+               return
        }
-
-       return u, nil
+       if err = UpdateURL(u); err != nil {
+               u = nil
+       }
+       return u, err
 }

http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/26e7ff80/proton-c/bindings/go/src/qpid.apache.org/amqp/url_test.go
----------------------------------------------------------------------
diff --git a/proton-c/bindings/go/src/qpid.apache.org/amqp/url_test.go 
b/proton-c/bindings/go/src/qpid.apache.org/amqp/url_test.go
index 99b656d..29edb98 100644
--- a/proton-c/bindings/go/src/qpid.apache.org/amqp/url_test.go
+++ b/proton-c/bindings/go/src/qpid.apache.org/amqp/url_test.go
@@ -28,10 +28,13 @@ func ExampleParseURL() {
                "amqp://username:password@host:1234/path",
                "host:1234",
                "host",
-               ":1234",
                "host/path",
                "amqps://host",
+               "/path",
+               "[::1]",
                "",
+               ":1234",
+               "[::1",
        } {
                u, err := ParseURL(s)
                if err != nil {
@@ -44,8 +47,11 @@ func ExampleParseURL() {
        // amqp://username:password@host:1234/path
        // amqp://host:1234
        // amqp://host:amqp
-       // amqp://:1234
        // amqp://host:amqp/path
        // amqps://host:amqps
-       // bad URL ""
+       // amqp://localhost:amqp/path
+       // amqp://[::1]:amqp
+       // amqp://localhost:amqp
+       // parse :1234: missing protocol scheme
+       // parse amqp://[::1: missing ']' in host
 }


---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscr...@qpid.apache.org
For additional commands, e-mail: commits-h...@qpid.apache.org

Reply via email to