You are viewing a plain text version of this content. The canonical link for it is here.
Posted to notifications@dubbo.apache.org by "DMwangnima (via GitHub)" <gi...@apache.org> on 2024/04/14 03:00:57 UTC

Re: [PR] fix: Server return with Attachment [dubbo-go]

DMwangnima commented on code in PR #2648:
URL: https://github.com/apache/dubbo-go/pull/2648#discussion_r1564406802


##########
protocol/triple/triple_protocol/header.go:
##########
@@ -88,61 +90,109 @@ func addHeaderCanonical(h http.Header, key, value string) {
 	h[key] = append(h[key], value)
 }
 
-type headerIncomingKey struct{}
-type headerOutgoingKey struct{}
+type extraDataKey struct{}
+
+const headerIncomingKey string = "headerIncomingKey"
+const headerOutgoingKey string = "headerOutgoingKey"
+
 type handlerOutgoingKey struct{}
 
 func newIncomingContext(ctx context.Context, header http.Header) context.Context {
-	return context.WithValue(ctx, headerIncomingKey{}, header)
+	extraData, ok := ctx.Value(extraDataKey{}).(map[string]http.Header)
+	if !ok {
+		extraData = map[string]http.Header{}
+	}
+	if header == nil {
+		header = make(http.Header)
+	}
+	extraData[headerIncomingKey] = header
+	return context.WithValue(ctx, extraDataKey{}, extraData)
 }
 
 // NewOutgoingContext sets headers entirely. If there are existing headers, they would be replaced.
 // It is used for passing headers to server-side.
 // It is like grpc.NewOutgoingContext.
 // Please refer to https://github.com/grpc/grpc-go/blob/master/Documentation/grpc-metadata.md#sending-metadata.
