From 817b60025fe1db829fa56c88f21e59186a89a9c1 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 5 Dec 2024 03:07:39 +0000 Subject: [PATCH 1/4] Bump the all group with 2 updates Bumps the all group with 2 updates: [golang.org/x/crypto](https://github.com/golang/crypto) and [golang.org/x/sys](https://github.com/golang/sys). Updates `golang.org/x/crypto` from 0.29.0 to 0.30.0 - [Commits](https://github.com/golang/crypto/compare/v0.29.0...v0.30.0) Updates `golang.org/x/sys` from 0.27.0 to 0.28.0 - [Commits](https://github.com/golang/sys/compare/v0.27.0...v0.28.0) --- updated-dependencies: - dependency-name: golang.org/x/crypto dependency-type: direct:production update-type: version-update:semver-minor dependency-group: all - dependency-name: golang.org/x/sys dependency-type: direct:production update-type: version-update:semver-minor dependency-group: all ... Signed-off-by: dependabot[bot] --- go.mod | 4 ++-- go.sum | 8 ++++---- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/go.mod b/go.mod index 0f834108..557ed7a0 100644 --- a/go.mod +++ b/go.mod @@ -6,8 +6,8 @@ require ( github.com/essentialkaos/check v1.4.1 github.com/essentialkaos/depsy v1.3.1 github.com/essentialkaos/go-linenoise/v3 v3.6.1 - golang.org/x/crypto v0.29.0 - golang.org/x/sys v0.27.0 + golang.org/x/crypto v0.30.0 + golang.org/x/sys v0.28.0 ) require ( diff --git a/go.sum b/go.sum index 537178bf..b5f6a78d 100644 --- a/go.sum +++ b/go.sum @@ -13,7 +13,7 @@ github.com/pkg/diff v0.0.0-20210226163009-20ebb0f2a09e/go.mod h1:pJLUxLENpZxwdsK github.com/rogpeppe/go-internal v1.9.0/go.mod h1:WtVeX8xhTBvf0smdhujwtBcq4Qrzq/fJaraNFVN+nFs= github.com/rogpeppe/go-internal v1.13.1 h1:KvO1DLK/DRN07sQ1LQKScxyZJuNnedQ5/wKSR38lUII= github.com/rogpeppe/go-internal v1.13.1/go.mod h1:uMEvuHeurkdAXX61udpOXGD/AzZDWNMNyH2VO9fmH0o= -golang.org/x/crypto v0.29.0 h1:L5SG1JTTXupVV3n6sUqMTeWbjAyfPwoda2DLX8J8FrQ= -golang.org/x/crypto v0.29.0/go.mod h1:+F4F4N5hv6v38hfeYwTdx20oUvLLc+QfrE9Ax9HtgRg= -golang.org/x/sys v0.27.0 h1:wBqf8DvsY9Y/2P8gAfPDEYNuS30J4lPHJxXSb/nJZ+s= -golang.org/x/sys v0.27.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/crypto v0.30.0 h1:RwoQn3GkWiMkzlX562cLB7OxWvjH1L8xutO2WoJcRoY= +golang.org/x/crypto v0.30.0/go.mod h1:kDsLvtWBEx7MV9tJOj9bnXsPbxwJQ6csT/x4KIN4Ssk= +golang.org/x/sys v0.28.0 h1:Fksou7UEQUWlKvIdsqzJmUmCX3cZuD2+P3XyyzwMhlA= +golang.org/x/sys v0.28.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= From 8ba57648d3de4ff64f431ab05459ff33454c3a86 Mon Sep 17 00:00:00 2001 From: Anton Novojilov Date: Mon, 9 Dec 2024 16:50:52 +0300 Subject: [PATCH 2/4] [color] Add fmt.GoStringer support for structs --- CHANGELOG.md | 5 ++++ color/color.go | 59 ++++++++++++++++++++++++++++++++---------- color/color_test.go | 30 +++++++++++++-------- color/examples_test.go | 54 +++++++++++++++++++------------------- version.go | 2 +- 5 files changed, 97 insertions(+), 53 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index d5778ebe..8a90260b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,10 @@ ## Changelog +### [13.14.3](https://kaos.sh/ek/13.14.3) + +- `[color]` Added `fmt.GoStringer` support for structs +- `[color]` Code refactoring + ### [13.14.2](https://kaos.sh/ek/13.14.2) - `[log]` Added variable `LogLevels` with all supported log level names diff --git a/color/color.go b/color/color.go index fee183be..26e7f4d4 100644 --- a/color/color.go +++ b/color/color.go @@ -336,51 +336,82 @@ func (c Hex) ToWeb(useCaps, allowShorthand bool) string { return "#" + k } +// String returns string representation of hex color +func (c Hex) String() string { + return c.ToWeb(true, false) +} + // String returns string representation of RGB color func (c RGB) String() string { - return fmt.Sprintf( - "RGB{R:%d G:%d B:%d}", - c.R, c.G, c.B, - ) + return fmt.Sprintf("%d,%d,%d", c.R, c.G, c.B) +} + +// GoString returns Go representation of RGB color +func (c RGB) GoString() string { + return fmt.Sprintf("RGB{R:%d, G:%d, B:%d}", c.R, c.G, c.B) } // String returns string representation of RGBA color func (c RGBA) String() string { - return fmt.Sprintf( - "RGBA{R:%d G:%d B:%d A:%.2f}", - c.R, c.G, c.B, float64(c.A)/255.0, - ) + return fmt.Sprintf("%d,%d,%d,%.2f", c.R, c.G, c.B, float64(c.A)/255.0) } -// String returns string representation of hex color -func (c Hex) String() string { - return fmt.Sprintf("Hex{%s}", c.ToWeb(true, false)) +// GoString returns Go representation of RGBA color +func (c RGBA) GoString() string { + if c.A == 0 { + return fmt.Sprintf("RGBA{R:%d, G:%d, B:%d}", c.R, c.G, c.B) + } + + return fmt.Sprintf("RGBA{R:%d, G:%d, B:%d, A:%d}", c.R, c.G, c.B, c.A) } // String returns string representation of CMYK color func (c CMYK) String() string { return fmt.Sprintf( - "CMYK{C:%.0f%% M:%.0f%% Y:%.0f%% K:%.0f%%}", + "%.0f%%,%.0f%%,%.0f%%,%.0f%%", c.C*100.0, c.M*100.0, c.Y*100.0, c.K*100.0, ) } +// GoString returns Go representation of CMYK color +func (c CMYK) GoString() string { + return fmt.Sprintf("CMYK{C:%g, M:%g, Y:%g, K:%g}", c.C, c.M, c.Y, c.K) +} + // String returns string representation of HSV color func (c HSV) String() string { return fmt.Sprintf( - "HSV{H:%.0f° S:%.0f%% V:%.0f%% A:%.0f%%}", + "%.0f°,%.0f%%,%.0f%%,%.0f%%", c.H*360, c.S*100, c.V*100, c.A*100, ) } +// GoString returns Go representation of HSV color +func (c HSV) GoString() string { + if c.A == 0 { + return fmt.Sprintf("HSV{H:%g, S:%g, V:%g}", c.H, c.S, c.V) + } + + return fmt.Sprintf("HSV{H:%g, S:%g, V:%g, A:%g}", c.H, c.S, c.V, c.A) +} + // String returns string representation of HSL color func (c HSL) String() string { return fmt.Sprintf( - "HSL{H:%.0f° S:%.0f%% L:%.0f%% A:%.0f%%}", + "%.0f°,%.0f%%,%.0f%%,%.0f%%", c.H*360, c.S*100, c.L*100, c.A*100, ) } +// GoString returns Go representation of HSL color +func (c HSL) GoString() string { + if c.A == 0 { + return fmt.Sprintf("HSL{H:%g, S:%g, L:%g}", c.H, c.S, c.L) + } + + return fmt.Sprintf("HSL{H:%g, S:%g, L:%g, A:%g}", c.H, c.S, c.L, c.A) +} + // ////////////////////////////////////////////////////////////////////////////////// // // Parse parses color diff --git a/color/color_test.go b/color/color_test.go index c515c81f..7addb8c5 100644 --- a/color/color_test.go +++ b/color/color_test.go @@ -70,7 +70,8 @@ func (s *ColorSuite) TestRGB(c *C) { c.Assert(RGB{255, 255, 255}.ToHex().v, DeepEquals, uint32(0xFFFFFF)) c.Assert(RGB{127, 127, 127}.ToHex().v, DeepEquals, uint32(0x7F7F7F)) - c.Assert(RGB{23, 182, 89}.String(), Equals, "RGB{R:23 G:182 B:89}") + c.Assert(RGB{23, 182, 89}.String(), Equals, "23,182,89") + c.Assert(RGB{23, 182, 89}.GoString(), Equals, "RGB{R:23, G:182, B:89}") } func (s *ColorSuite) TestHex(c *C) { @@ -78,8 +79,8 @@ func (s *ColorSuite) TestHex(c *C) { c.Assert(NewHex(0xFFFFFF).ToRGB(), DeepEquals, RGB{0xFF, 0xFF, 0xFF}) c.Assert(NewHex(0x49d62d).ToRGB(), DeepEquals, RGB{0x49, 0xd6, 0x2d}) - c.Assert(NewHex(0x49d62d).String(), Equals, "Hex{#49D62D}") - c.Assert(NewHex(0x49d62df7).String(), Equals, "Hex{#49D62DF7}") + c.Assert(NewHex(0x49d62d).String(), Equals, "#49D62D") + c.Assert(NewHex(0x49d62df7).String(), Equals, "#49D62DF7") c.Assert(NewHex(0x49d62d).ToWeb(false, false), Equals, "#49d62d") c.Assert(NewHex(0x49d62df7).ToWeb(true, false), Equals, "#49D62DF7") c.Assert(NewHex(0x49d62df7).ToWeb(false, false), Equals, "#49d62df7") @@ -104,11 +105,13 @@ func (s *ColorSuite) TestRGBA(c *C) { c.Assert(NewHex(0xFFAABB).IsRGBA(), Equals, false) c.Assert(NewHex(0xFFAABB01).IsRGBA(), Equals, true) - c.Assert(RGBA{23, 182, 89, 130}.String(), Equals, "RGBA{R:23 G:182 B:89 A:0.51}") + c.Assert(RGBA{23, 182, 89, 130}.String(), Equals, "23,182,89,0.51") clr := RGBA{23, 182, 89, 0} - c.Assert(clr.String(), Equals, "RGBA{R:23 G:182 B:89 A:0.00}") - c.Assert(clr.WithAlpha(0.23).String(), Equals, "RGBA{R:23 G:182 B:89 A:0.23}") + c.Assert(clr.String(), Equals, "23,182,89,0.00") + c.Assert(clr.GoString(), Equals, "RGBA{R:23, G:182, B:89}") + c.Assert(clr.WithAlpha(0.23).String(), Equals, "23,182,89,0.23") + c.Assert(clr.WithAlpha(0.23).GoString(), Equals, "RGBA{R:23, G:182, B:89, A:58}") } func (s *ColorSuite) TestCMYK(c *C) { @@ -121,7 +124,8 @@ func (s *ColorSuite) TestCMYK(c *C) { c.Assert(CMYK{0.0, 0.0, 0.0, 1.0}.ToRGB(), DeepEquals, RGB{0, 0, 0}) c.Assert(CMYK{0.64, 0.77, 0, 0.17}.ToRGB(), DeepEquals, RGB{76, 48, 211}) - c.Assert(CMYK{0.64, 0.77, 0, 0.17}.String(), Equals, "CMYK{C:64% M:77% Y:0% K:17%}") + c.Assert(CMYK{0.64, 0.77, 0, 0.17}.String(), Equals, "64%,77%,0%,17%") + c.Assert(CMYK{0.64, 0.77, 0, 0.17}.GoString(), Equals, "CMYK{C:0.64, M:0.77, Y:0, K:0.17}") } func (s *ColorSuite) TestHSV(c *C) { @@ -143,8 +147,10 @@ func (s *ColorSuite) TestHSV(c *C) { c.Assert(HSV{0.32, 0.12, 0.76, 0.5}.ToRGBA(), DeepEquals, RGBA{172, 193, 170, 127}) - c.Assert(RGB{73, 158, 105}.ToHSV().String(), Equals, "HSV{H:143° S:54% V:62% A:0%}") - c.Assert(RGBA{73, 158, 105, 127}.ToHSV().String(), Equals, "HSV{H:143° S:54% V:62% A:50%}") + c.Assert(RGB{73, 158, 105}.ToHSV().String(), Equals, "143°,54%,62%,0%") + c.Assert(RGB{73, 158, 105}.ToHSV().GoString(), Equals, "HSV{H:0.396078431372549, S:0.5379746835443039, V:0.6196078431372549}") + c.Assert(RGBA{73, 158, 105, 127}.ToHSV().String(), Equals, "143°,54%,62%,50%") + c.Assert(RGBA{73, 158, 105, 127}.ToHSV().GoString(), Equals, "HSV{H:0.396078431372549, S:0.5379746835443039, V:0.6196078431372549, A:0.4980392156862745}") } func (s *ColorSuite) TestHSL(c *C) { @@ -160,8 +166,10 @@ func (s *ColorSuite) TestHSL(c *C) { c.Assert(HSL{0.6833333333333332, 0.7079646017699115, 0.5568627450980392, 0.0}.ToRGB(), DeepEquals, RGB{77, 62, 222}) c.Assert(HSL{0.6833333333333332, 0.7079646017699115, 0.5568627450980392, 0.50}.ToRGBA(), DeepEquals, RGBA{77, 62, 222, 127}) - c.Assert(RGB{146, 93, 176}.ToHSL().String(), Equals, "HSL{H:278° S:34% L:53% A:0%}") - c.Assert(RGBA{146, 93, 176, 80}.ToHSL().String(), Equals, "HSL{H:278° S:34% L:53% A:31%}") + c.Assert(RGB{146, 93, 176}.ToHSL().String(), Equals, "278°,34%,53%,0%") + c.Assert(RGB{146, 93, 176}.ToHSL().GoString(), Equals, "HSL{H:0.7730923694779116, S:0.34439834024896265, L:0.5274509803921569}") + c.Assert(RGBA{146, 93, 176, 80}.ToHSL().String(), Equals, "278°,34%,53%,31%") + c.Assert(RGBA{146, 93, 176, 80}.ToHSL().GoString(), Equals, "HSL{H:0.7730923694779116, S:0.34439834024896265, L:0.5274509803921569, A:0.3137254901960784}") } func (s *ColorSuite) TestHUE(c *C) { diff --git a/color/examples_test.go b/color/examples_test.go index 64442377..f87e7709 100644 --- a/color/examples_test.go +++ b/color/examples_test.go @@ -20,10 +20,10 @@ func ExampleParse() { fmt.Println(Parse("mintcream")) // Output: - // Hex{#FF6347} - // Hex{#BB88FF} - // Hex{#FF3B21A6} - // Hex{#F5FFFA} + // #FF6347 + // #BB88FF + // #FF3B21A6 + // #F5FFFA } func ExampleRGB2Hex() { @@ -33,15 +33,15 @@ func ExampleRGB2Hex() { } func ExampleHex2RGB() { - fmt.Printf("%s\n", Hex2RGB(NewHex(0x7F194B))) + fmt.Printf("%#v\n", Hex2RGB(NewHex(0x7F194B))) - // Output: RGB{R:127 G:25 B:75} + // Output: RGB{R:127, G:25, B:75} } func ExampleHex2RGBA() { - fmt.Printf("%s\n", Hex2RGBA(NewHex(0x7F194BCC))) + fmt.Printf("%#v\n", Hex2RGBA(NewHex(0x7F194BCC))) - // Output: RGBA{R:127 G:25 B:75 A:0.80} + // Output: RGBA{R:127, G:25, B:75, A:204} } func ExampleRGBA2Hex() { @@ -55,35 +55,35 @@ func ExampleRGBA2Hex() { func ExampleRGB2Term() { c := RGB{255, 0, 0} - fmt.Printf("%s → \\e[38;5;%dm\n", c, RGB2Term(c)) + fmt.Printf("%#v → \\e[38;5;%dm\n", c, RGB2Term(c)) - // Output: RGB{R:255 G:0 B:0} → \e[38;5;196m + // Output: RGB{R:255, G:0, B:0} → \e[38;5;196m } func ExampleTerm2RGB() { c := uint8(162) - fmt.Printf("%d → %s\n", c, Term2RGB(c)) + fmt.Printf("%d → %#v\n", c, Term2RGB(c)) - // Output: 162 → RGB{R:215 G:0 B:135} + // Output: 162 → RGB{R:215, G:0, B:135} } func ExampleRGB2CMYK() { fmt.Printf("%s\n", RGB2CMYK(RGB{127, 25, 75})) - // Output: CMYK{C:0% M:80% Y:41% K:50%} + // Output: 0%,80%,41%,50% } func ExampleCMYK2RGB() { fmt.Printf("%s\n", CMYK2RGB(CMYK{0, 0.8, 0.41, 0.5})) - // Output: RGB{R:127 G:25 B:75} + // Output: 127,25,75 } func ExampleRGB2HSV() { fmt.Printf("%s\n", RGB2HSV(RGB{127, 25, 75})) - // Output: HSV{H:331° S:80% V:50% A:0%} + // Output: 331°,80%,50%,0% } func ExampleHSV2RGB() { @@ -91,13 +91,13 @@ func ExampleHSV2RGB() { fmt.Printf("%s\n", c) - // Output: RGB{R:127 G:25 B:74} + // Output: 127,25,74 } func ExampleRGB2HSL() { fmt.Printf("%s\n", RGB2HSL(RGB{127, 25, 75})) - // Output: HSL{H:331° S:67% L:30% A:0%} + // Output: 331°,67%,30%,0% } func ExampleHSL2RGB() { @@ -105,7 +105,7 @@ func ExampleHSL2RGB() { fmt.Printf("%s\n", c) - // Output: RGB{R:127 G:25 B:74} + // Output: 127,25,74 } func ExampleHUE2RGB() { @@ -141,19 +141,19 @@ func ExampleRGB_ToHex() { func ExampleRGB_ToCMYK() { fmt.Printf("%s\n", RGB{127, 25, 75}.ToCMYK()) - // Output: CMYK{C:0% M:80% Y:41% K:50%} + // Output: 0%,80%,41%,50% } func ExampleRGB_ToHSV() { fmt.Printf("%s\n", RGB{127, 25, 75}.ToHSV()) - // Output: HSV{H:331° S:80% V:50% A:0%} + // Output: 331°,80%,50%,0% } func ExampleRGB_ToHSL() { fmt.Printf("%s\n", RGB{127, 25, 75}.ToHSL()) - // Output: HSL{H:331° S:67% L:30% A:0%} + // Output: 331°,67%,30%,0% } func ExampleRGB_ToTerm() { @@ -161,7 +161,7 @@ func ExampleRGB_ToTerm() { fmt.Printf("%s → \\e[38;5;%dm\n", c, c.ToTerm()) - // Output: RGB{R:255 G:0 B:0} → \e[38;5;196m + // Output: 255,0,0 → \e[38;5;196m } func ExampleRGBA_ToHex() { @@ -175,7 +175,7 @@ func ExampleRGBA_ToHex() { func ExampleCMYK_ToRGB() { fmt.Printf("%s\n", CMYK{0, 0.8, 0.41, 0.5}.ToRGB()) - // Output: RGB{R:127 G:25 B:75} + // Output: 127,25,75 } func ExampleHSV_ToRGB() { @@ -183,7 +183,7 @@ func ExampleHSV_ToRGB() { fmt.Printf("%s\n", c) - // Output: RGB{R:127 G:25 B:74} + // Output: 127,25,74 } func ExampleHSL_ToRGB() { @@ -191,7 +191,7 @@ func ExampleHSL_ToRGB() { fmt.Printf("%s\n", c) - // Output: RGB{R:127 G:25 B:74} + // Output: 127,25,74 } func ExampleHex_IsRGBA() { @@ -209,13 +209,13 @@ func ExampleHex_IsRGBA() { func ExampleHex_ToRGB() { fmt.Printf("%s\n", NewHex(0x7F194B).ToRGB()) - // Output: RGB{R:127 G:25 B:75} + // Output: 127,25,75 } func ExampleHex_ToRGBA() { fmt.Printf("%s\n", NewHex(0x7F194B5F).ToRGBA()) - // Output: RGBA{R:127 G:25 B:75 A:0.37} + // Output: 127,25,75,0.37 } func ExampleHex_ToWeb() { diff --git a/version.go b/version.go index 085c7f47..e319567e 100644 --- a/version.go +++ b/version.go @@ -8,4 +8,4 @@ package ek // ////////////////////////////////////////////////////////////////////////////////// // // VERSION is current ek package version -const VERSION = "13.14.2" +const VERSION = "13.14.3" From ffe4d6dbcea78fc52c50fee0da1732fd18c780cf Mon Sep 17 00:00:00 2001 From: Anton Novojilov Date: Tue, 10 Dec 2024 15:22:28 +0300 Subject: [PATCH 3/4] [req] Improved authentication support --- CHANGELOG.md | 4 ++- req/example_test.go | 13 ++++--- req/req.go | 35 +++++++++--------- req/req_test.go | 87 +++++++++++++++++++++++++++++++-------------- version.go | 2 +- 5 files changed, 87 insertions(+), 54 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 8a90260b..b2a95f36 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,8 +1,10 @@ ## Changelog -### [13.14.3](https://kaos.sh/ek/13.14.3) +### [13.15.0](https://kaos.sh/ek/13.15.0) - `[color]` Added `fmt.GoStringer` support for structs +- `[req]` Added more authentication methods (`OAuth`, `Digest`, `VAPID`, `AWS4`, `API Key`) +- `[req]` Added support of custom authentication methods - `[color]` Code refactoring ### [13.14.2](https://kaos.sh/ek/13.14.2) diff --git a/req/example_test.go b/req/example_test.go index 289c500e..392fb82c 100644 --- a/req/example_test.go +++ b/req/example_test.go @@ -110,13 +110,12 @@ func ExampleRequest_Post() { // send post request with basic auth resp, err := Request{ - URL: "https://my.domain.com", - Body: request, - Accept: CONTENT_TYPE_JSON, - ContentType: CONTENT_TYPE_JSON, - BasicAuthUsername: "someuser", - BasicAuthPassword: "somepass", - AutoDiscard: true, + URL: "https://my.domain.com", + Body: request, + Accept: CONTENT_TYPE_JSON, + ContentType: CONTENT_TYPE_JSON, + Auth: AuthBasic{"john", "test1234"}, + AutoDiscard: true, }.Post() if err != nil { diff --git a/req/req.go b/req/req.go index d30e9518..4e60b639 100644 --- a/req/req.go +++ b/req/req.go @@ -186,20 +186,19 @@ type Headers map[string]string // Request is basic struct type Request struct { - Method string // Request method - URL string // Request URL - Query Query // Map with query params - Body any // Request body - Headers Headers // Map with headers - ContentType string // Content type header - Accept string // Accept header - BasicAuthUsername string // Basic auth username - BasicAuthPassword string // Basic auth password - BearerAuth string // Bearer auth token - Timeout time.Duration // Request timeout - AutoDiscard bool // Automatically discard all responses with status code > 299 - FollowRedirect bool // Follow redirect - Close bool // Close indicates whether to close the connection after sending request + Method string // Request method + URL string // Request URL + Query Query // Map with query params + Auth Auth // Authentication data + ProxyAuth Auth // Proxy authentication data + Body any // Request body + Headers Headers // Map with headers + ContentType string // Content type header + Accept string // Accept header + Timeout time.Duration // Request timeout + AutoDiscard bool // Automatically discard all responses with status code > 299 + FollowRedirect bool // Follow redirect + Close bool // Close indicates whether to close the connection after sending request } // Response is struct contains response data and properties @@ -675,12 +674,12 @@ func createRequest(e *Engine, r Request, bodyReader io.Reader) (*http.Request, c req.Header.Add("User-Agent", e.UserAgent) } - if r.BasicAuthUsername != "" && r.BasicAuthPassword != "" { - req.SetBasicAuth(r.BasicAuthUsername, r.BasicAuthPassword) + if r.Auth != nil { + r.Auth.Apply(req, "Authorization") } - if r.BearerAuth != "" { - req.Header.Add("Authorization", "Bearer "+r.BearerAuth) + if r.ProxyAuth != nil { + r.ProxyAuth.Apply(req, "Proxy-Authorization") } if r.Close { diff --git a/req/req_test.go b/req/req_test.go index ae57855d..24aef987 100644 --- a/req/req_test.go +++ b/req/req_test.go @@ -40,7 +40,6 @@ const ( _URL_ACCEPT = "/accept" _URL_USER_AGENT = "/user-agent" _URL_BASIC_AUTH = "/basic-auth" - _URL_BEARER = "/bearer" _URL_STRING_RESP = "/string-response" _URL_JSON_RESP = "/json-response" _URL_DISCARD = "/discard" @@ -52,7 +51,6 @@ const ( _TEST_ACCEPT = "application/vnd.example.api+json;version=2" _TEST_BASIC_AUTH_USER = "admin" _TEST_BASIC_AUTH_PASS = "password" - _TEST_BEARER_TOKEN = "XUWjA4EnRqUNyqmz" _TEST_STRING_RESP = "Test String Response" ) @@ -324,19 +322,9 @@ func (s *ReqSuite) TestUserAgent(c *C) { func (s *ReqSuite) TestBasicAuth(c *C) { resp, err := Request{ - URL: s.url + _URL_BASIC_AUTH, - BasicAuthUsername: _TEST_BASIC_AUTH_USER, - BasicAuthPassword: _TEST_BASIC_AUTH_PASS, - }.Do() - - c.Assert(err, IsNil) - c.Assert(resp.StatusCode, Equals, 200) -} - -func (s *ReqSuite) TestBearerAuth(c *C) { - resp, err := Request{ - URL: s.url + _URL_BEARER, - BearerAuth: _TEST_BEARER_TOKEN, + URL: s.url + _URL_BASIC_AUTH, + Auth: AuthBasic{_TEST_BASIC_AUTH_USER, _TEST_BASIC_AUTH_PASS}, + ProxyAuth: AuthBasic{_TEST_BASIC_AUTH_USER, _TEST_BASIC_AUTH_PASS}, }.Do() c.Assert(err, IsNil) @@ -660,6 +648,63 @@ func (s *ReqSuite) TestNil(c *C) { c.Assert(r.String(), Equals, "") } +func (s *ReqSuite) TestAuth(c *C) { + var a Auth + + r, _ := http.NewRequest("GET", "http://127.0.0.1", nil) + + a = AuthBasic{"John", "Test1234"} + a.Apply(r, "Authorization") + c.Assert(r.Header.Get("Authorization"), Equals, "Basic Sm9objpUZXN0MTIzNA==") + + a = AuthBearer{"acbd1234"} + a.Apply(r, "Authorization") + c.Assert(r.Header.Get("Authorization"), Equals, "Bearer acbd1234") + + a = AuthOAuth{ + Realm: "Example", + ConsumerKey: "0685bd9184jfhq22", + Token: "ad180jjd733klru7", + SignatureMethod: "HMAC-SHA1", + Signature: "wOJIO9A2W5mFwDgiDvZbTSMK", + Timestamp: 137131200, + Nonce: "4572616e48616d6d65724c61686176", + Version: "1.0", + } + a.Apply(r, "Authorization") + c.Assert(r.Header.Get("Authorization"), Equals, `OAuth realm="Example", oauth_consumer_key="0685bd9184jfhq22", oauth_token="ad180jjd733klru7", oauth_signature_method="HMAC-SHA1", oauth_signature="wOJIO9A2W5mFwDgiDvZbTSMK", oauth_timestamp="137131200", oauth_nonce="4572616e48616d6d65724c61686176", oauth_version="1.0"`) + + a = AuthDigest{ + Username: "Mufasa", + Realm: "http-auth@example.org", + URI: "/dir/index.html", + Algorithm: "SHA-256", + Nonce: "7ypf/xlj9XXwfDPEoM4URrv/xwf94BcCAzFZH4GiTo0v", + CNonce: "f2/wE4q74E6zIJEtWaHKaf5wv/H5QzzpXusqGemxURZJ", + NC: 1, + QOP: "auth", + Response: "8ca523f5e9506fed4657c9700eebdbec", + Opaque: "FQhe/qaU925kfnzjCev0ciny7QMkPqMAFRtzCUYo5tdS", + UserHash: true, + } + a.Apply(r, "Authorization") + c.Assert(r.Header.Get("Authorization"), Equals, `Digest username="Mufasa", realm="http-auth@example.org", uri="/dir/index.html", algorithm=SHA-256, nonce="7ypf/xlj9XXwfDPEoM4URrv/xwf94BcCAzFZH4GiTo0v", cnonce="f2/wE4q74E6zIJEtWaHKaf5wv/H5QzzpXusqGemxURZJ", nc=00000001, qop=auth, response="8ca523f5e9506fed4657c9700eebdbec", opaque="FQhe/qaU925kfnzjCev0ciny7QMkPqMAFRtzCUYo5tdS", userhash=true`) + + a = AuthAWS4{ + Credential: "AKIAIOSFODNN7EXAMPLE/20130524/us-east-1/s3/aws4_request", + SignedHeaders: "host;range;x-amz-date", + Signature: "fe5f80f77d5fa3beca038a248ff027d0445342fe2855ddc963176630326f1024", + } + a.Apply(r, "Authorization") + c.Assert(r.Header.Get("Authorization"), Equals, `AWS4-HMAC-SHA256 Credential=AKIAIOSFODNN7EXAMPLE/20130524/us-east-1/s3/aws4_request,SignedHeaders=host;range;x-amz-date,Signature=fe5f80f77d5fa3beca038a248ff027d0445342fe2855ddc963176630326f1024`) + + r, _ = http.NewRequest("GET", "http://127.0.0.1", nil) + a = AuthAPIKey{Key: "fe5f80f77d5fa3beca038a248ff027d0"} + a.Apply(r, "Authorization") + c.Assert(r.Header.Get("X-API-Key"), Equals, `fe5f80f77d5fa3beca038a248ff027d0`) + c.Assert(r.Header.Get("API-Key"), Equals, `fe5f80f77d5fa3beca038a248ff027d0`) +} + func (s *ReqSuite) TestQuery(c *C) { resp, err := Request{ URL: s.url + _URL_QUERY, @@ -888,7 +933,6 @@ func runHTTPServer(s *ReqSuite, c *C) { server.Handler.(*http.ServeMux).HandleFunc(_URL_ACCEPT, acceptRequestHandler) server.Handler.(*http.ServeMux).HandleFunc(_URL_USER_AGENT, uaRequestHandler) server.Handler.(*http.ServeMux).HandleFunc(_URL_BASIC_AUTH, basicAuthRequestHandler) - server.Handler.(*http.ServeMux).HandleFunc(_URL_BEARER, bearerRequestHandler) server.Handler.(*http.ServeMux).HandleFunc(_URL_STRING_RESP, stringRespRequestHandler) server.Handler.(*http.ServeMux).HandleFunc(_URL_JSON_RESP, jsonRespRequestHandler) server.Handler.(*http.ServeMux).HandleFunc(_URL_DISCARD, discardRequestHandler) @@ -1085,17 +1129,6 @@ func basicAuthRequestHandler(w http.ResponseWriter, r *http.Request) { w.WriteHeader(200) } -func bearerRequestHandler(w http.ResponseWriter, r *http.Request) { - header := r.Header.Get("Authorization") - - if header != "Bearer "+_TEST_BEARER_TOKEN { - w.WriteHeader(960) - return - } - - w.WriteHeader(200) -} - func stringRespRequestHandler(w http.ResponseWriter, r *http.Request) { w.Write([]byte(_TEST_STRING_RESP)) } diff --git a/version.go b/version.go index e319567e..25ee0447 100644 --- a/version.go +++ b/version.go @@ -8,4 +8,4 @@ package ek // ////////////////////////////////////////////////////////////////////////////////// // // VERSION is current ek package version -const VERSION = "13.14.3" +const VERSION = "13.15.0" From 9336e9fc1b395f156df79c7e21c98c710da9cb0b Mon Sep 17 00:00:00 2001 From: Anton Novojilov Date: Tue, 10 Dec 2024 15:22:38 +0300 Subject: [PATCH 4/4] [req] Improved authentication support --- req/auth.go | 220 ++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 220 insertions(+) create mode 100644 req/auth.go diff --git a/req/auth.go b/req/auth.go new file mode 100644 index 00000000..2b02861a --- /dev/null +++ b/req/auth.go @@ -0,0 +1,220 @@ +package req + +// ////////////////////////////////////////////////////////////////////////////////// // +// // +// Copyright (c) 2024 ESSENTIAL KAOS // +// Apache License, Version 2.0 // +// // +// ////////////////////////////////////////////////////////////////////////////////// // + +import ( + "bytes" + "encoding/base64" + "fmt" + "net/http" +) + +// ////////////////////////////////////////////////////////////////////////////////// // + +// Auth is interface for authentication method +type Auth interface { + // Apply sets authentication data for given request + Apply(r *http.Request, header string) +} + +// ////////////////////////////////////////////////////////////////////////////////// // + +// AuthBasic is auth using username and password (RFC 7617) +// +// https://datatracker.ietf.org/doc/html/rfc7617 +type AuthBasic struct { + Username string + Password string +} + +// AuthOAuth is auth using Bearer token (RFC 6750) +// +// https://datatracker.ietf.org/doc/html/rfc6750 +type AuthBearer struct { + Token string +} + +// AuthOAuth is auth using OAuth token +// +// https://www.rfc-editor.org/rfc/rfc5849.html#section-3.5.1 +type AuthOAuth struct { + Realm string + ConsumerKey string + Token string + SignatureMethod string + Signature string + Nonce string + Version string + Timestamp int64 +} + +// AuthDigest is auth using Digest Auth (RFC 7616) +// +// https://datatracker.ietf.org/doc/html/rfc7616 +type AuthDigest struct { + Username string + Realm string + URI string + Algorithm string + Nonce string + CNonce string + NC uint + QOP string + Response string + Opaque string + UserHash bool +} + +// AuthVAPID s auth using Voluntary Application Server Identification (RFC 8292) +// +// https://datatracker.ietf.org/doc/html/rfc8292 +type AuthVAPID struct { + Credential string + SignedHeaders string + Signature string +} + +// AuthAWS4 is auth using AWS Signature Version 4 +// +// https://docs.aws.amazon.com/AmazonS3/latest/API/sigv4-auth-using-authorization-header.html +type AuthAWS4 struct { + Credential string + SignedHeaders string + Signature string +} + +// AuthAPIKey is auth using X-API-Key/API-Key header +type AuthAPIKey struct { + Key string +} + +// ////////////////////////////////////////////////////////////////////////////////// // + +// Apply sets authentication data for given request +func (a AuthBasic) Apply(r *http.Request, header string) { + r.Header.Set(header, "Basic "+base64.StdEncoding.EncodeToString( + []byte(a.Username+":"+a.Password), + )) +} + +// Apply sets authentication data for given request +func (a AuthBearer) Apply(r *http.Request, header string) { + r.Header.Set(header, "Bearer "+a.Token) +} + +// Apply sets authentication data for given request +func (a AuthOAuth) Apply(r *http.Request, header string) { + var buf bytes.Buffer + + buf.WriteString("OAuth ") + + if a.Realm != "" { + fmt.Fprintf(&buf, "realm=%q, ", a.Realm) + } + + if a.ConsumerKey != "" { + fmt.Fprintf(&buf, "oauth_consumer_key=%q, ", a.ConsumerKey) + } + + if a.Token != "" { + fmt.Fprintf(&buf, "oauth_token=%q, ", a.Token) + } + + if a.SignatureMethod != "" { + fmt.Fprintf(&buf, "oauth_signature_method=%q, ", a.SignatureMethod) + } + + if a.Signature != "" { + fmt.Fprintf(&buf, "oauth_signature=%q, ", a.Signature) + } + + fmt.Fprintf(&buf, "oauth_timestamp=\"%d\", ", a.Timestamp) + + if a.Nonce != "" { + fmt.Fprintf(&buf, "oauth_nonce=%q, ", a.Nonce) + } + + if a.Version != "" { + fmt.Fprintf(&buf, "oauth_version=%q, ", a.Version) + } + + if buf.Len() > 2 { + buf.Truncate(buf.Len() - 2) + } + + r.Header.Set(header, buf.String()) +} + +// Apply sets authentication data for given request +func (a AuthDigest) Apply(r *http.Request, header string) { + var buf bytes.Buffer + + buf.WriteString("Digest ") + + if a.Username != "" { + fmt.Fprintf(&buf, "username=%q, ", a.Username) + } + + if a.Realm != "" { + fmt.Fprintf(&buf, "realm=%q, ", a.Realm) + } + + if a.URI != "" { + fmt.Fprintf(&buf, "uri=%q, ", a.URI) + } + + if a.Algorithm != "" { + fmt.Fprintf(&buf, "algorithm=%s, ", a.Algorithm) + } + + if a.Nonce != "" { + fmt.Fprintf(&buf, "nonce=%q, ", a.Nonce) + } + + if a.CNonce != "" { + fmt.Fprintf(&buf, "cnonce=%q, ", a.CNonce) + } + + fmt.Fprintf(&buf, "nc=%08d, ", a.NC) + + if a.QOP != "" { + fmt.Fprintf(&buf, "qop=%s, ", a.QOP) + } + + if a.Response != "" { + fmt.Fprintf(&buf, "response=%q, ", a.Response) + } + + if a.Opaque != "" { + fmt.Fprintf(&buf, "opaque=%q, ", a.Opaque) + } + + if a.UserHash { + fmt.Fprint(&buf, "userhash=true, ") + } + + if buf.Len() > 2 { + buf.Truncate(buf.Len() - 2) + } + + r.Header.Set(header, buf.String()) +} + +// Apply sets authentication data for given request +func (a AuthAWS4) Apply(r *http.Request, header string) { + r.Header.Set("Authorization", fmt.Sprintf( + "AWS4-HMAC-SHA256 Credential=%s,SignedHeaders=%s,Signature=%s", + a.Credential, a.SignedHeaders, a.Signature, + )) +} + +// Apply sets authentication data for given request +func (a AuthAPIKey) Apply(r *http.Request, header string) { + r.Header.Set("X-API-Key", a.Key) + r.Header.Set("API-Key", a.Key) +}