Skip to content

Commit

Permalink
禁止Go客户端自动重定向 (#1030)
Browse files Browse the repository at this point in the history
* close http.Response Body

* 禁止Go客户端自动重定向

* 请求为空时,defer r.Body.Close()panic

* 请求返回体为空时,defer r.Body.Close()panic

* Update rest_client.go

请求返回体为空时,defer r.Body.Close()panic

* 禁止Go客户端自动重定向

* 禁止Go客户端自动重定向

Co-authored-by: c30014156 <chenwei387@huawei.com>
  • Loading branch information
chenwei113524 and c30014156 committed Apr 26, 2022
1 parent 77eb082 commit f191803
Show file tree
Hide file tree
Showing 6 changed files with 48 additions and 18 deletions.
11 changes: 9 additions & 2 deletions client/rest/rest_client.go
Original file line number Diff line number Diff line change
Expand Up @@ -63,8 +63,9 @@ func NewRestClient(opts client.Options) (client.ProtocolClient, error) {
opts: opts,

c: &http.Client{
Timeout: opts.Timeout,
Transport: tp,
Timeout: opts.Timeout,
Transport: tp,
CheckRedirect: opts.CheckRedirect,
},
}
return rc, nil
Expand All @@ -91,6 +92,12 @@ func newTransport(opts client.Options) *http.Transport {

// If a request fails, we generate an error.
func (c *Client) failure2Error(e error, r *http.Response, addr string) error {
defer func() {
if r == nil || r.Body == nil {
return
}
r.Body.Close()
}()
if e != nil {
return e
}
Expand Down
34 changes: 19 additions & 15 deletions core/client/client_manager.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import (
"crypto/tls"
"errors"
"fmt"
"net/http"
"strings"
"sync"
"time"
Expand All @@ -27,13 +28,14 @@ const DefaultPoolSize = 512

//Options is configs for client creation
type Options struct {
Service string
PoolSize int
Timeout time.Duration
Endpoint string
PoolTTL time.Duration
TLSConfig *tls.Config
Failure map[string]bool
Service string
PoolSize int
Timeout time.Duration
Endpoint string
PoolTTL time.Duration
TLSConfig *tls.Config
Failure map[string]bool
CheckRedirect func(req *http.Request, via []*http.Request) error
}

// GetFailureMap return failure map
Expand All @@ -60,7 +62,7 @@ func GetMaxIdleCon(p string) int {
}

// CreateClient is for to create client based on protocol and the service name
func CreateClient(protocol, service, endpoint string, sslEnable bool) (ProtocolClient, error) {
func CreateClient(protocol, service, endpoint string, sslEnable bool, checkRedirect func(req *http.Request, via []*http.Request) error) (ProtocolClient, error) {
f, err := GetClientNewFunc(protocol)
if err != nil {
openlog.Error(fmt.Sprintf("do not support [%s] client", protocol))
Expand All @@ -86,12 +88,13 @@ func CreateClient(protocol, service, endpoint string, sslEnable bool) (ProtocolC
command = strings.Join([]string{common.Consumer, service}, ".")
}
return f(Options{
Service: service,
TLSConfig: tlsConfig,
PoolSize: GetMaxIdleCon(protocol),
Failure: GetFailureMap(protocol),
Timeout: config.GetTimeoutDurationFromArchaius(command, common.Consumer),
Endpoint: endpoint,
Service: service,
TLSConfig: tlsConfig,
PoolSize: GetMaxIdleCon(protocol),
Failure: GetFailureMap(protocol),
Timeout: config.GetTimeoutDurationFromArchaius(command, common.Consumer),
Endpoint: endpoint,
CheckRedirect: checkRedirect,
})
}
func generateKey(protocol, service, endpoint string) string {
Expand All @@ -108,7 +111,7 @@ func GetClient(i *invocation.Invocation) (ProtocolClient, error) {
sl.RUnlock()
if !ok {
openlog.Info("Create client for " + i.Protocol + ":" + i.MicroServiceName + ":" + i.Endpoint)
c, err = CreateClient(i.Protocol, i.MicroServiceName, i.Endpoint, i.SSLEnable)
c, err = CreateClient(i.Protocol, i.MicroServiceName, i.Endpoint, i.SSLEnable, i.CheckRedirect)
if err != nil {
return nil, err
}
Expand Down Expand Up @@ -169,5 +172,6 @@ func EqualOpts(oldOpts, newOpts Options) Options {
oldOpts.TLSConfig = newOpts.TLSConfig
}
oldOpts.Failure = newOpts.Failure
oldOpts.CheckRedirect = newOpts.CheckRedirect
return oldOpts
}
2 changes: 1 addition & 1 deletion core/config/cd_config_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ servicecomb:
---
servicecomb:
service:
name: Client
name: Client
`)
d, _ = os.Getwd()
Expand Down
3 changes: 3 additions & 0 deletions core/core_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,9 @@ func TestOptions(t *testing.T) {
inv = core.WithMetadata(nil)
assert.NotEmpty(t, inv)

inv = core.WithCheckRedirect()
assert.NotEmpty(t, inv)

t.Log("with router tag")
testKey := "testKey"
testValue := "testValue"
Expand Down
3 changes: 3 additions & 0 deletions core/invocation/invocation.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package invocation

import (
"context"
"net/http"

"github.com/go-chassis/go-chassis/v2/core/common"
"github.com/go-chassis/go-chassis/v2/pkg/runtime"
Expand Down Expand Up @@ -63,6 +64,8 @@ type Invocation struct {
Metadata map[string]interface{} // can save local data, will not send in header on network
Strategy string // load balancing strategy
Filters []string
// http.CheckRedirect
CheckRedirect func(req *http.Request, via []*http.Request) error
}

// GetMark return match rule name that request matches
Expand Down
13 changes: 13 additions & 0 deletions core/options.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package core

import (
"net/http"
"time"

"github.com/go-chassis/go-chassis/v2/core/invocation"
Expand Down Expand Up @@ -36,6 +37,8 @@ type InvokeOptions struct {
Metadata map[string]interface{}
// tags for router
RouteTags utiltags.Tags
//http.CheckRedirect
CheckRedirect func(req *http.Request, via []*http.Request) error
}

//TODO a lot of options
Expand Down Expand Up @@ -98,6 +101,15 @@ func WithProtocol(p string) InvocationOption {
}
}

// WithCheckRedirect is a request option
func WithCheckRedirect() InvocationOption {
return func(o *InvokeOptions) {
o.CheckRedirect = func(req *http.Request, via []*http.Request) error {
return http.ErrUseLastResponse
}
}
}

// WithStrategy is a request option
func WithStrategy(s string) InvocationOption {
return func(o *InvokeOptions) {
Expand Down Expand Up @@ -155,4 +167,5 @@ func wrapInvocationWithOpts(i *invocation.Invocation, opts InvokeOptions) {
}

i.RouteTags = opts.RouteTags
i.CheckRedirect = opts.CheckRedirect
}

0 comments on commit f191803

Please sign in to comment.