Skip to content

Commit

Permalink
Merge pull request #139 from microsoft/feat/middleware-with-options
Browse files Browse the repository at this point in the history
Adds middleware with overridable options
  • Loading branch information
baywet authored Jan 22, 2024
2 parents 1430a26 + 52a0763 commit 3b54a31
Show file tree
Hide file tree
Showing 4 changed files with 179 additions and 8 deletions.
6 changes: 6 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,12 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0

### Changed

## [1.3.0] - 2024-01-22

### Added

- Added support to override default middleware with function `GetDefaultMiddlewaresWithOptions`.

## [1.2.1] - 2023-01-22

### Changed
Expand Down
2 changes: 1 addition & 1 deletion headers_inspection_handler_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ func TestHeadersInspectionOptionsImplementTheOptionInterface(t *testing.T) {
options := NewHeadersInspectionOptions()
assert.NotNil(t, options)
_, ok := any(options).(abs.RequestOption)
assert.True(t, ok, "options does not implement RequestOption")
assert.True(t, ok, "options does not implement optionsType")
}

func TestItGetsRequestHeaders(t *testing.T) {
Expand Down
80 changes: 73 additions & 7 deletions kiota_client_factory.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@
package nethttplibrary

import (
"errors"
abs "github.com/microsoft/kiota-abstractions-go"
nethttp "net/http"
"net/url"
"time"
Expand Down Expand Up @@ -76,12 +78,76 @@ func getDefaultClientWithoutMiddleware() *nethttp.Client {

// GetDefaultMiddlewares creates a new default set of middlewares for the Kiota request adapter
func GetDefaultMiddlewares() []Middleware {
return []Middleware{
NewRetryHandler(),
NewRedirectHandler(),
NewCompressionHandler(),
NewParametersNameDecodingHandler(),
NewUserAgentHandler(),
NewHeadersInspectionHandler(),
return getDefaultMiddleWare(make(map[abs.RequestOptionKey]Middleware))
}

// GetDefaultMiddlewaresWithOptions creates a new default set of middlewares for the Kiota request adapter with options
func GetDefaultMiddlewaresWithOptions(requestOptions ...abs.RequestOption) ([]Middleware, error) {
if len(requestOptions) == 0 {
return GetDefaultMiddlewares(), nil
}

// map of middleware options
middlewareMap := make(map[abs.RequestOptionKey]Middleware)

for _, element := range requestOptions {
switch v := element.(type) {
case *RetryHandlerOptions:
middlewareMap[retryKeyValue] = NewRetryHandlerWithOptions(*v)
case *RedirectHandlerOptions:
middlewareMap[redirectKeyValue] = NewRedirectHandlerWithOptions(*v)
case *CompressionOptions:
middlewareMap[compressKey] = NewCompressionHandlerWithOptions(*v)
case *ParametersNameDecodingOptions:
middlewareMap[parametersNameDecodingKeyValue] = NewParametersNameDecodingHandlerWithOptions(*v)
case *UserAgentHandlerOptions:
middlewareMap[userAgentKeyValue] = NewUserAgentHandlerWithOptions(v)
case *HeadersInspectionOptions:
middlewareMap[headersInspectionKeyValue] = NewHeadersInspectionHandlerWithOptions(*v)
default:
// none of the above types
return nil, errors.New("unsupported option type")
}
}

middleware := getDefaultMiddleWare(middlewareMap)
return middleware, nil
}

// getDefaultMiddleWare creates a new default set of middlewares for the Kiota request adapter
func getDefaultMiddleWare(middlewareMap map[abs.RequestOptionKey]Middleware) []Middleware {
middlewareSource := map[abs.RequestOptionKey]func() Middleware{
retryKeyValue: func() Middleware {
return NewRetryHandler()
},
redirectKeyValue: func() Middleware {
return NewRedirectHandler()
},
compressKey: func() Middleware {
return NewCompressionHandler()
},
parametersNameDecodingKeyValue: func() Middleware {
return NewParametersNameDecodingHandler()
},
userAgentKeyValue: func() Middleware {
return NewUserAgentHandler()
},
headersInspectionKeyValue: func() Middleware {
return NewHeadersInspectionHandler()
},
}

// loop over middlewareSource and add any middleware that wasn't provided in the requestOptions
for key, value := range middlewareSource {
if _, ok := middlewareMap[key]; !ok {
middlewareMap[key] = value()
}
}

var middleware []Middleware
for _, value := range middlewareMap {
middleware = append(middleware, value)
}

return middleware
}
99 changes: 99 additions & 0 deletions kiota_client_factory_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,99 @@
package nethttplibrary

import (
abstractions "github.com/microsoft/kiota-abstractions-go"
"github.com/stretchr/testify/assert"
nethttp "net/http"
"testing"
"time"
)

func TestGetDefaultMiddleWareWithMultipleOptions(t *testing.T) {
retryOptions := RetryHandlerOptions{
ShouldRetry: func(delay time.Duration, executionCount int, request *nethttp.Request, response *nethttp.Response) bool {
return false
},
}
redirectHandlerOptions := RedirectHandlerOptions{
MaxRedirects: defaultMaxRedirects,
ShouldRedirect: func(req *nethttp.Request, res *nethttp.Response) bool {
return true
},
}
compressionOptions := NewCompressionOptions(false)
parametersNameDecodingOptions := ParametersNameDecodingOptions{
Enable: true,
ParametersToDecode: []byte{'-', '.', '~', '$'},
}
userAgentHandlerOptions := UserAgentHandlerOptions{
Enabled: true,
ProductName: "kiota-go",
ProductVersion: "1.1.0",
}
headersInspectionOptions := HeadersInspectionOptions{
RequestHeaders: abstractions.NewRequestHeaders(),
ResponseHeaders: abstractions.NewResponseHeaders(),
}
options, err := GetDefaultMiddlewaresWithOptions(&retryOptions,
&redirectHandlerOptions,
&compressionOptions,
&parametersNameDecodingOptions,
&userAgentHandlerOptions,
&headersInspectionOptions,
)
if err != nil {
t.Errorf(err.Error())
}
if len(options) != 6 {
t.Errorf("expected 6 middleware, got %v", len(options))
}

for _, element := range options {
switch v := element.(type) {
case *CompressionHandler:
assert.Equal(t, v.options.ShouldCompress(), compressionOptions.ShouldCompress())
}
}
}

func TestGetDefaultMiddleWareWithInvalidOption(t *testing.T) {
chaosOptions := ChaosHandlerOptions{
ChaosPercentage: 101,
ChaosStrategy: Random,
}
_, err := GetDefaultMiddlewaresWithOptions(&chaosOptions)

assert.Equal(t, err.Error(), "unsupported option type")
}

func TestGetDefaultMiddleWareWithOptions(t *testing.T) {
compression := NewCompressionOptions(false)
options, err := GetDefaultMiddlewaresWithOptions(&compression)
if err != nil {
t.Errorf(err.Error())
}
if len(options) != 6 {
t.Errorf("expected 6 middleware, got %v", len(options))
}

for _, element := range options {
switch v := element.(type) {
case *CompressionHandler:
assert.Equal(t, v.options.ShouldCompress(), compression.ShouldCompress())
}
}
}

func TestGetDefaultMiddlewares(t *testing.T) {
options := GetDefaultMiddlewares()
if len(options) != 6 {
t.Errorf("expected 6 middleware, got %v", len(options))
}

for _, element := range options {
switch v := element.(type) {
case *CompressionHandler:
assert.True(t, v.options.ShouldCompress())
}
}
}

0 comments on commit 3b54a31

Please sign in to comment.