Skip to content

Commit 063d352

Browse files
internal/resolver: introduce a new resolver to handle target URI and proxy address resolution (#7857)
1 parent 10c7e13 commit 063d352

File tree

5 files changed

+1162
-0
lines changed

5 files changed

+1162
-0
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
/*
2+
*
3+
* Copyright 2024 gRPC authors.
4+
*
5+
* Licensed under the Apache License, Version 2.0 (the "License");
6+
* you may not use this file except in compliance with the License.
7+
* You may obtain a copy of the License at
8+
*
9+
* http://www.apache.org/licenses/LICENSE-2.0
10+
*
11+
* Unless required by applicable law or agreed to in writing, software
12+
* distributed under the License is distributed on an "AS IS" BASIS,
13+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14+
* See the License for the specific language governing permissions and
15+
* limitations under the License.
16+
*
17+
*/
18+
19+
// Package proxyattributes contains functions for getting and setting proxy
20+
// attributes like the CONNECT address and user info.
21+
package proxyattributes
22+
23+
import (
24+
"net/url"
25+
26+
"google.golang.org/grpc/resolver"
27+
)
28+
29+
type keyType string
30+
31+
const proxyOptionsKey = keyType("grpc.resolver.delegatingresolver.proxyOptions")
32+
33+
// Options holds the proxy connection details needed during the CONNECT
34+
// handshake.
35+
type Options struct {
36+
User url.Userinfo
37+
ConnectAddr string
38+
}
39+
40+
// Set returns a copy of addr with opts set in its attributes.
41+
func Set(addr resolver.Address, opts Options) resolver.Address {
42+
addr.Attributes = addr.Attributes.WithValue(proxyOptionsKey, opts)
43+
return addr
44+
}
45+
46+
// Get returns the Options for the proxy [resolver.Address] and a boolean
47+
// value representing if the attribute is present or not.
48+
func Get(addr resolver.Address) (Options, bool) {
49+
if a := addr.Attributes.Value(proxyOptionsKey); a != nil {
50+
return a.(Options), true
51+
}
52+
return Options{}, false
53+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,116 @@
1+
/*
2+
*
3+
* Copyright 2024 gRPC authors.
4+
*
5+
* Licensed under the Apache License, Version 2.0 (the "License");
6+
* you may not use this file except in compliance with the License.
7+
* You may obtain a copy of the License at
8+
*
9+
* http://www.apache.org/licenses/LICENSE-2.0
10+
*
11+
* Unless required by applicable law or agreed to in writing, software
12+
* distributed under the License is distributed on an "AS IS" BASIS,
13+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14+
* See the License for the specific language governing permissions and
15+
* limitations under the License.
16+
*
17+
*/
18+
19+
package proxyattributes
20+
21+
import (
22+
"net/url"
23+
"testing"
24+
25+
"google.golang.org/grpc/attributes"
26+
"google.golang.org/grpc/internal/grpctest"
27+
"google.golang.org/grpc/resolver"
28+
)
29+
30+
type s struct {
31+
grpctest.Tester
32+
}
33+
34+
func Test(t *testing.T) {
35+
grpctest.RunSubTests(t, s{})
36+
}
37+
38+
// Tests that Get returns a valid proxy attribute.
39+
func (s) TestGet(t *testing.T) {
40+
user := url.UserPassword("username", "password")
41+
tests := []struct {
42+
name string
43+
addr resolver.Address
44+
wantConnectAddr string
45+
wantUser url.Userinfo
46+
wantAttrPresent bool
47+
}{
48+
{
49+
name: "connect_address_in_attribute",
50+
addr: resolver.Address{
51+
Addr: "test-address",
52+
Attributes: attributes.New(proxyOptionsKey, Options{
53+
ConnectAddr: "proxy-address",
54+
}),
55+
},
56+
wantConnectAddr: "proxy-address",
57+
wantAttrPresent: true,
58+
},
59+
{
60+
name: "user_in_attribute",
61+
addr: resolver.Address{
62+
Addr: "test-address",
63+
Attributes: attributes.New(proxyOptionsKey, Options{
64+
User: *user,
65+
}),
66+
},
67+
wantUser: *user,
68+
wantAttrPresent: true,
69+
},
70+
{
71+
name: "no_attribute",
72+
addr: resolver.Address{Addr: "test-address"},
73+
wantAttrPresent: false,
74+
},
75+
}
76+
77+
for _, tt := range tests {
78+
t.Run(tt.name, func(t *testing.T) {
79+
gotOption, attrPresent := Get(tt.addr)
80+
if attrPresent != tt.wantAttrPresent {
81+
t.Errorf("Get(%v) = %v, want %v", tt.addr, attrPresent, tt.wantAttrPresent)
82+
}
83+
84+
if gotOption.ConnectAddr != tt.wantConnectAddr {
85+
t.Errorf("ConnectAddr(%v) = %v, want %v", tt.addr, gotOption.ConnectAddr, tt.wantConnectAddr)
86+
}
87+
88+
if gotOption.User != tt.wantUser {
89+
t.Errorf("User(%v) = %v, want %v", tt.addr, gotOption.User, tt.wantUser)
90+
}
91+
})
92+
}
93+
}
94+
95+
// Tests that Set returns a copy of addr with attributes containing correct
96+
// user and connect address.
97+
func (s) TestSet(t *testing.T) {
98+
addr := resolver.Address{Addr: "test-address"}
99+
pOpts := Options{
100+
User: *url.UserPassword("username", "password"),
101+
ConnectAddr: "proxy-address",
102+
}
103+
104+
// Call Set and validate attributes
105+
populatedAddr := Set(addr, pOpts)
106+
gotOption, attrPresent := Get(populatedAddr)
107+
if !attrPresent {
108+
t.Errorf("Get(%v) = %v, want %v ", populatedAddr, attrPresent, true)
109+
}
110+
if got, want := gotOption.ConnectAddr, pOpts.ConnectAddr; got != want {
111+
t.Errorf("Unexpected ConnectAddr proxy atrribute = %v, want %v", got, want)
112+
}
113+
if got, want := gotOption.User, pOpts.User; got != want {
114+
t.Errorf("unexpected User proxy attribute = %v, want %v", got, want)
115+
}
116+
}

0 commit comments

Comments
 (0)