Repository: nats-io/nats-server
Pull request #3163 (2022-06-02 16:27:05)

export the correct subject transformer subject
While the TransformSubject function was doing the right
thing it did not match first and so would panic for subjects
that do not match the mapping.

The map function does the right thing so this is a more
appropriate function to export.

This undoes the exporting of unsafe TransformSubject and
exports the safer Match instead.

Signed-off-by: R.I.Pienaar <rip@devco.net>

/cc @nats-io/core



Patch:
diff --git a/server/accounts.go b/server/accounts.go
index 016d2042..1e415fd7 100644
--- a/server/accounts.go
+++ b/server/accounts.go
@@ -4229,7 +4229,7 @@ func placeHolderIndex(token string) ([]int, int32, error) {
 //
 // This API is not part of the public API and not subject to SemVer protections
 type SubjectTransformer interface {
-	TransformSubject(string) (string, error)
+	Match(string) (string, error)
 }
 
 // NewSubjectTransformer creates a new SubjectTransformer
@@ -4294,10 +4294,13 @@ func newTransform(src, dest string) (*transform, error) {
 	return &transform{src: src, dest: dest, dtoks: dtokens, stoks: stokens, dtpi: dtpi, dtpinp: dtpinb}, nil
 }
 
-// match will take a literal published subject that is associated with a client and will match and transform
+// Match will take a literal published subject that is associated with a client and will match and transform
 // the subject if possible.
-// TODO(dlc) - We could add in client here to allow for things like foo -> foo.$ACCOUNT
-func (tr *transform) match(subject string) (string, error) {
+//
+// This API is not part of the public API and not subject to SemVer protections
+func (tr *transform) Match(subject string) (string, error) {
+	// TODO(dlc) - We could add in client here to allow for things like foo -> foo.$ACCOUNT
+
 	// Tokenize the subject. This should always be a literal subject.
 	tsa := [32]string{}
 	tts := tsa[:0]
@@ -4319,10 +4322,8 @@ func (tr *transform) match(subject string) (string, error) {
 	return _EMPTY_, ErrNoTransforms
 }
 
-// TransformSubject do not need to match, just transform.
-//
-// This API is not part of the public API and not subject to SemVer protections
-func (tr *transform) TransformSubject(subject string) (string, error) {
+// transformSubject do not need to match, just transform.
+func (tr *transform) transformSubject(subject string) (string, error) {
 	// Tokenize the subject.
 	tsa := [32]string{}
 	tts := tsa[:0]
diff --git a/server/client.go b/server/client.go
index 8fb78287..d7a8da09 100644
--- a/server/client.go
+++ b/server/client.go
@@ -2662,7 +2662,7 @@ func (c *client) addShadowSub(sub *subscription, ime *ime) (*subscription, error
 		if ime.overlapSubj != _EMPTY_ {
 			s = ime.overlapSubj
 		}
-		subj, err := im.rtr.TransformSubject(s)
+		subj, err := im.rtr.transformSubject(s)
 		if err != nil {
 			return nil, err
 		}
@@ -2943,7 +2943,7 @@ func (c *client) msgHeaderForRouteOrLeaf(subj, reply []byte, rt *routeTarget, ac
 		// Remap subject if its a shadow subscription, treat like a normal client.
 		if rt.sub.im != nil {
 			if rt.sub.im.tr != nil {
-				to, _ := rt.sub.im.tr.TransformSubject(string(subj))
+				to, _ := rt.sub.im.tr.transformSubject(string(subj))
 				subj = []byte(to)
 			} else if !rt.sub.im.usePub {
 				subj = []byte(rt.sub.im.to)
@@ -3894,7 +3894,7 @@ func (c *client) processServiceImport(si *serviceImport, acc *Account, msg []byt
 
 	if si.tr != nil {
 		// FIXME(dlc) - This could be slow, may want to look at adding cache to bare transforms?
-		to, _ = si.tr.TransformSubject(subject)
+		to, _ = si.tr.transformSubject(subject)
 	} else if si.usePub {
 		to = subject
 	}
@@ -4138,7 +4138,7 @@ func (c *client) processMsgResults(acc *Account, r *SublistResult, msg, deliver,
 				continue
 			}
 			if sub.im.tr != nil {
-				to, _ := sub.im.tr.TransformSubject(string(subject))
+				to, _ := sub.im.tr.transformSubject(string(subject))
 				dsubj = append(_dsubj[:0], to...)
 			} else if sub.im.usePub {
 				dsubj = append(_dsubj[:0], subj...)
@@ -4279,7 +4279,7 @@ func (c *client) processMsgResults(acc *Account, r *SublistResult, msg, deliver,
 					continue
 				}
 				if sub.im.tr != nil {
-					to, _ := sub.im.tr.TransformSubject(string(subject))
+					to, _ := sub.im.tr.transformSubject(string(subject))
 					dsubj = append(_dsubj[:0], to...)
 				} else if sub.im.usePub {
 					dsubj = append(_dsubj[:0], subj...)
diff --git a/server/stream.go b/server/stream.go
index 1352c7c3..d714caa6 100644
--- a/server/stream.go
+++ b/server/stream.go
@@ -3486,7 +3486,7 @@ func (mset *stream) processJetStreamMsg(subject, reply string, hdr, msg []byte,
 	var tlseq uint64
 	var thdrsOnly bool
 	if mset.tr != nil {
-		tsubj, _ = mset.tr.TransformSubject(subject)
+		tsubj, _ = mset.tr.transformSubject(subject)
 		if mset.cfg.RePublish != nil {
 			thdrsOnly = mset.cfg.RePublish.HeadersOnly
 		}


Test patch:
diff --git a/server/accounts_test.go b/server/accounts_test.go
index 35fbdcc2..eaff2c56 100644
--- a/server/accounts_test.go
+++ b/server/accounts_test.go
@@ -3296,7 +3296,7 @@ func TestSubjectTransforms(t *testing.T) {
 	shouldMatch := func(src, dest, sample, expected string) {
 		t.Helper()
 		tr := shouldBeOK(src, dest)
-		s, err := tr.match(sample)
+		s, err := tr.Match(sample)
 		if err != nil {
 			t.Fatalf("Got an error %v when expecting a match for %q to %q", err, sample, expected)
 		}