-func NewOutgoingContext(ctx context.Context, header http.Header) context.Context {
-	return context.WithValue(ctx, headerOutgoingKey{}, header)
+func NewOutgoingContext(ctx context.Context, data interface{}) (context.Context, error) {

Review Comment:
   Why do we need to modify the args of this function?
   - I think ```http.Header``` is clear and efficient enough for users to use.



##########
protocol/triple/triple_protocol/header.go:
##########
@@ -181,3 +231,11 @@ func SendHeader(ctx context.Context, header http.Header) error {
 	mergeHeaders(conn.RequestHeader(), header)
 	return conn.Send(nil)
 }
+
+func outGoingKeyCheck(key string) bool {

Review Comment:
   Where is this function used?



##########
protocol/triple/triple_protocol/header.go:
##########
@@ -88,61 +90,109 @@ func addHeaderCanonical(h http.Header, key, value string) {
 	h[key] = append(h[key], value)
 }
 
-type headerIncomingKey struct{}
-type headerOutgoingKey struct{}
+type extraDataKey struct{}
+
+const headerIncomingKey string = "headerIncomingKey"
+const headerOutgoingKey string = "headerOutgoingKey"
+
 type handlerOutgoingKey struct{}
 
 func newIncomingContext(ctx context.Context, header http.Header) context.Context {
-	return context.WithValue(ctx, headerIncomingKey{}, header)
+	extraData, ok := ctx.Value(extraDataKey{}).(map[string]http.Header)
+	if !ok {
+		extraData = map[string]http.Header{}
+	}
+	if header == nil {
+		header = make(http.Header)
+	}
+	extraData[headerIncomingKey] = header
+	return context.WithValue(ctx, extraDataKey{}, extraData)
 }
 
 // NewOutgoingContext sets headers entirely. If there are existing headers, they would be replaced.
 // It is used for passing headers to server-side.
 // It is like grpc.NewOutgoingContext.
 // Please refer to https://github.com/grpc/grpc-go/blob/master/Documentation/grpc-metadata.md#sending-metadata.
-func NewOutgoingContext(ctx context.Context, header http.Header) context.Context {
-	return context.WithValue(ctx, headerOutgoingKey{}, header)
+func NewOutgoingContext(ctx context.Context, data interface{}) (context.Context, error) {
+	header := make(http.Header)
+	if inputData, ok := data.(map[string]string); ok {
+		for k, v := range inputData {
+			header.Add(k, v)
+		}
+	} else if inputData, ok := data.(map[string][]string); ok {
+		header = inputData
+	} else if inputData, ok := data.(http.Header); ok {
+		header = inputData
+	} else if inputData, ok := data.(map[string]interface{}); ok {
+		for k, v := range inputData {
+			if val, ok := v.(string); ok {
+				header[k] = []string{val}
+			} else if val, ok := v.([]string); ok {
+				header[k] = val
+			} else {
+				return ctx, errors.New("IncomingContext data must be map[string]string or map[string][]string")
+			}
+		}
+	} else {
+		return ctx, errors.New("IncomingContext data must be map[string]string or map[string][]string")
+	}
+
+	extraData, ok := ctx.Value(extraDataKey{}).(map[string]http.Header)
+	if !ok {
+		extraData = map[string]http.Header{}
+	}
+	extraData[headerOutgoingKey] = header
+	return context.WithValue(ctx, extraDataKey{}, extraData), nil
 }
 
 // AppendToOutgoingContext merges kv pairs from user and existing headers.
 // It is used for passing headers to server-side.
 // It is like grpc.AppendToOutgoingContext.
 // Please refer to https://github.com/grpc/grpc-go/blob/master/Documentation/grpc-metadata.md#sending-metadata.
-func AppendToOutgoingContext(ctx context.Context, kv ...string) context.Context {
+func AppendToOutgoingContext(ctx context.Context, kv ...string) (context.Context, error) {

Review Comment:
   What is the reason of returning error?



##########
protocol/triple/triple_protocol/header.go:
##########
@@ -88,61 +90,109 @@ func addHeaderCanonical(h http.Header, key, value string) {
 	h[key] = append(h[key], value)
 }
 
-type headerIncomingKey struct{}
-type headerOutgoingKey struct{}
+type extraDataKey struct{}
+
+const headerIncomingKey string = "headerIncomingKey"
+const headerOutgoingKey string = "headerOutgoingKey"
+
 type handlerOutgoingKey struct{}
 
 func newIncomingContext(ctx context.Context, header http.Header) context.Context {
-	return context.WithValue(ctx, headerIncomingKey{}, header)
+	extraData, ok := ctx.Value(extraDataKey{}).(map[string]http.Header)
+	if !ok {
+		extraData = map[string]http.Header{}
+	}
+	if header == nil {
+		header = make(http.Header)
+	}
+	extraData[headerIncomingKey] = header
+	return context.WithValue(ctx, extraDataKey{}, extraData)
 }
 
 // NewOutgoingContext sets headers entirely. If there are existing headers, they would be replaced.
 // It is used for passing headers to server-side.
 // It is like grpc.NewOutgoingContext.
 // Please refer to https://github.com/grpc/grpc-go/blob/master/Documentation/grpc-metadata.md#sending-metadata.
-func NewOutgoingContext(ctx context.Context, header http.Header) context.Context {
-	return context.WithValue(ctx, headerOutgoingKey{}, header)
+func NewOutgoingContext(ctx context.Context, data interface{}) (context.Context, error) {
+	header := make(http.Header)
+	if inputData, ok := data.(map[string]string); ok {
+		for k, v := range inputData {
+			header.Add(k, v)
+		}
+	} else if inputData, ok := data.(map[string][]string); ok {
+		header = inputData
+	} else if inputData, ok := data.(http.Header); ok {
+		header = inputData
+	} else if inputData, ok := data.(map[string]interface{}); ok {
+		for k, v := range inputData {
+			if val, ok := v.(string); ok {
+				header[k] = []string{val}
+			} else if val, ok := v.([]string); ok {
+				header[k] = val
+			} else {
+				return ctx, errors.New("IncomingContext data must be map[string]string or map[string][]string")
+			}
+		}
+	} else {
+		return ctx, errors.New("IncomingContext data must be map[string]string or map[string][]string")
+	}
+
+	extraData, ok := ctx.Value(extraDataKey{}).(map[string]http.Header)
+	if !ok {
+		extraData = map[string]http.Header{}
+	}
+	extraData[headerOutgoingKey] = header
+	return context.WithValue(ctx, extraDataKey{}, extraData), nil
 }
 
 // AppendToOutgoingContext merges kv pairs from user and existing headers.
 // It is used for passing headers to server-side.
 // It is like grpc.AppendToOutgoingContext.
 // Please refer to https://github.com/grpc/grpc-go/blob/master/Documentation/grpc-metadata.md#sending-metadata.
-func AppendToOutgoingContext(ctx context.Context, kv ...string) context.Context {
+func AppendToOutgoingContext(ctx context.Context, kv ...string) (context.Context, error) {
 	if len(kv)%2 == 1 {
 		panic(fmt.Sprintf("AppendToOutgoingContext got an odd number of input pairs for header: %d", len(kv)))
 	}
-	var header http.Header
-	headerRaw := ctx.Value(headerOutgoingKey{})
-	if headerRaw == nil {
+	extraData, ok := ctx.Value(extraDataKey{}).(map[string]http.Header)
+	if !ok {
+		extraData = map[string]http.Header{}
+		ctx = context.WithValue(ctx, extraDataKey{}, extraData)
+	}
+	header, ok := extraData[headerOutgoingKey]
+	if !ok {
 		header = make(http.Header)
-	} else {
-		header = headerRaw.(http.Header)
+		extraData[headerOutgoingKey] = header
 	}
 	for i := 0; i < len(kv); i += 2 {
 		// todo(DMwangnima): think about lowering
 		header.Add(kv[i], kv[i+1])
 	}
-	return context.WithValue(ctx, headerOutgoingKey{}, header)
+	return ctx, nil
 }
 
-func ExtractFromOutgoingContext(ctx context.Context) http.Header {
-	headerRaw := ctx.Value(headerOutgoingKey{})
-	if headerRaw == nil {
+func ExtractFromOutgoingContext(ctx context.Context) map[string][]string {
+	extraData, ok := ctx.Value(extraDataKey{}).(map[string]http.Header)
+	if !ok {
+		return nil
+	} else if outGoingDataHeader, ok := extraData[headerOutgoingKey]; !ok {
 		return nil
+	} else {
+		return outGoingDataHeader
 	}
-	// since headerOutgoingKey is only used in triple_protocol package, we need not verify the type
-	return headerRaw.(http.Header)
 }
 
 // FromIncomingContext retrieves headers passed by client-side. It is like grpc.FromIncomingContext.
+// it must call after append/setOutgoingContext to return current value
 // Please refer to https://github.com/grpc/grpc-go/blob/master/Documentation/grpc-metadata.md#receiving-metadata-1.
-func FromIncomingContext(ctx context.Context) (http.Header, bool) {
-	header, ok := ctx.Value(headerIncomingKey{}).(http.Header)
+func FromIncomingContext(ctx context.Context) (map[string][]string, bool) {

Review Comment:
   ditto.



##########
protocol/triple/triple_protocol/header.go:
##########
@@ -88,61 +90,109 @@ func addHeaderCanonical(h http.Header, key, value string) {
 	h[key] = append(h[key], value)
 }
 
-type headerIncomingKey struct{}
-type headerOutgoingKey struct{}
+type extraDataKey struct{}
+
+const headerIncomingKey string = "headerIncomingKey"
+const headerOutgoingKey string = "headerOutgoingKey"
+
 type handlerOutgoingKey struct{}
 
 func newIncomingContext(ctx context.Context, header http.Header) context.Context {
-	return context.WithValue(ctx, headerIncomingKey{}, header)
+	extraData, ok := ctx.Value(extraDataKey{}).(map[string]http.Header)
+	if !ok {
+		extraData = map[string]http.Header{}
+	}
+	if header == nil {
+		header = make(http.Header)
+	}
+	extraData[headerIncomingKey] = header
+	return context.WithValue(ctx, extraDataKey{}, extraData)
 }
 
 // NewOutgoingContext sets headers entirely. If there are existing headers, they would be replaced.
 // It is used for passing headers to server-side.
 // It is like grpc.NewOutgoingContext.
 // Please refer to https://github.com/grpc/grpc-go/blob/master/Documentation/grpc-metadata.md#sending-metadata.
-func NewOutgoingContext(ctx context.Context, header http.Header) context.Context {
-	return context.WithValue(ctx, headerOutgoingKey{}, header)
+func NewOutgoingContext(ctx context.Context, data interface{}) (context.Context, error) {
+	header := make(http.Header)
+	if inputData, ok := data.(map[string]string); ok {
+		for k, v := range inputData {
+			header.Add(k, v)
+		}
+	} else if inputData, ok := data.(map[string][]string); ok {
+		header = inputData
+	} else if inputData, ok := data.(http.Header); ok {
+		header = inputData
+	} else if inputData, ok := data.(map[string]interface{}); ok {
+		for k, v := range inputData {
+			if val, ok := v.(string); ok {
+				header[k] = []string{val}
+			} else if val, ok := v.([]string); ok {
+				header[k] = val
+			} else {
+				return ctx, errors.New("IncomingContext data must be map[string]string or map[string][]string")
+			}
+		}
+	} else {
+		return ctx, errors.New("IncomingContext data must be map[string]string or map[string][]string")
+	}
+
+	extraData, ok := ctx.Value(extraDataKey{}).(map[string]http.Header)
+	if !ok {
+		extraData = map[string]http.Header{}
+	}
+	extraData[headerOutgoingKey] = header
+	return context.WithValue(ctx, extraDataKey{}, extraData), nil
 }
 
 // AppendToOutgoingContext merges kv pairs from user and existing headers.
 // It is used for passing headers to server-side.
 // It is like grpc.AppendToOutgoingContext.
 // Please refer to https://github.com/grpc/grpc-go/blob/master/Documentation/grpc-metadata.md#sending-metadata.
-func AppendToOutgoingContext(ctx context.Context, kv ...string) context.Context {
+func AppendToOutgoingContext(ctx context.Context, kv ...string) (context.Context, error) {
 	if len(kv)%2 == 1 {
 		panic(fmt.Sprintf("AppendToOutgoingContext got an odd number of input pairs for header: %d", len(kv)))
 	}
-	var header http.Header
-	headerRaw := ctx.Value(headerOutgoingKey{})
-	if headerRaw == nil {
+	extraData, ok := ctx.Value(extraDataKey{}).(map[string]http.Header)
+	if !ok {
+		extraData = map[string]http.Header{}
+		ctx = context.WithValue(ctx, extraDataKey{}, extraData)
+	}
+	header, ok := extraData[headerOutgoingKey]
+	if !ok {
 		header = make(http.Header)
-	} else {
-		header = headerRaw.(http.Header)
+		extraData[headerOutgoingKey] = header
 	}
 	for i := 0; i < len(kv); i += 2 {
 		// todo(DMwangnima): think about lowering
 		header.Add(kv[i], kv[i+1])
 	}
-	return context.WithValue(ctx, headerOutgoingKey{}, header)
+	return ctx, nil
 }
 
-func ExtractFromOutgoingContext(ctx context.Context) http.Header {
-	headerRaw := ctx.Value(headerOutgoingKey{})
-	if headerRaw == nil {
+func ExtractFromOutgoingContext(ctx context.Context) map[string][]string {

Review Comment:
   ditto. 



-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: notifications-unsubscribe@dubbo.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org


---------------------------------------------------------------------
To unsubscribe, e-mail: notifications-unsubscribe@dubbo.apache.org
For additional commands, e-mail: notifications-help@dubbo.apache.org