@@ -4,19 +4,19 @@ import (
4
4
"fmt"
5
5
"net/http"
6
6
"net/url"
7
+ "reflect"
7
8
)
8
9
9
10
type ProxyOption struct {
10
11
ProxyURL string
12
+ proxyObj * url.URL
11
13
}
12
14
13
15
func NewProxyOption (proxyURL string ) * ProxyOption {
14
16
return & ProxyOption {ProxyURL : proxyURL }
15
17
}
16
18
17
- // TODO: Allow for other types of proxies outside of stdlib too?
18
-
19
- func (o * ProxyOption ) Execute (client * http.Client ) error {
19
+ func (o * ProxyOption ) ExecuteV1 (client * http.Client ) error {
20
20
puo , err := url .Parse (o .ProxyURL )
21
21
if err != nil {
22
22
return fmt .Errorf ("ProxyOption: url.Parse: %w" , err )
@@ -29,3 +29,83 @@ func (o *ProxyOption) Execute(client *http.Client) error {
29
29
30
30
return nil
31
31
}
32
+
33
+ func (o * ProxyOption ) Execute (client * http.Client ) error {
34
+ puo , err := url .Parse (o .ProxyURL )
35
+ if err != nil {
36
+ return fmt .Errorf ("ProxyOption: url.Parse: %w" , err )
37
+ }
38
+ o .proxyObj = puo
39
+ return o .processTransport (client , 1 )
40
+ }
41
+
42
+ func (o * ProxyOption ) processTransport (clientOrTransport any , depth int ) error {
43
+ var (
44
+ ok bool
45
+ clientOrTransportRV reflect.Value
46
+ )
47
+ clientOrTransportRV , ok = clientOrTransport .(reflect.Value )
48
+ if ! ok {
49
+ clientOrTransportRV = reflect .ValueOf (clientOrTransport )
50
+ }
51
+
52
+ if clientOrTransportRV .Kind () != reflect .Ptr || clientOrTransportRV .IsNil () {
53
+ return fmt .Errorf ("expected non-nil pointer to struct" )
54
+ }
55
+
56
+ // fmt.Println(fmt.Sprintf("Depth %d clientOrTransport.Type: %s", depth, clientOrTransport.Type().String()))
57
+ clientOrTransportElem := clientOrTransportRV .Elem ()
58
+ // fmt.Println(fmt.Sprintf("Depth %d rvElem.Type: %s", depth, clientOrTransportElem.Type().String()))
59
+
60
+ // http.Client, oohttp.Client, http.Transport, oohttp.StdlibTransport, oohttp.Transport are all structs.
61
+ if clientOrTransportElem .Kind () != reflect .Struct {
62
+ return fmt .Errorf ("expected pointer to struct" )
63
+ }
64
+
65
+ // Check for ".Transport" field
66
+ transportField := clientOrTransportElem .FieldByName ("Transport" )
67
+ // Should always be an interface
68
+ if transportField .Kind () == reflect .Interface {
69
+ transportField = transportField .Elem ()
70
+ }
71
+
72
+ // If it exists, we should recurse into it
73
+ if transportField .IsValid () {
74
+ // fmt.Println(fmt.Sprintf("Depth %d configField.Type: %s", depth, transportField.Type().String()))
75
+ if transportField .Kind () == reflect .Ptr {
76
+ if transportField .IsNil () {
77
+ return fmt .Errorf ("transport field is nil" )
78
+ }
79
+ return o .processTransport (transportField , depth + 1 )
80
+ } else if transportField .Kind () == reflect .Struct {
81
+ return o .processTransport (transportField .Addr (), depth + 1 )
82
+ } else {
83
+ return fmt .Errorf ("transport field is not a struct or pointer to struct" )
84
+ }
85
+ } else {
86
+ // Set ".Proxy" field
87
+ proxyField := clientOrTransportElem .FieldByName ("Proxy" )
88
+ if proxyField .IsValid () && proxyField .Kind () == reflect .Func {
89
+ if ! proxyField .CanSet () {
90
+ return fmt .Errorf ("cannot set Proxy field" )
91
+ }
92
+ // Literally make a new function based on it's signature
93
+ proxyFieldType := proxyField .Type ()
94
+ newFuncValue := reflect .MakeFunc (proxyFieldType , func (args []reflect.Value ) (results []reflect.Value ) {
95
+ // fmt.Println("Dynamic Proxy called with arguments:")
96
+ for i , arg := range args {
97
+ fmt .Printf (" Arg %d: %v\n " , i , arg .Interface ())
98
+ }
99
+ results = make ([]reflect.Value , proxyFieldType .NumOut ())
100
+ results [0 ] = reflect .ValueOf (o .proxyObj )
101
+ results [1 ] = reflect .Zero (reflect .TypeOf ((* error )(nil )).Elem ())
102
+ return results
103
+ })
104
+ // Set the Proxy field to the new function
105
+ proxyField .Set (newFuncValue )
106
+ return nil
107
+ } else {
108
+ return fmt .Errorf ("proxy field not found or not a function" )
109
+ }
110
+ }
111
+ }
0 commit comments