parent
326f0cfa2f
commit
5c292c61c6
1437 changed files with 208886 additions and 87131 deletions
51
vendor/github.com/Azure/azure-sdk-for-go/sdk/azcore/CHANGELOG.md
generated
vendored
51
vendor/github.com/Azure/azure-sdk-for-go/sdk/azcore/CHANGELOG.md
generated
vendored
|
|
@ -1,5 +1,56 @@
|
|||
# Release History
|
||||
|
||||
## 1.6.0 (2023-05-04)
|
||||
|
||||
### Features Added
|
||||
* Added support for ARM cross-tenant authentication. Set the `AuxiliaryTenants` field of `arm.ClientOptions` to enable.
|
||||
* Added `TenantID` field to `policy.TokenRequestOptions`.
|
||||
|
||||
## 1.5.0 (2023-04-06)
|
||||
|
||||
### Features Added
|
||||
* Added `ShouldRetry` to `policy.RetryOptions` for finer-grained control over when to retry.
|
||||
|
||||
### Breaking Changes
|
||||
> These changes affect only code written against a beta version such as v1.5.0-beta.1
|
||||
> These features will return in v1.6.0-beta.1.
|
||||
* Removed `TokenRequestOptions.Claims` and `.TenantID`
|
||||
* Removed ARM client support for CAE and cross-tenant auth.
|
||||
|
||||
### Bugs Fixed
|
||||
* Added non-conformant LRO terminal states `Cancelled` and `Completed`.
|
||||
|
||||
### Other Changes
|
||||
* Updated to latest `internal` module.
|
||||
|
||||
## 1.5.0-beta.1 (2023-03-02)
|
||||
|
||||
### Features Added
|
||||
* This release includes the features added in v1.4.0-beta.1
|
||||
|
||||
## 1.4.0 (2023-03-02)
|
||||
> This release doesn't include features added in v1.4.0-beta.1. They will return in v1.5.0-beta.1.
|
||||
|
||||
### Features Added
|
||||
* Add `Clone()` method for `arm/policy.ClientOptions`.
|
||||
|
||||
### Bugs Fixed
|
||||
* ARM's RP registration policy will no longer swallow unrecognized errors.
|
||||
* Fixed an issue in `runtime.NewPollerFromResumeToken()` when resuming a `Poller` with a custom `PollingHandler`.
|
||||
* Fixed wrong policy copy in `arm/runtime.NewPipeline()`.
|
||||
|
||||
## 1.4.0-beta.1 (2023-02-02)
|
||||
|
||||
### Features Added
|
||||
* Added support for ARM cross-tenant authentication. Set the `AuxiliaryTenants` field of `arm.ClientOptions` to enable.
|
||||
* Added `Claims` and `TenantID` fields to `policy.TokenRequestOptions`.
|
||||
* ARM bearer token policy handles CAE challenges.
|
||||
|
||||
## 1.3.1 (2023-02-02)
|
||||
|
||||
### Other Changes
|
||||
* Update dependencies to latest versions.
|
||||
|
||||
## 1.3.0 (2023-01-06)
|
||||
|
||||
### Features Added
|
||||
|
|
|
|||
24
vendor/github.com/Azure/azure-sdk-for-go/sdk/azcore/internal/exported/exported.go
generated
vendored
24
vendor/github.com/Azure/azure-sdk-for-go/sdk/azcore/internal/exported/exported.go
generated
vendored
|
|
@ -11,8 +11,6 @@ import (
|
|||
"io"
|
||||
"net/http"
|
||||
"time"
|
||||
|
||||
"github.com/Azure/azure-sdk-for-go/sdk/azcore/internal/shared"
|
||||
)
|
||||
|
||||
type nopCloser struct {
|
||||
|
|
@ -43,24 +41,6 @@ func HasStatusCode(resp *http.Response, statusCodes ...int) bool {
|
|||
return false
|
||||
}
|
||||
|
||||
// Payload reads and returns the response body or an error.
|
||||
// On a successful read, the response body is cached.
|
||||
// Subsequent reads will access the cached value.
|
||||
// Exported as runtime.Payload().
|
||||
func Payload(resp *http.Response) ([]byte, error) {
|
||||
// r.Body won't be a nopClosingBytesReader if downloading was skipped
|
||||
if buf, ok := resp.Body.(*shared.NopClosingBytesReader); ok {
|
||||
return buf.Bytes(), nil
|
||||
}
|
||||
bytesBody, err := io.ReadAll(resp.Body)
|
||||
resp.Body.Close()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
resp.Body = shared.NewNopClosingBytesReader(bytesBody)
|
||||
return bytesBody, nil
|
||||
}
|
||||
|
||||
// AccessToken represents an Azure service bearer access token with expiry information.
|
||||
// Exported as azcore.AccessToken.
|
||||
type AccessToken struct {
|
||||
|
|
@ -73,6 +53,10 @@ type AccessToken struct {
|
|||
type TokenRequestOptions struct {
|
||||
// Scopes contains the list of permission scopes required for the token.
|
||||
Scopes []string
|
||||
|
||||
// TenantID identifies the tenant from which to request the token. azidentity credentials authenticate in
|
||||
// their configured default tenants when this field isn't set.
|
||||
TenantID string
|
||||
}
|
||||
|
||||
// TokenCredential represents a credential capable of providing an OAuth token.
|
||||
|
|
|
|||
12
vendor/github.com/Azure/azure-sdk-for-go/sdk/azcore/internal/exported/request.go
generated
vendored
12
vendor/github.com/Azure/azure-sdk-for-go/sdk/azcore/internal/exported/request.go
generated
vendored
|
|
@ -103,6 +103,7 @@ func (req *Request) OperationValue(value interface{}) bool {
|
|||
// SetBody sets the specified ReadSeekCloser as the HTTP request body, and sets Content-Type and Content-Length
|
||||
// accordingly. If the ReadSeekCloser is nil or empty, Content-Length won't be set. If contentType is "",
|
||||
// Content-Type won't be set.
|
||||
// Use streaming.NopCloser to turn an io.ReadSeeker into an io.ReadSeekCloser.
|
||||
func (req *Request) SetBody(body io.ReadSeekCloser, contentType string) error {
|
||||
var err error
|
||||
var size int64
|
||||
|
|
@ -168,3 +169,14 @@ func (req *Request) Clone(ctx context.Context) *Request {
|
|||
r2.req = req.req.Clone(ctx)
|
||||
return &r2
|
||||
}
|
||||
|
||||
// not exported but dependent on Request
|
||||
|
||||
// PolicyFunc is a type that implements the Policy interface.
|
||||
// Use this type when implementing a stateless policy as a first-class function.
|
||||
type PolicyFunc func(*Request) (*http.Response, error)
|
||||
|
||||
// Do implements the Policy interface on policyFunc.
|
||||
func (pf PolicyFunc) Do(req *Request) (*http.Response, error) {
|
||||
return pf(req)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -12,6 +12,8 @@ import (
|
|||
"fmt"
|
||||
"net/http"
|
||||
"regexp"
|
||||
|
||||
"github.com/Azure/azure-sdk-for-go/sdk/internal/exported"
|
||||
)
|
||||
|
||||
// NewResponseError creates a new *ResponseError from the provided HTTP response.
|
||||
|
|
@ -29,7 +31,7 @@ func NewResponseError(resp *http.Response) error {
|
|||
}
|
||||
|
||||
// if we didn't get x-ms-error-code, check in the response body
|
||||
body, err := Payload(resp)
|
||||
body, err := exported.Payload(resp, nil)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
|
@ -121,7 +123,7 @@ func (e *ResponseError) Error() string {
|
|||
fmt.Fprintln(msg, "ERROR CODE UNAVAILABLE")
|
||||
}
|
||||
fmt.Fprintln(msg, "--------------------------------------------------------------------------------")
|
||||
body, err := Payload(e.RawResponse)
|
||||
body, err := exported.Payload(e.RawResponse, nil)
|
||||
if err != nil {
|
||||
// this really shouldn't fail at this point as the response
|
||||
// body is already cached (it was read in NewResponseError)
|
||||
|
|
|
|||
17
vendor/github.com/Azure/azure-sdk-for-go/sdk/azcore/internal/pollers/async/async.go
generated
vendored
17
vendor/github.com/Azure/azure-sdk-for-go/sdk/azcore/internal/pollers/async/async.go
generated
vendored
|
|
@ -16,6 +16,7 @@ import (
|
|||
"github.com/Azure/azure-sdk-for-go/sdk/azcore/internal/log"
|
||||
"github.com/Azure/azure-sdk-for-go/sdk/azcore/internal/pollers"
|
||||
"github.com/Azure/azure-sdk-for-go/sdk/azcore/internal/shared"
|
||||
"github.com/Azure/azure-sdk-for-go/sdk/internal/poller"
|
||||
)
|
||||
|
||||
// see https://github.com/Azure/azure-resource-manager-rpc/blob/master/v1.0/async-api-reference.md
|
||||
|
|
@ -68,15 +69,15 @@ func New[T any](pl exported.Pipeline, resp *http.Response, finalState pollers.Fi
|
|||
if asyncURL == "" {
|
||||
return nil, errors.New("response is missing Azure-AsyncOperation header")
|
||||
}
|
||||
if !pollers.IsValidURL(asyncURL) {
|
||||
if !poller.IsValidURL(asyncURL) {
|
||||
return nil, fmt.Errorf("invalid polling URL %s", asyncURL)
|
||||
}
|
||||
// check for provisioning state. if the operation is a RELO
|
||||
// and terminates synchronously this will prevent extra polling.
|
||||
// it's ok if there's no provisioning state.
|
||||
state, _ := pollers.GetProvisioningState(resp)
|
||||
state, _ := poller.GetProvisioningState(resp)
|
||||
if state == "" {
|
||||
state = pollers.StatusInProgress
|
||||
state = poller.StatusInProgress
|
||||
}
|
||||
p := &Poller[T]{
|
||||
pl: pl,
|
||||
|
|
@ -93,17 +94,17 @@ func New[T any](pl exported.Pipeline, resp *http.Response, finalState pollers.Fi
|
|||
|
||||
// Done returns true if the LRO is in a terminal state.
|
||||
func (p *Poller[T]) Done() bool {
|
||||
return pollers.IsTerminalState(p.CurState)
|
||||
return poller.IsTerminalState(p.CurState)
|
||||
}
|
||||
|
||||
// Poll retrieves the current state of the LRO.
|
||||
func (p *Poller[T]) Poll(ctx context.Context) (*http.Response, error) {
|
||||
err := pollers.PollHelper(ctx, p.AsyncURL, p.pl, func(resp *http.Response) (string, error) {
|
||||
if !pollers.StatusCodeValid(resp) {
|
||||
if !poller.StatusCodeValid(resp) {
|
||||
p.resp = resp
|
||||
return "", exported.NewResponseError(resp)
|
||||
}
|
||||
state, err := pollers.GetStatus(resp)
|
||||
state, err := poller.GetStatus(resp)
|
||||
if err != nil {
|
||||
return "", err
|
||||
} else if state == "" {
|
||||
|
|
@ -122,7 +123,7 @@ func (p *Poller[T]) Poll(ctx context.Context) (*http.Response, error) {
|
|||
func (p *Poller[T]) Result(ctx context.Context, out *T) error {
|
||||
if p.resp.StatusCode == http.StatusNoContent {
|
||||
return nil
|
||||
} else if pollers.Failed(p.CurState) {
|
||||
} else if poller.Failed(p.CurState) {
|
||||
return exported.NewResponseError(p.resp)
|
||||
}
|
||||
var req *exported.Request
|
||||
|
|
@ -154,5 +155,5 @@ func (p *Poller[T]) Result(ctx context.Context, out *T) error {
|
|||
p.resp = resp
|
||||
}
|
||||
|
||||
return pollers.ResultHelper(p.resp, pollers.Failed(p.CurState), out)
|
||||
return pollers.ResultHelper(p.resp, poller.Failed(p.CurState), out)
|
||||
}
|
||||
|
|
|
|||
25
vendor/github.com/Azure/azure-sdk-for-go/sdk/azcore/internal/pollers/body/body.go
generated
vendored
25
vendor/github.com/Azure/azure-sdk-for-go/sdk/azcore/internal/pollers/body/body.go
generated
vendored
|
|
@ -14,6 +14,7 @@ import (
|
|||
"github.com/Azure/azure-sdk-for-go/sdk/azcore/internal/exported"
|
||||
"github.com/Azure/azure-sdk-for-go/sdk/azcore/internal/log"
|
||||
"github.com/Azure/azure-sdk-for-go/sdk/azcore/internal/pollers"
|
||||
"github.com/Azure/azure-sdk-for-go/sdk/internal/poller"
|
||||
)
|
||||
|
||||
// Kind is the identifier of this type in a resume token.
|
||||
|
|
@ -72,9 +73,9 @@ func New[T any](pl exported.Pipeline, resp *http.Response) (*Poller[T], error) {
|
|||
}
|
||||
// default initial state to InProgress. depending on the HTTP
|
||||
// status code and provisioning state, we might change the value.
|
||||
curState := pollers.StatusInProgress
|
||||
provState, err := pollers.GetProvisioningState(resp)
|
||||
if err != nil && !errors.Is(err, pollers.ErrNoBody) {
|
||||
curState := poller.StatusInProgress
|
||||
provState, err := poller.GetProvisioningState(resp)
|
||||
if err != nil && !errors.Is(err, poller.ErrNoBody) {
|
||||
return nil, err
|
||||
}
|
||||
if resp.StatusCode == http.StatusCreated && provState != "" {
|
||||
|
|
@ -85,37 +86,37 @@ func New[T any](pl exported.Pipeline, resp *http.Response) (*Poller[T], error) {
|
|||
curState = provState
|
||||
} else if provState == "" {
|
||||
// for a 200, absense of provisioning state indicates success
|
||||
curState = pollers.StatusSucceeded
|
||||
curState = poller.StatusSucceeded
|
||||
}
|
||||
} else if resp.StatusCode == http.StatusNoContent {
|
||||
curState = pollers.StatusSucceeded
|
||||
curState = poller.StatusSucceeded
|
||||
}
|
||||
p.CurState = curState
|
||||
return p, nil
|
||||
}
|
||||
|
||||
func (p *Poller[T]) Done() bool {
|
||||
return pollers.IsTerminalState(p.CurState)
|
||||
return poller.IsTerminalState(p.CurState)
|
||||
}
|
||||
|
||||
func (p *Poller[T]) Poll(ctx context.Context) (*http.Response, error) {
|
||||
err := pollers.PollHelper(ctx, p.PollURL, p.pl, func(resp *http.Response) (string, error) {
|
||||
if !pollers.StatusCodeValid(resp) {
|
||||
if !poller.StatusCodeValid(resp) {
|
||||
p.resp = resp
|
||||
return "", exported.NewResponseError(resp)
|
||||
}
|
||||
if resp.StatusCode == http.StatusNoContent {
|
||||
p.resp = resp
|
||||
p.CurState = pollers.StatusSucceeded
|
||||
p.CurState = poller.StatusSucceeded
|
||||
return p.CurState, nil
|
||||
}
|
||||
state, err := pollers.GetProvisioningState(resp)
|
||||
if errors.Is(err, pollers.ErrNoBody) {
|
||||
state, err := poller.GetProvisioningState(resp)
|
||||
if errors.Is(err, poller.ErrNoBody) {
|
||||
// a missing response body in non-204 case is an error
|
||||
return "", err
|
||||
} else if state == "" {
|
||||
// a response body without provisioning state is considered terminal success
|
||||
state = pollers.StatusSucceeded
|
||||
state = poller.StatusSucceeded
|
||||
} else if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
|
@ -130,5 +131,5 @@ func (p *Poller[T]) Poll(ctx context.Context) (*http.Response, error) {
|
|||
}
|
||||
|
||||
func (p *Poller[T]) Result(ctx context.Context, out *T) error {
|
||||
return pollers.ResultHelper(p.resp, pollers.Failed(p.CurState), out)
|
||||
return pollers.ResultHelper(p.resp, poller.Failed(p.CurState), out)
|
||||
}
|
||||
|
|
|
|||
19
vendor/github.com/Azure/azure-sdk-for-go/sdk/azcore/internal/pollers/loc/loc.go
generated
vendored
19
vendor/github.com/Azure/azure-sdk-for-go/sdk/azcore/internal/pollers/loc/loc.go
generated
vendored
|
|
@ -16,6 +16,7 @@ import (
|
|||
"github.com/Azure/azure-sdk-for-go/sdk/azcore/internal/log"
|
||||
"github.com/Azure/azure-sdk-for-go/sdk/azcore/internal/pollers"
|
||||
"github.com/Azure/azure-sdk-for-go/sdk/azcore/internal/shared"
|
||||
"github.com/Azure/azure-sdk-for-go/sdk/internal/poller"
|
||||
)
|
||||
|
||||
// Kind is the identifier of this type in a resume token.
|
||||
|
|
@ -61,15 +62,15 @@ func New[T any](pl exported.Pipeline, resp *http.Response) (*Poller[T], error) {
|
|||
if locURL == "" {
|
||||
return nil, errors.New("response is missing Location header")
|
||||
}
|
||||
if !pollers.IsValidURL(locURL) {
|
||||
if !poller.IsValidURL(locURL) {
|
||||
return nil, fmt.Errorf("invalid polling URL %s", locURL)
|
||||
}
|
||||
// check for provisioning state. if the operation is a RELO
|
||||
// and terminates synchronously this will prevent extra polling.
|
||||
// it's ok if there's no provisioning state.
|
||||
state, _ := pollers.GetProvisioningState(resp)
|
||||
state, _ := poller.GetProvisioningState(resp)
|
||||
if state == "" {
|
||||
state = pollers.StatusInProgress
|
||||
state = poller.StatusInProgress
|
||||
}
|
||||
return &Poller[T]{
|
||||
pl: pl,
|
||||
|
|
@ -81,7 +82,7 @@ func New[T any](pl exported.Pipeline, resp *http.Response) (*Poller[T], error) {
|
|||
}
|
||||
|
||||
func (p *Poller[T]) Done() bool {
|
||||
return pollers.IsTerminalState(p.CurState)
|
||||
return poller.IsTerminalState(p.CurState)
|
||||
}
|
||||
|
||||
func (p *Poller[T]) Poll(ctx context.Context) (*http.Response, error) {
|
||||
|
|
@ -93,17 +94,17 @@ func (p *Poller[T]) Poll(ctx context.Context) (*http.Response, error) {
|
|||
// if provisioning state is available, use that. this is only
|
||||
// for some ARM LRO scenarios (e.g. DELETE with a Location header)
|
||||
// so if it's missing then use HTTP status code.
|
||||
provState, _ := pollers.GetProvisioningState(resp)
|
||||
provState, _ := poller.GetProvisioningState(resp)
|
||||
p.resp = resp
|
||||
if provState != "" {
|
||||
p.CurState = provState
|
||||
} else if resp.StatusCode == http.StatusAccepted {
|
||||
p.CurState = pollers.StatusInProgress
|
||||
p.CurState = poller.StatusInProgress
|
||||
} else if resp.StatusCode > 199 && resp.StatusCode < 300 {
|
||||
// any 2xx other than a 202 indicates success
|
||||
p.CurState = pollers.StatusSucceeded
|
||||
p.CurState = poller.StatusSucceeded
|
||||
} else {
|
||||
p.CurState = pollers.StatusFailed
|
||||
p.CurState = poller.StatusFailed
|
||||
}
|
||||
return p.CurState, nil
|
||||
})
|
||||
|
|
@ -114,5 +115,5 @@ func (p *Poller[T]) Poll(ctx context.Context) (*http.Response, error) {
|
|||
}
|
||||
|
||||
func (p *Poller[T]) Result(ctx context.Context, out *T) error {
|
||||
return pollers.ResultHelper(p.resp, pollers.Failed(p.CurState), out)
|
||||
return pollers.ResultHelper(p.resp, poller.Failed(p.CurState), out)
|
||||
}
|
||||
|
|
|
|||
21
vendor/github.com/Azure/azure-sdk-for-go/sdk/azcore/internal/pollers/op/op.go
generated
vendored
21
vendor/github.com/Azure/azure-sdk-for-go/sdk/azcore/internal/pollers/op/op.go
generated
vendored
|
|
@ -16,6 +16,7 @@ import (
|
|||
"github.com/Azure/azure-sdk-for-go/sdk/azcore/internal/log"
|
||||
"github.com/Azure/azure-sdk-for-go/sdk/azcore/internal/pollers"
|
||||
"github.com/Azure/azure-sdk-for-go/sdk/azcore/internal/shared"
|
||||
"github.com/Azure/azure-sdk-for-go/sdk/internal/poller"
|
||||
)
|
||||
|
||||
// Applicable returns true if the LRO is using Operation-Location.
|
||||
|
|
@ -54,19 +55,19 @@ func New[T any](pl exported.Pipeline, resp *http.Response, finalState pollers.Fi
|
|||
if opURL == "" {
|
||||
return nil, errors.New("response is missing Operation-Location header")
|
||||
}
|
||||
if !pollers.IsValidURL(opURL) {
|
||||
if !poller.IsValidURL(opURL) {
|
||||
return nil, fmt.Errorf("invalid Operation-Location URL %s", opURL)
|
||||
}
|
||||
locURL := resp.Header.Get(shared.HeaderLocation)
|
||||
// Location header is optional
|
||||
if locURL != "" && !pollers.IsValidURL(locURL) {
|
||||
if locURL != "" && !poller.IsValidURL(locURL) {
|
||||
return nil, fmt.Errorf("invalid Location URL %s", locURL)
|
||||
}
|
||||
// default initial state to InProgress. if the
|
||||
// service sent us a status then use that instead.
|
||||
curState := pollers.StatusInProgress
|
||||
status, err := pollers.GetStatus(resp)
|
||||
if err != nil && !errors.Is(err, pollers.ErrNoBody) {
|
||||
curState := poller.StatusInProgress
|
||||
status, err := poller.GetStatus(resp)
|
||||
if err != nil && !errors.Is(err, poller.ErrNoBody) {
|
||||
return nil, err
|
||||
}
|
||||
if status != "" {
|
||||
|
|
@ -86,16 +87,16 @@ func New[T any](pl exported.Pipeline, resp *http.Response, finalState pollers.Fi
|
|||
}
|
||||
|
||||
func (p *Poller[T]) Done() bool {
|
||||
return pollers.IsTerminalState(p.CurState)
|
||||
return poller.IsTerminalState(p.CurState)
|
||||
}
|
||||
|
||||
func (p *Poller[T]) Poll(ctx context.Context) (*http.Response, error) {
|
||||
err := pollers.PollHelper(ctx, p.OpLocURL, p.pl, func(resp *http.Response) (string, error) {
|
||||
if !pollers.StatusCodeValid(resp) {
|
||||
if !poller.StatusCodeValid(resp) {
|
||||
p.resp = resp
|
||||
return "", exported.NewResponseError(resp)
|
||||
}
|
||||
state, err := pollers.GetStatus(resp)
|
||||
state, err := poller.GetStatus(resp)
|
||||
if err != nil {
|
||||
return "", err
|
||||
} else if state == "" {
|
||||
|
|
@ -118,7 +119,7 @@ func (p *Poller[T]) Result(ctx context.Context, out *T) error {
|
|||
req, err = exported.NewRequest(ctx, http.MethodGet, p.LocURL)
|
||||
} else if p.FinalState == pollers.FinalStateViaOpLocation && p.Method == http.MethodPost {
|
||||
// no final GET required, terminal response should have it
|
||||
} else if rl, rlErr := pollers.GetResourceLocation(p.resp); rlErr != nil && !errors.Is(rlErr, pollers.ErrNoBody) {
|
||||
} else if rl, rlErr := poller.GetResourceLocation(p.resp); rlErr != nil && !errors.Is(rlErr, poller.ErrNoBody) {
|
||||
return rlErr
|
||||
} else if rl != "" {
|
||||
req, err = exported.NewRequest(ctx, http.MethodGet, rl)
|
||||
|
|
@ -140,5 +141,5 @@ func (p *Poller[T]) Result(ctx context.Context, out *T) error {
|
|||
p.resp = resp
|
||||
}
|
||||
|
||||
return pollers.ResultHelper(p.resp, pollers.Failed(p.CurState), out)
|
||||
return pollers.ResultHelper(p.resp, poller.Failed(p.CurState), out)
|
||||
}
|
||||
|
|
|
|||
148
vendor/github.com/Azure/azure-sdk-for-go/sdk/azcore/internal/pollers/util.go
generated
vendored
148
vendor/github.com/Azure/azure-sdk-for-go/sdk/azcore/internal/pollers/util.go
generated
vendored
|
|
@ -12,49 +12,15 @@ import (
|
|||
"errors"
|
||||
"fmt"
|
||||
"net/http"
|
||||
"net/url"
|
||||
"reflect"
|
||||
"strings"
|
||||
|
||||
"github.com/Azure/azure-sdk-for-go/sdk/azcore/internal/exported"
|
||||
azexported "github.com/Azure/azure-sdk-for-go/sdk/azcore/internal/exported"
|
||||
"github.com/Azure/azure-sdk-for-go/sdk/azcore/internal/log"
|
||||
"github.com/Azure/azure-sdk-for-go/sdk/azcore/internal/shared"
|
||||
"github.com/Azure/azure-sdk-for-go/sdk/internal/exported"
|
||||
"github.com/Azure/azure-sdk-for-go/sdk/internal/poller"
|
||||
)
|
||||
|
||||
// the well-known set of LRO status/provisioning state values.
|
||||
const (
|
||||
StatusSucceeded = "Succeeded"
|
||||
StatusCanceled = "Canceled"
|
||||
StatusFailed = "Failed"
|
||||
StatusInProgress = "InProgress"
|
||||
)
|
||||
|
||||
// IsTerminalState returns true if the LRO's state is terminal.
|
||||
func IsTerminalState(s string) bool {
|
||||
return strings.EqualFold(s, StatusSucceeded) || strings.EqualFold(s, StatusFailed) || strings.EqualFold(s, StatusCanceled)
|
||||
}
|
||||
|
||||
// Failed returns true if the LRO's state is terminal failure.
|
||||
func Failed(s string) bool {
|
||||
return strings.EqualFold(s, StatusFailed) || strings.EqualFold(s, StatusCanceled)
|
||||
}
|
||||
|
||||
// Succeeded returns true if the LRO's state is terminal success.
|
||||
func Succeeded(s string) bool {
|
||||
return strings.EqualFold(s, StatusSucceeded)
|
||||
}
|
||||
|
||||
// returns true if the LRO response contains a valid HTTP status code
|
||||
func StatusCodeValid(resp *http.Response) bool {
|
||||
return exported.HasStatusCode(resp, http.StatusOK, http.StatusAccepted, http.StatusCreated, http.StatusNoContent)
|
||||
}
|
||||
|
||||
// IsValidURL verifies that the URL is valid and absolute.
|
||||
func IsValidURL(s string) bool {
|
||||
u, err := url.Parse(s)
|
||||
return err == nil && u.IsAbs()
|
||||
}
|
||||
|
||||
// getTokenTypeName creates a type name from the type parameter T.
|
||||
func getTokenTypeName[T any]() (string, error) {
|
||||
tt := shared.TypeOfT[T]()
|
||||
|
|
@ -130,102 +96,6 @@ func IsTokenValid[T any](token string) error {
|
|||
return nil
|
||||
}
|
||||
|
||||
// ErrNoBody is returned if the response didn't contain a body.
|
||||
var ErrNoBody = errors.New("the response did not contain a body")
|
||||
|
||||
// GetJSON reads the response body into a raw JSON object.
|
||||
// It returns ErrNoBody if there was no content.
|
||||
func GetJSON(resp *http.Response) (map[string]interface{}, error) {
|
||||
body, err := exported.Payload(resp)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if len(body) == 0 {
|
||||
return nil, ErrNoBody
|
||||
}
|
||||
// unmarshall the body to get the value
|
||||
var jsonBody map[string]interface{}
|
||||
if err = json.Unmarshal(body, &jsonBody); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return jsonBody, nil
|
||||
}
|
||||
|
||||
// provisioningState returns the provisioning state from the response or the empty string.
|
||||
func provisioningState(jsonBody map[string]interface{}) string {
|
||||
jsonProps, ok := jsonBody["properties"]
|
||||
if !ok {
|
||||
return ""
|
||||
}
|
||||
props, ok := jsonProps.(map[string]interface{})
|
||||
if !ok {
|
||||
return ""
|
||||
}
|
||||
rawPs, ok := props["provisioningState"]
|
||||
if !ok {
|
||||
return ""
|
||||
}
|
||||
ps, ok := rawPs.(string)
|
||||
if !ok {
|
||||
return ""
|
||||
}
|
||||
return ps
|
||||
}
|
||||
|
||||
// status returns the status from the response or the empty string.
|
||||
func status(jsonBody map[string]interface{}) string {
|
||||
rawStatus, ok := jsonBody["status"]
|
||||
if !ok {
|
||||
return ""
|
||||
}
|
||||
status, ok := rawStatus.(string)
|
||||
if !ok {
|
||||
return ""
|
||||
}
|
||||
return status
|
||||
}
|
||||
|
||||
// GetStatus returns the LRO's status from the response body.
|
||||
// Typically used for Azure-AsyncOperation flows.
|
||||
// If there is no status in the response body the empty string is returned.
|
||||
func GetStatus(resp *http.Response) (string, error) {
|
||||
jsonBody, err := GetJSON(resp)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
return status(jsonBody), nil
|
||||
}
|
||||
|
||||
// GetProvisioningState returns the LRO's state from the response body.
|
||||
// If there is no state in the response body the empty string is returned.
|
||||
func GetProvisioningState(resp *http.Response) (string, error) {
|
||||
jsonBody, err := GetJSON(resp)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
return provisioningState(jsonBody), nil
|
||||
}
|
||||
|
||||
// GetResourceLocation returns the LRO's resourceLocation value from the response body.
|
||||
// Typically used for Operation-Location flows.
|
||||
// If there is no resourceLocation in the response body the empty string is returned.
|
||||
func GetResourceLocation(resp *http.Response) (string, error) {
|
||||
jsonBody, err := GetJSON(resp)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
v, ok := jsonBody["resourceLocation"]
|
||||
if !ok {
|
||||
// it might be ok if the field doesn't exist, the caller must make that determination
|
||||
return "", nil
|
||||
}
|
||||
vv, ok := v.(string)
|
||||
if !ok {
|
||||
return "", fmt.Errorf("the resourceLocation value %v was not in string format", v)
|
||||
}
|
||||
return vv, nil
|
||||
}
|
||||
|
||||
// used if the operation synchronously completed
|
||||
type NopPoller[T any] struct {
|
||||
resp *http.Response
|
||||
|
|
@ -239,7 +109,7 @@ func NewNopPoller[T any](resp *http.Response) (*NopPoller[T], error) {
|
|||
if resp.StatusCode == http.StatusNoContent {
|
||||
return np, nil
|
||||
}
|
||||
payload, err := exported.Payload(resp)
|
||||
payload, err := exported.Payload(resp, nil)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
|
@ -269,8 +139,8 @@ func (p *NopPoller[T]) Result(ctx context.Context, out *T) error {
|
|||
// If the request fails, the update func is not called.
|
||||
// The update func returns the state of the operation for logging purposes or an error
|
||||
// if it fails to extract the required state from the response.
|
||||
func PollHelper(ctx context.Context, endpoint string, pl exported.Pipeline, update func(resp *http.Response) (string, error)) error {
|
||||
req, err := exported.NewRequest(ctx, http.MethodGet, endpoint)
|
||||
func PollHelper(ctx context.Context, endpoint string, pl azexported.Pipeline, update func(resp *http.Response) (string, error)) error {
|
||||
req, err := azexported.NewRequest(ctx, http.MethodGet, endpoint)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
|
@ -296,13 +166,13 @@ func ResultHelper[T any](resp *http.Response, failed bool, out *T) error {
|
|||
}
|
||||
|
||||
defer resp.Body.Close()
|
||||
if !StatusCodeValid(resp) || failed {
|
||||
if !poller.StatusCodeValid(resp) || failed {
|
||||
// the LRO failed. unmarshall the error and update state
|
||||
return exported.NewResponseError(resp)
|
||||
return azexported.NewResponseError(resp)
|
||||
}
|
||||
|
||||
// success case
|
||||
payload, err := exported.Payload(resp)
|
||||
payload, err := exported.Payload(resp, nil)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
|
|
|||
4
vendor/github.com/Azure/azure-sdk-for-go/sdk/azcore/internal/shared/constants.go
generated
vendored
4
vendor/github.com/Azure/azure-sdk-for-go/sdk/azcore/internal/shared/constants.go
generated
vendored
|
|
@ -21,6 +21,8 @@ const (
|
|||
HeaderOperationLocation = "Operation-Location"
|
||||
HeaderRetryAfter = "Retry-After"
|
||||
HeaderUserAgent = "User-Agent"
|
||||
HeaderWWWAuthenticate = "WWW-Authenticate"
|
||||
HeaderXMSClientRequestID = "x-ms-client-request-id"
|
||||
)
|
||||
|
||||
const BearerTokenPrefix = "Bearer "
|
||||
|
|
@ -30,5 +32,5 @@ const (
|
|||
Module = "azcore"
|
||||
|
||||
// Version is the semantic version (see http://semver.org) of this module.
|
||||
Version = "v1.3.0"
|
||||
Version = "v1.6.0"
|
||||
)
|
||||
|
|
|
|||
67
vendor/github.com/Azure/azure-sdk-for-go/sdk/azcore/internal/shared/shared.go
generated
vendored
67
vendor/github.com/Azure/azure-sdk-for-go/sdk/azcore/internal/shared/shared.go
generated
vendored
|
|
@ -8,9 +8,7 @@ package shared
|
|||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"fmt"
|
||||
"io"
|
||||
"net/http"
|
||||
"reflect"
|
||||
"regexp"
|
||||
|
|
@ -64,71 +62,6 @@ func TypeOfT[T any]() reflect.Type {
|
|||
return reflect.TypeOf((*T)(nil)).Elem()
|
||||
}
|
||||
|
||||
// BytesSetter abstracts replacing a byte slice on some type.
|
||||
type BytesSetter interface {
|
||||
Set(b []byte)
|
||||
}
|
||||
|
||||
// NewNopClosingBytesReader creates a new *NopClosingBytesReader for the specified slice.
|
||||
func NewNopClosingBytesReader(data []byte) *NopClosingBytesReader {
|
||||
return &NopClosingBytesReader{s: data}
|
||||
}
|
||||
|
||||
// NopClosingBytesReader is an io.ReadSeekCloser around a byte slice.
|
||||
// It also provides direct access to the byte slice to avoid rereading.
|
||||
type NopClosingBytesReader struct {
|
||||
s []byte
|
||||
i int64
|
||||
}
|
||||
|
||||
// Bytes returns the underlying byte slice.
|
||||
func (r *NopClosingBytesReader) Bytes() []byte {
|
||||
return r.s
|
||||
}
|
||||
|
||||
// Close implements the io.Closer interface.
|
||||
func (*NopClosingBytesReader) Close() error {
|
||||
return nil
|
||||
}
|
||||
|
||||
// Read implements the io.Reader interface.
|
||||
func (r *NopClosingBytesReader) Read(b []byte) (n int, err error) {
|
||||
if r.i >= int64(len(r.s)) {
|
||||
return 0, io.EOF
|
||||
}
|
||||
n = copy(b, r.s[r.i:])
|
||||
r.i += int64(n)
|
||||
return
|
||||
}
|
||||
|
||||
// Set replaces the existing byte slice with the specified byte slice and resets the reader.
|
||||
func (r *NopClosingBytesReader) Set(b []byte) {
|
||||
r.s = b
|
||||
r.i = 0
|
||||
}
|
||||
|
||||
// Seek implements the io.Seeker interface.
|
||||
func (r *NopClosingBytesReader) Seek(offset int64, whence int) (int64, error) {
|
||||
var i int64
|
||||
switch whence {
|
||||
case io.SeekStart:
|
||||
i = offset
|
||||
case io.SeekCurrent:
|
||||
i = r.i + offset
|
||||
case io.SeekEnd:
|
||||
i = int64(len(r.s)) + offset
|
||||
default:
|
||||
return 0, errors.New("nopClosingBytesReader: invalid whence")
|
||||
}
|
||||
if i < 0 {
|
||||
return 0, errors.New("nopClosingBytesReader: negative position")
|
||||
}
|
||||
r.i = i
|
||||
return i, nil
|
||||
}
|
||||
|
||||
var _ BytesSetter = (*NopClosingBytesReader)(nil)
|
||||
|
||||
// TransportFunc is a helper to use a first-class func to satisfy the Transporter interface.
|
||||
type TransportFunc func(*http.Request) (*http.Response, error)
|
||||
|
||||
|
|
|
|||
11
vendor/github.com/Azure/azure-sdk-for-go/sdk/azcore/policy/policy.go
generated
vendored
11
vendor/github.com/Azure/azure-sdk-for-go/sdk/azcore/policy/policy.go
generated
vendored
|
|
@ -99,7 +99,7 @@ type RetryOptions struct {
|
|||
|
||||
// MaxRetryDelay specifies the maximum delay allowed before retrying an operation.
|
||||
// Typically the value is greater than or equal to the value specified in RetryDelay.
|
||||
// The default Value is 120 seconds. A value less than zero means there is no cap.
|
||||
// The default Value is 60 seconds. A value less than zero means there is no cap.
|
||||
MaxRetryDelay time.Duration
|
||||
|
||||
// StatusCodes specifies the HTTP status codes that indicate the operation should be retried.
|
||||
|
|
@ -113,6 +113,15 @@ type RetryOptions struct {
|
|||
// Specifying values will replace the default values.
|
||||
// Specifying an empty slice will disable retries for HTTP status codes.
|
||||
StatusCodes []int
|
||||
|
||||
// ShouldRetry evaluates if the retry policy should retry the request.
|
||||
// When specified, the function overrides comparison against the list of
|
||||
// HTTP status codes and error checking within the retry policy. Context
|
||||
// and NonRetriable errors remain evaluated before calling ShouldRetry.
|
||||
// The *http.Response and error parameters are mutually exclusive, i.e.
|
||||
// if one is nil, the other is not nil.
|
||||
// A return value of true means the retry policy should retry.
|
||||
ShouldRetry func(*http.Response, error) bool
|
||||
}
|
||||
|
||||
// TelemetryOptions configures the telemetry policy's behavior.
|
||||
|
|
|
|||
15
vendor/github.com/Azure/azure-sdk-for-go/sdk/azcore/runtime/pipeline.go
generated
vendored
15
vendor/github.com/Azure/azure-sdk-for-go/sdk/azcore/runtime/pipeline.go
generated
vendored
|
|
@ -7,8 +7,6 @@
|
|||
package runtime
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
|
||||
"github.com/Azure/azure-sdk-for-go/sdk/azcore/internal/exported"
|
||||
"github.com/Azure/azure-sdk-for-go/sdk/azcore/policy"
|
||||
)
|
||||
|
|
@ -46,7 +44,7 @@ func NewPipeline(module, version string, plOpts PipelineOptions, options *policy
|
|||
}
|
||||
// we put the includeResponsePolicy at the very beginning so that the raw response
|
||||
// is populated with the final response (some policies might mutate the response)
|
||||
policies := []policy.Policy{policyFunc(includeResponsePolicy)}
|
||||
policies := []policy.Policy{exported.PolicyFunc(includeResponsePolicy)}
|
||||
if cp.APIVersion != "" {
|
||||
policies = append(policies, newAPIVersionPolicy(cp.APIVersion, &plOpts.APIVersion))
|
||||
}
|
||||
|
|
@ -59,19 +57,10 @@ func NewPipeline(module, version string, plOpts PipelineOptions, options *policy
|
|||
policies = append(policies, plOpts.PerRetry...)
|
||||
policies = append(policies, cp.PerRetryPolicies...)
|
||||
policies = append(policies, NewLogPolicy(&cp.Logging))
|
||||
policies = append(policies, policyFunc(httpHeaderPolicy), policyFunc(bodyDownloadPolicy))
|
||||
policies = append(policies, exported.PolicyFunc(httpHeaderPolicy), exported.PolicyFunc(bodyDownloadPolicy))
|
||||
transport := cp.Transport
|
||||
if transport == nil {
|
||||
transport = defaultHTTPClient
|
||||
}
|
||||
return exported.NewPipeline(transport, policies...)
|
||||
}
|
||||
|
||||
// policyFunc is a type that implements the Policy interface.
|
||||
// Use this type when implementing a stateless policy as a first-class function.
|
||||
type policyFunc func(*policy.Request) (*http.Response, error)
|
||||
|
||||
// Do implements the Policy interface on policyFunc.
|
||||
func (pf policyFunc) Do(req *policy.Request) (*http.Response, error) {
|
||||
return pf(req)
|
||||
}
|
||||
|
|
|
|||
3
vendor/github.com/Azure/azure-sdk-for-go/sdk/azcore/runtime/policy_body_download.go
generated
vendored
3
vendor/github.com/Azure/azure-sdk-for-go/sdk/azcore/runtime/policy_body_download.go
generated
vendored
|
|
@ -11,7 +11,6 @@ import (
|
|||
"net/http"
|
||||
"strings"
|
||||
|
||||
"github.com/Azure/azure-sdk-for-go/sdk/azcore/internal/exported"
|
||||
"github.com/Azure/azure-sdk-for-go/sdk/azcore/policy"
|
||||
"github.com/Azure/azure-sdk-for-go/sdk/internal/errorinfo"
|
||||
)
|
||||
|
|
@ -29,7 +28,7 @@ func bodyDownloadPolicy(req *policy.Request) (*http.Response, error) {
|
|||
}
|
||||
// Either bodyDownloadPolicyOpValues was not specified (so skip is false)
|
||||
// or it was specified and skip is false: don't skip downloading the body
|
||||
_, err = exported.Payload(resp)
|
||||
_, err = Payload(resp)
|
||||
if err != nil {
|
||||
return resp, newBodyDownloadError(err, req)
|
||||
}
|
||||
|
|
|
|||
40
vendor/github.com/Azure/azure-sdk-for-go/sdk/azcore/runtime/policy_logging.go
generated
vendored
40
vendor/github.com/Azure/azure-sdk-for-go/sdk/azcore/runtime/policy_logging.go
generated
vendored
|
|
@ -11,6 +11,7 @@ import (
|
|||
"fmt"
|
||||
"io"
|
||||
"net/http"
|
||||
"net/url"
|
||||
"sort"
|
||||
"strings"
|
||||
"time"
|
||||
|
|
@ -66,12 +67,7 @@ func NewLogPolicy(o *policy.LogOptions) policy.Policy {
|
|||
allowedHeaders[strings.ToLower(ah)] = struct{}{}
|
||||
}
|
||||
// now do the same thing for query params
|
||||
allowedQP := map[string]struct{}{
|
||||
"api-version": {},
|
||||
}
|
||||
for _, qp := range o.AllowedQueryParams {
|
||||
allowedQP[strings.ToLower(qp)] = struct{}{}
|
||||
}
|
||||
allowedQP := getAllowedQueryParams(o.AllowedQueryParams)
|
||||
return &logPolicy{
|
||||
includeBody: o.IncludeBody,
|
||||
allowedHeaders: allowedHeaders,
|
||||
|
|
@ -79,6 +75,18 @@ func NewLogPolicy(o *policy.LogOptions) policy.Policy {
|
|||
}
|
||||
}
|
||||
|
||||
// getAllowedQueryParams merges the default set of allowed query parameters
|
||||
// with a custom set (usually comes from client options).
|
||||
func getAllowedQueryParams(customAllowedQP []string) map[string]struct{} {
|
||||
allowedQP := map[string]struct{}{
|
||||
"api-version": {},
|
||||
}
|
||||
for _, qp := range customAllowedQP {
|
||||
allowedQP[strings.ToLower(qp)] = struct{}{}
|
||||
}
|
||||
return allowedQP
|
||||
}
|
||||
|
||||
// logPolicyOpValues is the struct containing the per-operation values
|
||||
type logPolicyOpValues struct {
|
||||
try int32
|
||||
|
|
@ -140,20 +148,24 @@ func (p *logPolicy) Do(req *policy.Request) (*http.Response, error) {
|
|||
|
||||
const redactedValue = "REDACTED"
|
||||
|
||||
// writeRequestWithResponse appends a formatted HTTP request into a Buffer. If request and/or err are
|
||||
// not nil, then these are also written into the Buffer.
|
||||
func (p *logPolicy) writeRequestWithResponse(b *bytes.Buffer, req *policy.Request, resp *http.Response, err error) {
|
||||
// getSanitizedURL returns a sanitized string for the provided url.URL
|
||||
func getSanitizedURL(u url.URL, allowedQueryParams map[string]struct{}) string {
|
||||
// redact applicable query params
|
||||
cpURL := *req.Raw().URL
|
||||
qp := cpURL.Query()
|
||||
qp := u.Query()
|
||||
for k := range qp {
|
||||
if _, ok := p.allowedQP[strings.ToLower(k)]; !ok {
|
||||
if _, ok := allowedQueryParams[strings.ToLower(k)]; !ok {
|
||||
qp.Set(k, redactedValue)
|
||||
}
|
||||
}
|
||||
cpURL.RawQuery = qp.Encode()
|
||||
u.RawQuery = qp.Encode()
|
||||
return u.String()
|
||||
}
|
||||
|
||||
// writeRequestWithResponse appends a formatted HTTP request into a Buffer. If request and/or err are
|
||||
// not nil, then these are also written into the Buffer.
|
||||
func (p *logPolicy) writeRequestWithResponse(b *bytes.Buffer, req *policy.Request, resp *http.Response, err error) {
|
||||
// Write the request into the buffer.
|
||||
fmt.Fprint(b, " "+req.Raw().Method+" "+cpURL.String()+"\n")
|
||||
fmt.Fprint(b, " "+req.Raw().Method+" "+getSanitizedURL(*req.Raw().URL, p.allowedQP)+"\n")
|
||||
p.writeHeader(b, req.Raw().Header)
|
||||
if resp != nil {
|
||||
fmt.Fprintln(b, " --------------------------------------------------------------------------------")
|
||||
|
|
|
|||
6
vendor/github.com/Azure/azure-sdk-for-go/sdk/azcore/runtime/policy_request_id.go
generated
vendored
6
vendor/github.com/Azure/azure-sdk-for-go/sdk/azcore/runtime/policy_request_id.go
generated
vendored
|
|
@ -9,6 +9,7 @@ package runtime
|
|||
import (
|
||||
"net/http"
|
||||
|
||||
"github.com/Azure/azure-sdk-for-go/sdk/azcore/internal/shared"
|
||||
"github.com/Azure/azure-sdk-for-go/sdk/azcore/policy"
|
||||
"github.com/Azure/azure-sdk-for-go/sdk/internal/uuid"
|
||||
)
|
||||
|
|
@ -21,13 +22,12 @@ func NewRequestIDPolicy() policy.Policy {
|
|||
}
|
||||
|
||||
func (r *requestIDPolicy) Do(req *policy.Request) (*http.Response, error) {
|
||||
const requestIdHeader = "x-ms-client-request-id"
|
||||
if req.Raw().Header.Get(requestIdHeader) == "" {
|
||||
if req.Raw().Header.Get(shared.HeaderXMSClientRequestID) == "" {
|
||||
id, err := uuid.New()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
req.Raw().Header.Set(requestIdHeader, id.String())
|
||||
req.Raw().Header.Set(shared.HeaderXMSClientRequestID, id.String())
|
||||
}
|
||||
|
||||
return req.Next()
|
||||
|
|
|
|||
22
vendor/github.com/Azure/azure-sdk-for-go/sdk/azcore/runtime/policy_retry.go
generated
vendored
22
vendor/github.com/Azure/azure-sdk-for-go/sdk/azcore/runtime/policy_retry.go
generated
vendored
|
|
@ -19,6 +19,7 @@ import (
|
|||
"github.com/Azure/azure-sdk-for-go/sdk/azcore/internal/shared"
|
||||
"github.com/Azure/azure-sdk-for-go/sdk/azcore/policy"
|
||||
"github.com/Azure/azure-sdk-for-go/sdk/internal/errorinfo"
|
||||
"github.com/Azure/azure-sdk-for-go/sdk/internal/exported"
|
||||
)
|
||||
|
||||
const (
|
||||
|
|
@ -133,7 +134,7 @@ func (p *retryPolicy) Do(req *policy.Request) (resp *http.Response, err error) {
|
|||
// if the body was already downloaded or there was an error it's safe to cancel the context now
|
||||
if err != nil {
|
||||
tryCancel()
|
||||
} else if _, ok := resp.Body.(*shared.NopClosingBytesReader); ok {
|
||||
} else if exported.PayloadDownloaded(resp) {
|
||||
tryCancel()
|
||||
} else {
|
||||
// must cancel the context after the body has been read and closed
|
||||
|
|
@ -146,11 +147,7 @@ func (p *retryPolicy) Do(req *policy.Request) (resp *http.Response, err error) {
|
|||
log.Writef(log.EventRetryPolicy, "error %v", err)
|
||||
}
|
||||
|
||||
if err == nil && !HasStatusCode(resp, options.StatusCodes...) {
|
||||
// if there is no error and the response code isn't in the list of retry codes then we're done.
|
||||
log.Write(log.EventRetryPolicy, "exit due to non-retriable status code")
|
||||
return
|
||||
} else if ctxErr := req.Raw().Context().Err(); ctxErr != nil {
|
||||
if ctxErr := req.Raw().Context().Err(); ctxErr != nil {
|
||||
// don't retry if the parent context has been cancelled or its deadline exceeded
|
||||
err = ctxErr
|
||||
log.Writef(log.EventRetryPolicy, "abort due to %v", err)
|
||||
|
|
@ -165,6 +162,19 @@ func (p *retryPolicy) Do(req *policy.Request) (resp *http.Response, err error) {
|
|||
return
|
||||
}
|
||||
|
||||
if options.ShouldRetry != nil {
|
||||
// a non-nil ShouldRetry overrides our HTTP status code check
|
||||
if !options.ShouldRetry(resp, err) {
|
||||
// predicate says we shouldn't retry
|
||||
log.Write(log.EventRetryPolicy, "exit due to ShouldRetry")
|
||||
return
|
||||
}
|
||||
} else if err == nil && !HasStatusCode(resp, options.StatusCodes...) {
|
||||
// if there is no error and the response code isn't in the list of retry codes then we're done.
|
||||
log.Write(log.EventRetryPolicy, "exit due to non-retriable status code")
|
||||
return
|
||||
}
|
||||
|
||||
if try == options.MaxRetries+1 {
|
||||
// max number of tries has been reached, don't sleep again
|
||||
log.Writef(log.EventRetryPolicy, "MaxRetries %d exceeded", options.MaxRetries)
|
||||
|
|
|
|||
9
vendor/github.com/Azure/azure-sdk-for-go/sdk/azcore/runtime/poller.go
generated
vendored
9
vendor/github.com/Azure/azure-sdk-for-go/sdk/azcore/runtime/poller.go
generated
vendored
|
|
@ -23,6 +23,7 @@ import (
|
|||
"github.com/Azure/azure-sdk-for-go/sdk/azcore/internal/pollers/loc"
|
||||
"github.com/Azure/azure-sdk-for-go/sdk/azcore/internal/pollers/op"
|
||||
"github.com/Azure/azure-sdk-for-go/sdk/azcore/internal/shared"
|
||||
"github.com/Azure/azure-sdk-for-go/sdk/internal/poller"
|
||||
)
|
||||
|
||||
// FinalStateVia is the enumerated type for the possible final-state-via values.
|
||||
|
|
@ -75,7 +76,7 @@ func NewPoller[T any](resp *http.Response, pl exported.Pipeline, options *NewPol
|
|||
defer resp.Body.Close()
|
||||
// this is a back-stop in case the swagger is incorrect (i.e. missing one or more status codes for success).
|
||||
// ideally the codegen should return an error if the initial response failed and not even create a poller.
|
||||
if !pollers.StatusCodeValid(resp) {
|
||||
if !poller.StatusCodeValid(resp) {
|
||||
return nil, errors.New("the operation failed or was cancelled")
|
||||
}
|
||||
|
||||
|
|
@ -146,7 +147,9 @@ func NewPollerFromResumeToken[T any](token string, pl exported.Pipeline, options
|
|||
|
||||
opr := options.Handler
|
||||
// now rehydrate the poller based on the encoded poller type
|
||||
if async.CanResume(asJSON) {
|
||||
if opr != nil {
|
||||
log.Writef(log.EventLRO, "Resuming custom poller %T.", opr)
|
||||
} else if async.CanResume(asJSON) {
|
||||
opr, _ = async.New[T](pl, nil, "")
|
||||
} else if body.CanResume(asJSON) {
|
||||
opr, _ = body.New[T](pl, nil)
|
||||
|
|
@ -154,8 +157,6 @@ func NewPollerFromResumeToken[T any](token string, pl exported.Pipeline, options
|
|||
opr, _ = loc.New[T](pl, nil)
|
||||
} else if op.CanResume(asJSON) {
|
||||
opr, _ = op.New[T](pl, nil, "")
|
||||
} else if opr != nil {
|
||||
log.Writef(log.EventLRO, "Resuming custom poller %T.", opr)
|
||||
} else {
|
||||
return nil, fmt.Errorf("unhandled poller token %s", string(raw))
|
||||
}
|
||||
|
|
|
|||
17
vendor/github.com/Azure/azure-sdk-for-go/sdk/azcore/runtime/response.go
generated
vendored
17
vendor/github.com/Azure/azure-sdk-for-go/sdk/azcore/runtime/response.go
generated
vendored
|
|
@ -15,15 +15,14 @@ import (
|
|||
"io"
|
||||
"net/http"
|
||||
|
||||
"github.com/Azure/azure-sdk-for-go/sdk/azcore/internal/exported"
|
||||
"github.com/Azure/azure-sdk-for-go/sdk/azcore/internal/shared"
|
||||
"github.com/Azure/azure-sdk-for-go/sdk/internal/exported"
|
||||
)
|
||||
|
||||
// Payload reads and returns the response body or an error.
|
||||
// On a successful read, the response body is cached.
|
||||
// Subsequent reads will access the cached value.
|
||||
func Payload(resp *http.Response) ([]byte, error) {
|
||||
return exported.Payload(resp)
|
||||
return exported.Payload(resp, nil)
|
||||
}
|
||||
|
||||
// HasStatusCode returns true if the Response's status code is one of the specified values.
|
||||
|
|
@ -92,15 +91,15 @@ func Drain(resp *http.Response) {
|
|||
|
||||
// removeBOM removes any byte-order mark prefix from the payload if present.
|
||||
func removeBOM(resp *http.Response) error {
|
||||
payload, err := Payload(resp)
|
||||
_, err := exported.Payload(resp, &exported.PayloadOptions{
|
||||
BytesModifier: func(b []byte) []byte {
|
||||
// UTF8
|
||||
return bytes.TrimPrefix(b, []byte("\xef\xbb\xbf"))
|
||||
},
|
||||
})
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
// UTF8
|
||||
trimmed := bytes.TrimPrefix(payload, []byte("\xef\xbb\xbf"))
|
||||
if len(trimmed) < len(payload) {
|
||||
resp.Body.(shared.BytesSetter).Set(trimmed)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
|
|
|
|||
3
vendor/github.com/Azure/azure-sdk-for-go/sdk/azcore/streaming/progress.go
generated
vendored
3
vendor/github.com/Azure/azure-sdk-for-go/sdk/azcore/streaming/progress.go
generated
vendored
|
|
@ -20,6 +20,9 @@ type progress struct {
|
|||
}
|
||||
|
||||
// NopCloser returns a ReadSeekCloser with a no-op close method wrapping the provided io.ReadSeeker.
|
||||
// In addition to adding a Close method to an io.ReadSeeker, this can also be used to wrap an
|
||||
// io.ReadSeekCloser with a no-op Close method to allow explicit control of when the io.ReedSeekCloser
|
||||
// has its underlying stream closed.
|
||||
func NopCloser(rs io.ReadSeeker) io.ReadSeekCloser {
|
||||
return exported.NopCloser(rs)
|
||||
}
|
||||
|
|
|
|||
124
vendor/github.com/Azure/azure-sdk-for-go/sdk/internal/exported/exported.go
generated
vendored
Normal file
124
vendor/github.com/Azure/azure-sdk-for-go/sdk/internal/exported/exported.go
generated
vendored
Normal file
|
|
@ -0,0 +1,124 @@
|
|||
//go:build go1.18
|
||||
// +build go1.18
|
||||
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// Licensed under the MIT License.
|
||||
|
||||
package exported
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"io"
|
||||
"net/http"
|
||||
)
|
||||
|
||||
// HasStatusCode returns true if the Response's status code is one of the specified values.
|
||||
// Exported as runtime.HasStatusCode().
|
||||
func HasStatusCode(resp *http.Response, statusCodes ...int) bool {
|
||||
if resp == nil {
|
||||
return false
|
||||
}
|
||||
for _, sc := range statusCodes {
|
||||
if resp.StatusCode == sc {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
// PayloadOptions contains the optional values for the Payload func.
|
||||
// NOT exported but used by azcore.
|
||||
type PayloadOptions struct {
|
||||
// BytesModifier receives the downloaded byte slice and returns an updated byte slice.
|
||||
// Use this to modify the downloaded bytes in a payload (e.g. removing a BOM).
|
||||
BytesModifier func([]byte) []byte
|
||||
}
|
||||
|
||||
// Payload reads and returns the response body or an error.
|
||||
// On a successful read, the response body is cached.
|
||||
// Subsequent reads will access the cached value.
|
||||
// Exported as runtime.Payload() WITHOUT the opts parameter.
|
||||
func Payload(resp *http.Response, opts *PayloadOptions) ([]byte, error) {
|
||||
modifyBytes := func(b []byte) []byte { return b }
|
||||
if opts != nil && opts.BytesModifier != nil {
|
||||
modifyBytes = opts.BytesModifier
|
||||
}
|
||||
|
||||
// r.Body won't be a nopClosingBytesReader if downloading was skipped
|
||||
if buf, ok := resp.Body.(*nopClosingBytesReader); ok {
|
||||
bytesBody := modifyBytes(buf.Bytes())
|
||||
buf.Set(bytesBody)
|
||||
return bytesBody, nil
|
||||
}
|
||||
|
||||
bytesBody, err := io.ReadAll(resp.Body)
|
||||
resp.Body.Close()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
bytesBody = modifyBytes(bytesBody)
|
||||
resp.Body = &nopClosingBytesReader{s: bytesBody}
|
||||
return bytesBody, nil
|
||||
}
|
||||
|
||||
// PayloadDownloaded returns true if the response body has already been downloaded.
|
||||
// This implies that the Payload() func above has been previously called.
|
||||
// NOT exported but used by azcore.
|
||||
func PayloadDownloaded(resp *http.Response) bool {
|
||||
_, ok := resp.Body.(*nopClosingBytesReader)
|
||||
return ok
|
||||
}
|
||||
|
||||
// nopClosingBytesReader is an io.ReadSeekCloser around a byte slice.
|
||||
// It also provides direct access to the byte slice to avoid rereading.
|
||||
type nopClosingBytesReader struct {
|
||||
s []byte
|
||||
i int64
|
||||
}
|
||||
|
||||
// Bytes returns the underlying byte slice.
|
||||
func (r *nopClosingBytesReader) Bytes() []byte {
|
||||
return r.s
|
||||
}
|
||||
|
||||
// Close implements the io.Closer interface.
|
||||
func (*nopClosingBytesReader) Close() error {
|
||||
return nil
|
||||
}
|
||||
|
||||
// Read implements the io.Reader interface.
|
||||
func (r *nopClosingBytesReader) Read(b []byte) (n int, err error) {
|
||||
if r.i >= int64(len(r.s)) {
|
||||
return 0, io.EOF
|
||||
}
|
||||
n = copy(b, r.s[r.i:])
|
||||
r.i += int64(n)
|
||||
return
|
||||
}
|
||||
|
||||
// Set replaces the existing byte slice with the specified byte slice and resets the reader.
|
||||
func (r *nopClosingBytesReader) Set(b []byte) {
|
||||
r.s = b
|
||||
r.i = 0
|
||||
}
|
||||
|
||||
// Seek implements the io.Seeker interface.
|
||||
func (r *nopClosingBytesReader) Seek(offset int64, whence int) (int64, error) {
|
||||
var i int64
|
||||
switch whence {
|
||||
case io.SeekStart:
|
||||
i = offset
|
||||
case io.SeekCurrent:
|
||||
i = r.i + offset
|
||||
case io.SeekEnd:
|
||||
i = int64(len(r.s)) + offset
|
||||
default:
|
||||
return 0, errors.New("nopClosingBytesReader: invalid whence")
|
||||
}
|
||||
if i < 0 {
|
||||
return 0, errors.New("nopClosingBytesReader: negative position")
|
||||
}
|
||||
r.i = i
|
||||
return i, nil
|
||||
}
|
||||
155
vendor/github.com/Azure/azure-sdk-for-go/sdk/internal/poller/util.go
generated
vendored
Normal file
155
vendor/github.com/Azure/azure-sdk-for-go/sdk/internal/poller/util.go
generated
vendored
Normal file
|
|
@ -0,0 +1,155 @@
|
|||
//go:build go1.18
|
||||
// +build go1.18
|
||||
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// Licensed under the MIT License.
|
||||
|
||||
package poller
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"fmt"
|
||||
"net/http"
|
||||
"net/url"
|
||||
"strings"
|
||||
|
||||
"github.com/Azure/azure-sdk-for-go/sdk/internal/exported"
|
||||
)
|
||||
|
||||
// the well-known set of LRO status/provisioning state values.
|
||||
const (
|
||||
StatusSucceeded = "Succeeded"
|
||||
StatusCanceled = "Canceled"
|
||||
StatusFailed = "Failed"
|
||||
StatusInProgress = "InProgress"
|
||||
)
|
||||
|
||||
// these are non-conformant states that we've seen in the wild.
|
||||
// we support them for back-compat.
|
||||
const (
|
||||
StatusCancelled = "Cancelled"
|
||||
StatusCompleted = "Completed"
|
||||
)
|
||||
|
||||
// IsTerminalState returns true if the LRO's state is terminal.
|
||||
func IsTerminalState(s string) bool {
|
||||
return Failed(s) || Succeeded(s)
|
||||
}
|
||||
|
||||
// Failed returns true if the LRO's state is terminal failure.
|
||||
func Failed(s string) bool {
|
||||
return strings.EqualFold(s, StatusFailed) || strings.EqualFold(s, StatusCanceled) || strings.EqualFold(s, StatusCancelled)
|
||||
}
|
||||
|
||||
// Succeeded returns true if the LRO's state is terminal success.
|
||||
func Succeeded(s string) bool {
|
||||
return strings.EqualFold(s, StatusSucceeded) || strings.EqualFold(s, StatusCompleted)
|
||||
}
|
||||
|
||||
// returns true if the LRO response contains a valid HTTP status code
|
||||
func StatusCodeValid(resp *http.Response) bool {
|
||||
return exported.HasStatusCode(resp, http.StatusOK, http.StatusAccepted, http.StatusCreated, http.StatusNoContent)
|
||||
}
|
||||
|
||||
// IsValidURL verifies that the URL is valid and absolute.
|
||||
func IsValidURL(s string) bool {
|
||||
u, err := url.Parse(s)
|
||||
return err == nil && u.IsAbs()
|
||||
}
|
||||
|
||||
// ErrNoBody is returned if the response didn't contain a body.
|
||||
var ErrNoBody = errors.New("the response did not contain a body")
|
||||
|
||||
// GetJSON reads the response body into a raw JSON object.
|
||||
// It returns ErrNoBody if there was no content.
|
||||
func GetJSON(resp *http.Response) (map[string]any, error) {
|
||||
body, err := exported.Payload(resp, nil)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if len(body) == 0 {
|
||||
return nil, ErrNoBody
|
||||
}
|
||||
// unmarshall the body to get the value
|
||||
var jsonBody map[string]any
|
||||
if err = json.Unmarshal(body, &jsonBody); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return jsonBody, nil
|
||||
}
|
||||
|
||||
// provisioningState returns the provisioning state from the response or the empty string.
|
||||
func provisioningState(jsonBody map[string]any) string {
|
||||
jsonProps, ok := jsonBody["properties"]
|
||||
if !ok {
|
||||
return ""
|
||||
}
|
||||
props, ok := jsonProps.(map[string]any)
|
||||
if !ok {
|
||||
return ""
|
||||
}
|
||||
rawPs, ok := props["provisioningState"]
|
||||
if !ok {
|
||||
return ""
|
||||
}
|
||||
ps, ok := rawPs.(string)
|
||||
if !ok {
|
||||
return ""
|
||||
}
|
||||
return ps
|
||||
}
|
||||
|
||||
// status returns the status from the response or the empty string.
|
||||
func status(jsonBody map[string]any) string {
|
||||
rawStatus, ok := jsonBody["status"]
|
||||
if !ok {
|
||||
return ""
|
||||
}
|
||||
status, ok := rawStatus.(string)
|
||||
if !ok {
|
||||
return ""
|
||||
}
|
||||
return status
|
||||
}
|
||||
|
||||
// GetStatus returns the LRO's status from the response body.
|
||||
// Typically used for Azure-AsyncOperation flows.
|
||||
// If there is no status in the response body the empty string is returned.
|
||||
func GetStatus(resp *http.Response) (string, error) {
|
||||
jsonBody, err := GetJSON(resp)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
return status(jsonBody), nil
|
||||
}
|
||||
|
||||
// GetProvisioningState returns the LRO's state from the response body.
|
||||
// If there is no state in the response body the empty string is returned.
|
||||
func GetProvisioningState(resp *http.Response) (string, error) {
|
||||
jsonBody, err := GetJSON(resp)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
return provisioningState(jsonBody), nil
|
||||
}
|
||||
|
||||
// GetResourceLocation returns the LRO's resourceLocation value from the response body.
|
||||
// Typically used for Operation-Location flows.
|
||||
// If there is no resourceLocation in the response body the empty string is returned.
|
||||
func GetResourceLocation(resp *http.Response) (string, error) {
|
||||
jsonBody, err := GetJSON(resp)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
v, ok := jsonBody["resourceLocation"]
|
||||
if !ok {
|
||||
// it might be ok if the field doesn't exist, the caller must make that determination
|
||||
return "", nil
|
||||
}
|
||||
vv, ok := v.(string)
|
||||
if !ok {
|
||||
return "", fmt.Errorf("the resourceLocation value %v was not in string format", v)
|
||||
}
|
||||
return vv, nil
|
||||
}
|
||||
39
vendor/github.com/Azure/azure-sdk-for-go/sdk/storage/azblob/CHANGELOG.md
generated
vendored
39
vendor/github.com/Azure/azure-sdk-for-go/sdk/storage/azblob/CHANGELOG.md
generated
vendored
|
|
@ -1,5 +1,44 @@
|
|||
# Release History
|
||||
|
||||
## 1.1.0 (2023-07-13)
|
||||
|
||||
### Features Added
|
||||
|
||||
* Added [Blob Batch API](https://learn.microsoft.com/rest/api/storageservices/blob-batch).
|
||||
* Added support for bearer challenge for identity based managed disks.
|
||||
* Added support for GetAccountInfo to container and blob level clients.
|
||||
* Added [UploadBlobFromURL API](https://learn.microsoft.com/rest/api/storageservices/put-blob-from-url).
|
||||
* Added support for CopySourceAuthorization to appendblob.AppendBlockFromURL
|
||||
* Added support for tag permission in Container SAS.
|
||||
|
||||
### Bugs Fixed
|
||||
|
||||
* Fixed time formatting for the conditional request headers. Fixes [#20475](https://github.com/Azure/azure-sdk-for-go/issues/20475).
|
||||
* Fixed an issue where passing a blob tags map of length 0 would result in the x-ms-tags header to be sent to the service with an empty string as value.
|
||||
|
||||
* Fixed block size and number of blocks calculation in `UploadBuffer` and `UploadFile`. Fixes [#20735](https://github.com/Azure/azure-sdk-for-go/issues/20735).
|
||||
|
||||
### Other Changes
|
||||
|
||||
* Add `dragonfly` to the list of build constraints for `blockblob`.
|
||||
* Updating version of azcore to 1.6.0 and azidentity to 1.3.0
|
||||
|
||||
## 1.1.0-beta.1 (2023-05-09)
|
||||
|
||||
### Features Added
|
||||
|
||||
* Added [Blob Batch API](https://learn.microsoft.com/rest/api/storageservices/blob-batch).
|
||||
* Added support for bearer challenge for identity based managed disks.
|
||||
* Added support for GetAccountInfo to container and blob level clients.
|
||||
* Added [UploadBlobFromURL API](https://learn.microsoft.com/rest/api/storageservices/put-blob-from-url).
|
||||
* Added support for CopySourceAuthorization to appendblob.AppendBlockFromURL
|
||||
* Added support for tag permission in Container SAS.
|
||||
|
||||
### Bugs Fixed
|
||||
|
||||
* Fixed time formatting for the conditional request headers. Fixes [#20475](https://github.com/Azure/azure-sdk-for-go/issues/20475).
|
||||
* Fixed an issue where passing a blob tags map of length 0 would result in the x-ms-tags header to be sent to the service with an empty string as value.
|
||||
|
||||
## 1.0.0 (2023-02-07)
|
||||
|
||||
### Features Added
|
||||
|
|
|
|||
152
vendor/github.com/Azure/azure-sdk-for-go/sdk/storage/azblob/README.md
generated
vendored
152
vendor/github.com/Azure/azure-sdk-for-go/sdk/storage/azblob/README.md
generated
vendored
|
|
@ -1,47 +1,51 @@
|
|||
# Azure Blob Storage SDK for Go
|
||||
# Azure Blob Storage module for Go
|
||||
|
||||
> Server Version: 2020-10-02
|
||||
> Service Version: 2020-10-02
|
||||
|
||||
Azure Blob storage is Microsoft's object storage solution for the cloud. Blob
|
||||
storage is optimized for storing massive amounts of unstructured data.
|
||||
Unstructured data is data that does not adhere to a particular data model or
|
||||
definition, such as text or binary data.
|
||||
Azure Blob Storage is Microsoft's object storage solution for the cloud. Blob
|
||||
Storage is optimized for storing massive amounts of unstructured data - data that does not adhere to a particular data model or
|
||||
definition, such as text or binary data. For more information, see [Introduction to Azure Blob Storage](https://learn.microsoft.com/azure/storage/blobs/storage-blobs-introduction).
|
||||
|
||||
[Source code][source] | [API reference documentation][docs] | [REST API documentation][rest_docs] | [Product documentation][product_docs]
|
||||
Use the Azure Blob Storage client module `github.com/Azure/azure-sdk-for-go/sdk/storage/azblob` to:
|
||||
|
||||
* Authenticate clients with Azure Blob Storage
|
||||
* Manipulate containers and blobs in an Azure storage account
|
||||
|
||||
Key links:
|
||||
|
||||
[Source code][source] | [API reference documentation][docs] | [REST API documentation][rest_docs] | [Product documentation][product_docs] | [Samples][go_samples]
|
||||
|
||||
## Getting started
|
||||
|
||||
### Install the package
|
||||
|
||||
Install the Azure Blob Storage SDK for Go with [go get][goget]:
|
||||
|
||||
```Powershell
|
||||
go get github.com/Azure/azure-sdk-for-go/sdk/storage/azblob
|
||||
```
|
||||
|
||||
If you're going to authenticate with Azure Active Directory (recommended), install the [azidentity][azidentity] module.
|
||||
```Powershell
|
||||
go get github.com/Azure/azure-sdk-for-go/sdk/azidentity
|
||||
```
|
||||
|
||||
### Prerequisites
|
||||
|
||||
A supported [Go][godevdl] version (the Azure SDK supports the two most recent Go releases).
|
||||
|
||||
You need an [Azure subscription][azure_sub] and a
|
||||
[Storage Account][storage_account_docs] to use this package.
|
||||
|
||||
To create a new Storage Account, you can use the [Azure Portal][storage_account_create_portal],
|
||||
- Go, version 1.18 or higher - [Install Go](https://go.dev/doc/install)
|
||||
- Azure subscription - [Create a free account](https://azure.microsoft.com/free/)
|
||||
- Azure storage account - To create a storage account, use tools including the [Azure portal][storage_account_create_portal],
|
||||
[Azure PowerShell][storage_account_create_ps], or the [Azure CLI][storage_account_create_cli].
|
||||
Here's an example using the Azure CLI:
|
||||
|
||||
```Powershell
|
||||
```bash
|
||||
az storage account create --name MyStorageAccount --resource-group MyResourceGroup --location westus --sku Standard_LRS
|
||||
```
|
||||
|
||||
### Install the package
|
||||
|
||||
Install the Azure Blob Storage client module for Go with [go get][goget]:
|
||||
|
||||
```bash
|
||||
go get github.com/Azure/azure-sdk-for-go/sdk/storage/azblob
|
||||
```
|
||||
|
||||
If you plan to authenticate with Azure Active Directory (recommended), also install the [azidentity][azidentity] module.
|
||||
|
||||
```bash
|
||||
go get github.com/Azure/azure-sdk-for-go/sdk/azidentity
|
||||
```
|
||||
|
||||
### Authenticate the client
|
||||
|
||||
In order to interact with the Azure Blob Storage service, you'll need to create an instance of the `azblob.Client` type. The [azidentity][azidentity] module makes it easy to add Azure Active Directory support for authenticating Azure SDK clients with their corresponding Azure services.
|
||||
To interact with the Azure Blob Storage service, you'll need to create an instance of the `azblob.Client` type. The [azidentity][azidentity] module makes it easy to add Azure Active Directory support for authenticating Azure SDK clients with their corresponding Azure services.
|
||||
|
||||
```go
|
||||
// create a credential for authenticating with Azure Active Directory
|
||||
|
|
@ -53,11 +57,17 @@ client, err := azblob.NewClient("https://MYSTORAGEACCOUNT.blob.core.windows.net/
|
|||
// TODO: handle err
|
||||
```
|
||||
|
||||
Learn more about enabling Azure Active Directory for authentication with Azure Storage in [our documentation][storage_ad] and [our samples](#next-steps).
|
||||
Learn more about enabling Azure Active Directory for authentication with Azure Storage:
|
||||
|
||||
* [Authorize access to blobs using Azure Active Directory][storage_ad]
|
||||
|
||||
Other options for authentication include connection strings, shared key, shared access signatures (SAS), and anonymous public access. Use the appropriate client constructor function for the authentication mechanism you wish to use. For examples, see:
|
||||
|
||||
* [Blob samples][samples]
|
||||
|
||||
## Key concepts
|
||||
|
||||
Blob storage is designed for:
|
||||
Blob Storage is designed for:
|
||||
|
||||
- Serving images or documents directly to a browser.
|
||||
- Storing files for distributed access.
|
||||
|
|
@ -66,23 +76,41 @@ Blob storage is designed for:
|
|||
- Storing data for backup and restore, disaster recovery, and archiving.
|
||||
- Storing data for analysis by an on-premises or Azure-hosted service.
|
||||
|
||||
Blob storage offers three types of resources:
|
||||
Blob Storage offers three types of resources:
|
||||
|
||||
- The _storage account_
|
||||
- One or more _containers_ in a storage account
|
||||
- One ore more _blobs_ in a container
|
||||
- One or more _blobs_ in a container
|
||||
|
||||
Instances of the `azblob.Client` type provide methods for manipulating containers and blobs within a storage account.
|
||||
The storage account is specified when the `azblob.Client` is constructed.
|
||||
Use the appropriate client constructor function for the authentication mechanism you wish to use.
|
||||
|
||||
Learn more about options for authentication _(including Connection Strings, Shared Key, Shared Access Signatures (SAS), Azure Active Directory (AAD), and anonymous public access)_ [in our examples.](https://github.com/Azure/azure-sdk-for-go/blob/main/sdk/storage/azblob/examples_test.go)
|
||||
### Specialized clients
|
||||
|
||||
The Azure Blob Storage client module for Go also provides specialized clients in various subpackages. Use these clients when you need to interact with a specific kind of blob. Learn more about [block blobs, append blobs, and page blobs](https://learn.microsoft.com/rest/api/storageservices/understanding-block-blobs--append-blobs--and-page-blobs).
|
||||
|
||||
- [appendblob][append_blob]
|
||||
- [blockblob][block_blob]
|
||||
- [pageblob][page_blob]
|
||||
|
||||
The [blob][blob] package contains APIs common to all blob types. This includes APIs for deleting and undeleting a blob, setting metadata, and more.
|
||||
|
||||
The [lease][lease] package contains clients for managing leases on blobs and containers. See the [REST API reference](https://learn.microsoft.com/rest/api/storageservices/lease-blob#remarks) for general information on leases.
|
||||
|
||||
The [container][container] package contains APIs specific to containers. This includes APIs for setting access policies or properties, and more.
|
||||
|
||||
The [service][service] package contains APIs specific to the Blob service. This includes APIs for manipulating containers, retrieving account information, and more.
|
||||
|
||||
The [sas][sas] package contains utilities to aid in the creation and manipulation of shared access signature (SAS) tokens.
|
||||
See the package's documentation for more information.
|
||||
|
||||
### Goroutine safety
|
||||
We guarantee that all client instance methods are goroutine-safe and independent of each other ([guideline](https://azure.github.io/azure-sdk/golang_introduction.html#thread-safety)). This ensures that the recommendation of reusing client instances is always safe, even across goroutines.
|
||||
|
||||
### About blob metadata
|
||||
Blob metadata name/value pairs are valid HTTP headers and should adhere to all restrictions governing HTTP headers. Metadata names must be valid HTTP header names, may contain only ASCII characters, and should be treated as case-insensitive. Base64-encode or URL-encode metadata values containing non-ASCII characters.
|
||||
We guarantee that all client instance methods are goroutine-safe and independent of each other (see [guideline](https://azure.github.io/azure-sdk/golang_introduction.html#thread-safety)). This ensures that the recommendation to reuse client instances is always safe, even across goroutines.
|
||||
|
||||
### Blob metadata
|
||||
|
||||
Blob metadata name-value pairs are valid HTTP headers and should adhere to all restrictions governing HTTP headers. Metadata names must be valid HTTP header names, may contain only ASCII characters, and should be treated as case-insensitive. Base64-encode or URL-encode metadata values containing non-ASCII characters.
|
||||
|
||||
### Additional concepts
|
||||
<!-- CLIENT COMMON BAR -->
|
||||
|
|
@ -94,7 +122,7 @@ Blob metadata name/value pairs are valid HTTP headers and should adhere to all r
|
|||
|
||||
## Examples
|
||||
|
||||
### Uploading a blob
|
||||
### Upload a blob
|
||||
|
||||
```go
|
||||
const (
|
||||
|
|
@ -122,7 +150,7 @@ _, err = client.UploadFile(context.TODO(), containerName, blobName, file, nil)
|
|||
// TODO: handle error
|
||||
```
|
||||
|
||||
### Downloading a blob
|
||||
### Download a blob
|
||||
|
||||
```go
|
||||
// this example accesses a public blob via anonymous access, so no credentials are required
|
||||
|
|
@ -139,7 +167,7 @@ _, err = client.DownloadFile(context.TODO(), "samples", "cloud.jpg", file, nil)
|
|||
// TODO: handle error
|
||||
```
|
||||
|
||||
### Enumerating blobs
|
||||
### Enumerate blobs
|
||||
|
||||
```go
|
||||
const (
|
||||
|
|
@ -177,7 +205,7 @@ All Blob service operations will return an
|
|||
[*azcore.ResponseError][azcore_response_error] on failure with a
|
||||
populated `ErrorCode` field. Many of these errors are recoverable.
|
||||
The [bloberror][blob_error] package provides the possible Storage error codes
|
||||
along with various helper facilities for error handling.
|
||||
along with helper facilities for error handling.
|
||||
|
||||
```go
|
||||
const (
|
||||
|
|
@ -201,28 +229,7 @@ if bloberror.HasCode(err, bloberror.ContainerBeingDeleted, bloberror.ContainerNo
|
|||
|
||||
## Next steps
|
||||
|
||||
Get started with our [Blob samples][samples]. They contain complete examples of the above snippets and more.
|
||||
|
||||
### Specialized clients
|
||||
|
||||
The Azure Blob Storage SDK for Go also provides specialized clients in various subpackages.
|
||||
Use these clients when you need to interact with a specific kind of blob.
|
||||
Learn more about the various types of blobs from the following links.
|
||||
|
||||
- [appendblob][append_blob] - [REST docs](https://docs.microsoft.com/rest/api/storageservices/understanding-block-blobs--append-blobs--and-page-blobs#about-append-blobs)
|
||||
- [blockblob][block_blob] - [REST docs](https://docs.microsoft.com/rest/api/storageservices/understanding-block-blobs--append-blobs--and-page-blobs#about-block-blobs)
|
||||
- [pageblob][page_blob] - [REST docs](https://docs.microsoft.com/rest/api/storageservices/understanding-block-blobs--append-blobs--and-page-blobs#about-page-blobs)
|
||||
|
||||
The [blob][blob] package contains APIs common to all blob types. This includes APIs for deleting and undeleting a blob, setting metadata, and more.
|
||||
|
||||
The [lease][lease] package contains clients for managing leases on blobs and containers. Please see the [reference docs](https://docs.microsoft.com/rest/api/storageservices/lease-blob#remarks) for general information on leases.
|
||||
|
||||
The [container][container] package contains APIs specific to containers. This includes APIs setting access policies or properties, and more.
|
||||
|
||||
The [service][service] package contains APIs specific to blob service. This includes APIs for manipulating containers, retrieving account information, and more.
|
||||
|
||||
The [sas][sas] package contains utilities to aid in the creation and manipulation of Shared Access Signature tokens.
|
||||
See the package's documentation for more information.
|
||||
Get started with our [Blob samples][samples]. They contain complete examples of the above snippets and more.
|
||||
|
||||
## Contributing
|
||||
|
||||
|
|
@ -243,19 +250,20 @@ additional questions or comments.
|
|||
|
||||
<!-- LINKS -->
|
||||
[source]: https://github.com/Azure/azure-sdk-for-go/tree/main/sdk/storage/azblob
|
||||
[docs]: https://pkg.go.dev/github.com/Azure/azure-sdk-for-go/sdk/storage/azblob
|
||||
[rest_docs]: https://docs.microsoft.com/rest/api/storageservices/blob-service-rest-api
|
||||
[product_docs]: https://docs.microsoft.com/azure/storage/blobs/storage-blobs-overview
|
||||
[docs]: https://pkg.go.dev/github.com/Azure/azure-sdk-for-go/sdk/storage/azblob#section_documentation
|
||||
[rest_docs]: https://learn.microsoft.com/rest/api/storageservices/blob-service-rest-api
|
||||
[product_docs]: https://learn.microsoft.com/azure/storage/blobs/storage-blobs-overview
|
||||
[godevdl]: https://go.dev/dl/
|
||||
[goget]: https://pkg.go.dev/cmd/go#hdr-Add_dependencies_to_current_module_and_install_them
|
||||
[storage_account_docs]: https://docs.microsoft.com/azure/storage/common/storage-account-overview
|
||||
[storage_account_create_ps]: https://docs.microsoft.com/azure/storage/common/storage-quickstart-create-account?tabs=azure-powershell
|
||||
[storage_account_create_cli]: https://docs.microsoft.com/azure/storage/common/storage-quickstart-create-account?tabs=azure-cli
|
||||
[storage_account_create_portal]: https://docs.microsoft.com/azure/storage/common/storage-quickstart-create-account?tabs=azure-portal
|
||||
[azure_cli]: https://docs.microsoft.com/cli/azure
|
||||
[go_samples]: https://github.com/Azure-Samples/azure-sdk-for-go-samples/tree/main
|
||||
[storage_account_docs]: https://learn.microsoft.com/azure/storage/common/storage-account-overview
|
||||
[storage_account_create_ps]: https://learn.microsoft.com/azure/storage/common/storage-quickstart-create-account?tabs=azure-powershell
|
||||
[storage_account_create_cli]: https://learn.microsoft.com/azure/storage/common/storage-quickstart-create-account?tabs=azure-cli
|
||||
[storage_account_create_portal]: https://learn.microsoft.com/azure/storage/common/storage-quickstart-create-account?tabs=azure-portal
|
||||
[azure_cli]: https://learn.microsoft.com/cli/azure
|
||||
[azure_sub]: https://azure.microsoft.com/free/
|
||||
[azidentity]: https://pkg.go.dev/github.com/Azure/azure-sdk-for-go/sdk/azidentity
|
||||
[storage_ad]: https://docs.microsoft.com/azure/storage/common/storage-auth-aad
|
||||
[storage_ad]: https://learn.microsoft.com/azure/storage/common/storage-auth-aad
|
||||
[azcore_response_error]: https://pkg.go.dev/github.com/Azure/azure-sdk-for-go/sdk/azcore#ResponseError
|
||||
[samples]: https://github.com/Azure/azure-sdk-for-go/blob/main/sdk/storage/azblob/examples_test.go
|
||||
[append_blob]: https://github.com/Azure/azure-sdk-for-go/tree/main/sdk/storage/azblob/appendblob/client.go
|
||||
|
|
|
|||
29
vendor/github.com/Azure/azure-sdk-for-go/sdk/storage/azblob/appendblob/client.go
generated
vendored
29
vendor/github.com/Azure/azure-sdk-for-go/sdk/storage/azblob/appendblob/client.go
generated
vendored
|
|
@ -8,6 +8,7 @@ package appendblob
|
|||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"io"
|
||||
"os"
|
||||
"time"
|
||||
|
|
@ -22,9 +23,7 @@ import (
|
|||
)
|
||||
|
||||
// ClientOptions contains the optional parameters when creating a Client.
|
||||
type ClientOptions struct {
|
||||
azcore.ClientOptions
|
||||
}
|
||||
type ClientOptions base.ClientOptions
|
||||
|
||||
// Client represents a client to an Azure Storage append blob;
|
||||
type Client base.CompositeClient[generated.BlobClient, generated.AppendBlobClient]
|
||||
|
|
@ -34,7 +33,7 @@ type Client base.CompositeClient[generated.BlobClient, generated.AppendBlobClien
|
|||
// - cred - an Azure AD credential, typically obtained via the azidentity module
|
||||
// - options - client options; pass nil to accept the default values
|
||||
func NewClient(blobURL string, cred azcore.TokenCredential, options *ClientOptions) (*Client, error) {
|
||||
authPolicy := runtime.NewBearerTokenPolicy(cred, []string{shared.TokenScope}, nil)
|
||||
authPolicy := shared.NewStorageChallengePolicy(cred)
|
||||
conOptions := shared.GetClientOptions(options)
|
||||
conOptions.PerRetryPolicies = append(conOptions.PerRetryPolicies, authPolicy)
|
||||
pl := runtime.NewPipeline(exported.ModuleName,
|
||||
|
|
@ -255,14 +254,10 @@ func (ab *Client) SetLegalHold(ctx context.Context, legalHold bool, options *blo
|
|||
return ab.BlobClient().SetLegalHold(ctx, legalHold, options)
|
||||
}
|
||||
|
||||
// SetTier operation sets the tier on a blob. The operation is allowed on a page
|
||||
// blob in a premium storage account and on a block blob in a blob storage account (locally
|
||||
// redundant storage only). A premium page blob's tier determines the allowed size, IOPS, and
|
||||
// bandwidth of the blob. A block blob's tier determines Hot/Cool/Archive storage type. This operation
|
||||
// does not update the blob's ETag.
|
||||
// For detailed information about block blob level tiering see https://docs.microsoft.com/en-us/azure/storage/blobs/storage-blob-storage-tiers.
|
||||
// SetTier
|
||||
// Deprecated: SetTier only works for page blob in premium storage account and block blob in blob storage account.
|
||||
func (ab *Client) SetTier(ctx context.Context, tier blob.AccessTier, o *blob.SetTierOptions) (blob.SetTierResponse, error) {
|
||||
return ab.BlobClient().SetTier(ctx, tier, o)
|
||||
return blob.SetTierResponse{}, errors.New("operation will not work on this blob type. SetTier only works for page blob in premium storage account and block blob in blob storage account")
|
||||
}
|
||||
|
||||
// SetExpiry operation sets an expiry time on an existing blob. This operation is only allowed on Hierarchical Namespace enabled accounts.
|
||||
|
|
@ -282,6 +277,12 @@ func (ab *Client) GetProperties(ctx context.Context, o *blob.GetPropertiesOption
|
|||
return ab.BlobClient().GetProperties(ctx, o)
|
||||
}
|
||||
|
||||
// GetAccountInfo provides account level information
|
||||
// For more information, see https://learn.microsoft.com/en-us/rest/api/storageservices/get-account-information?tabs=shared-access-signatures.
|
||||
func (ab *Client) GetAccountInfo(ctx context.Context, o *blob.GetAccountInfoOptions) (blob.GetAccountInfoResponse, error) {
|
||||
return ab.BlobClient().GetAccountInfo(ctx, o)
|
||||
}
|
||||
|
||||
// SetHTTPHeaders changes a blob's HTTP headers.
|
||||
// For more information, see https://docs.microsoft.com/rest/api/storageservices/set-blob-properties.
|
||||
func (ab *Client) SetHTTPHeaders(ctx context.Context, HTTPHeaders blob.HTTPHeaders, o *blob.SetHTTPHeadersOptions) (blob.SetHTTPHeadersResponse, error) {
|
||||
|
|
@ -326,10 +327,10 @@ func (ab *Client) GetTags(ctx context.Context, o *blob.GetTagsOptions) (blob.Get
|
|||
return ab.BlobClient().GetTags(ctx, o)
|
||||
}
|
||||
|
||||
// CopyFromURL synchronously copies the data at the source URL to a block blob, with sizes up to 256 MB.
|
||||
// For more information, see https://docs.microsoft.com/en-us/rest/api/storageservices/copy-blob-from-url.
|
||||
// CopyFromURL
|
||||
// Deprecated: CopyFromURL works only with block blob
|
||||
func (ab *Client) CopyFromURL(ctx context.Context, copySource string, o *blob.CopyFromURLOptions) (blob.CopyFromURLResponse, error) {
|
||||
return ab.BlobClient().CopyFromURL(ctx, copySource, o)
|
||||
return blob.CopyFromURLResponse{}, errors.New("operation will not work on this blob type. CopyFromURL works only with block blob")
|
||||
}
|
||||
|
||||
// Concurrent Download Functions -----------------------------------------------------------------------------------------
|
||||
|
|
|
|||
6
vendor/github.com/Azure/azure-sdk-for-go/sdk/storage/azblob/appendblob/models.go
generated
vendored
6
vendor/github.com/Azure/azure-sdk-for-go/sdk/storage/azblob/appendblob/models.go
generated
vendored
|
|
@ -100,6 +100,9 @@ func (o *AppendBlockOptions) format() (*generated.AppendBlobClientAppendBlockOpt
|
|||
|
||||
// AppendBlockFromURLOptions contains the optional parameters for the Client.AppendBlockFromURL method.
|
||||
type AppendBlockFromURLOptions struct {
|
||||
// Only Bearer type is supported. Credentials should be a valid OAuth access token to copy source.
|
||||
CopySourceAuthorization *string
|
||||
|
||||
// SourceContentValidation contains the validation mechanism used on the range of bytes read from the source.
|
||||
SourceContentValidation blob.SourceContentValidationType
|
||||
|
||||
|
|
@ -125,7 +128,8 @@ func (o *AppendBlockFromURLOptions) format() (*generated.AppendBlobClientAppendB
|
|||
}
|
||||
|
||||
options := &generated.AppendBlobClientAppendBlockFromURLOptions{
|
||||
SourceRange: exported.FormatHTTPRange(o.Range),
|
||||
SourceRange: exported.FormatHTTPRange(o.Range),
|
||||
CopySourceAuthorization: o.CopySourceAuthorization,
|
||||
}
|
||||
|
||||
if o.SourceContentValidation != nil {
|
||||
|
|
|
|||
2
vendor/github.com/Azure/azure-sdk-for-go/sdk/storage/azblob/assets.json
generated
vendored
2
vendor/github.com/Azure/azure-sdk-for-go/sdk/storage/azblob/assets.json
generated
vendored
|
|
@ -2,5 +2,5 @@
|
|||
"AssetsRepo": "Azure/azure-sdk-assets",
|
||||
"AssetsRepoPrefixPath": "go",
|
||||
"TagPrefix": "go/storage/azblob",
|
||||
"Tag": "go/storage/azblob_46e572d43a"
|
||||
"Tag": "go/storage/azblob_a772b9c866"
|
||||
}
|
||||
|
|
|
|||
29
vendor/github.com/Azure/azure-sdk-for-go/sdk/storage/azblob/blob/client.go
generated
vendored
29
vendor/github.com/Azure/azure-sdk-for-go/sdk/storage/azblob/blob/client.go
generated
vendored
|
|
@ -25,9 +25,7 @@ import (
|
|||
)
|
||||
|
||||
// ClientOptions contains the optional parameters when creating a Client.
|
||||
type ClientOptions struct {
|
||||
azcore.ClientOptions
|
||||
}
|
||||
type ClientOptions base.ClientOptions
|
||||
|
||||
// Client represents a URL to an Azure Storage blob; the blob may be a block blob, append blob, or page blob.
|
||||
type Client base.Client[generated.BlobClient]
|
||||
|
|
@ -37,12 +35,12 @@ type Client base.Client[generated.BlobClient]
|
|||
// - cred - an Azure AD credential, typically obtained via the azidentity module
|
||||
// - options - client options; pass nil to accept the default values
|
||||
func NewClient(blobURL string, cred azcore.TokenCredential, options *ClientOptions) (*Client, error) {
|
||||
authPolicy := runtime.NewBearerTokenPolicy(cred, []string{shared.TokenScope}, nil)
|
||||
authPolicy := shared.NewStorageChallengePolicy(cred)
|
||||
conOptions := shared.GetClientOptions(options)
|
||||
conOptions.PerRetryPolicies = append(conOptions.PerRetryPolicies, authPolicy)
|
||||
pl := runtime.NewPipeline(exported.ModuleName, exported.ModuleVersion, runtime.PipelineOptions{}, &conOptions.ClientOptions)
|
||||
|
||||
return (*Client)(base.NewBlobClient(blobURL, pl, nil)), nil
|
||||
return (*Client)(base.NewBlobClient(blobURL, pl, &cred)), nil
|
||||
}
|
||||
|
||||
// NewClientWithNoCredential creates an instance of Client with the specified values.
|
||||
|
|
@ -100,6 +98,10 @@ func (b *Client) sharedKey() *SharedKeyCredential {
|
|||
return base.SharedKey((*base.Client[generated.BlobClient])(b))
|
||||
}
|
||||
|
||||
func (b *Client) credential() any {
|
||||
return base.Credential((*base.Client[generated.BlobClient])(b))
|
||||
}
|
||||
|
||||
// URL returns the URL endpoint used by the Client object.
|
||||
func (b *Client) URL() string {
|
||||
return b.generated().Endpoint()
|
||||
|
|
@ -114,7 +116,7 @@ func (b *Client) WithSnapshot(snapshot string) (*Client, error) {
|
|||
}
|
||||
p.Snapshot = snapshot
|
||||
|
||||
return (*Client)(base.NewBlobClient(p.String(), b.generated().Pipeline(), b.sharedKey())), nil
|
||||
return (*Client)(base.NewBlobClient(p.String(), b.generated().Pipeline(), b.credential())), nil
|
||||
}
|
||||
|
||||
// WithVersionID creates a new AppendBlobURL object identical to the source but with the specified version id.
|
||||
|
|
@ -126,7 +128,7 @@ func (b *Client) WithVersionID(versionID string) (*Client, error) {
|
|||
}
|
||||
p.VersionID = versionID
|
||||
|
||||
return (*Client)(base.NewBlobClient(p.String(), b.generated().Pipeline(), b.sharedKey())), nil
|
||||
return (*Client)(base.NewBlobClient(p.String(), b.generated().Pipeline(), b.credential())), nil
|
||||
}
|
||||
|
||||
// Delete marks the specified blob or snapshot for deletion. The blob is later deleted during garbage collection.
|
||||
|
|
@ -264,6 +266,14 @@ func (b *Client) CopyFromURL(ctx context.Context, copySource string, options *Co
|
|||
return resp, err
|
||||
}
|
||||
|
||||
// GetAccountInfo provides account level information
|
||||
// For more information, see https://learn.microsoft.com/en-us/rest/api/storageservices/get-account-information?tabs=shared-access-signatures.
|
||||
func (b *Client) GetAccountInfo(ctx context.Context, o *GetAccountInfoOptions) (GetAccountInfoResponse, error) {
|
||||
getAccountInfoOptions := o.format()
|
||||
resp, err := b.generated().GetAccountInfo(ctx, getAccountInfoOptions)
|
||||
return resp, err
|
||||
}
|
||||
|
||||
// GetSASURL is a convenience method for generating a SAS token for the currently pointed at blob.
|
||||
// It can only be used if the credential supplied during creation was a SharedKeyCredential.
|
||||
func (b *Client) GetSASURL(permissions sas.BlobPermissions, expiry time.Time, o *GetSASURLOptions) (string, error) {
|
||||
|
|
@ -313,12 +323,11 @@ func (b *Client) download(ctx context.Context, writer io.WriterAt, o downloadOpt
|
|||
count := o.Range.Count
|
||||
if count == CountToEnd { // If size not specified, calculate it
|
||||
// If we don't have the length at all, get it
|
||||
downloadBlobOptions := o.getDownloadBlobOptions(HTTPRange{}, nil)
|
||||
dr, err := b.DownloadStream(ctx, downloadBlobOptions)
|
||||
gr, err := b.GetProperties(ctx, o.getBlobPropertiesOptions())
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
count = *dr.ContentLength - o.Range.Offset
|
||||
count = *gr.ContentLength - o.Range.Offset
|
||||
}
|
||||
|
||||
if count <= 0 {
|
||||
|
|
|
|||
11
vendor/github.com/Azure/azure-sdk-for-go/sdk/storage/azblob/blob/models.go
generated
vendored
11
vendor/github.com/Azure/azure-sdk-for-go/sdk/storage/azblob/blob/models.go
generated
vendored
|
|
@ -565,3 +565,14 @@ func (o *CopyFromURLOptions) format() (*generated.BlobClientCopyFromURLOptions,
|
|||
leaseAccessConditions, modifiedAccessConditions := exported.FormatBlobAccessConditions(o.BlobAccessConditions)
|
||||
return options, o.SourceModifiedAccessConditions, modifiedAccessConditions, leaseAccessConditions
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------------------------------------------------
|
||||
|
||||
// GetAccountInfoOptions provides set of options for Client.GetAccountInfo
|
||||
type GetAccountInfoOptions struct {
|
||||
// placeholder for future options
|
||||
}
|
||||
|
||||
func (o *GetAccountInfoOptions) format() *generated.BlobClientGetAccountInfoOptions {
|
||||
return nil
|
||||
}
|
||||
|
|
|
|||
3
vendor/github.com/Azure/azure-sdk-for-go/sdk/storage/azblob/blob/responses.go
generated
vendored
3
vendor/github.com/Azure/azure-sdk-for-go/sdk/storage/azblob/blob/responses.go
generated
vendored
|
|
@ -100,6 +100,9 @@ type SetLegalHoldResponse = generated.BlobClientSetLegalHoldResponse
|
|||
// CopyFromURLResponse contains the response from method BlobClient.CopyFromURL.
|
||||
type CopyFromURLResponse = generated.BlobClientCopyFromURLResponse
|
||||
|
||||
// GetAccountInfoResponse contains the response from method BlobClient.GetAccountInfo.
|
||||
type GetAccountInfoResponse = generated.BlobClientGetAccountInfoResponse
|
||||
|
||||
// AcquireLeaseResponse contains the response from method BlobClient.AcquireLease.
|
||||
type AcquireLeaseResponse = generated.BlobClientAcquireLeaseResponse
|
||||
|
||||
|
|
|
|||
47
vendor/github.com/Azure/azure-sdk-for-go/sdk/storage/azblob/blockblob/client.go
generated
vendored
47
vendor/github.com/Azure/azure-sdk-for-go/sdk/storage/azblob/blockblob/client.go
generated
vendored
|
|
@ -12,6 +12,7 @@ import (
|
|||
"encoding/base64"
|
||||
"errors"
|
||||
"io"
|
||||
"math"
|
||||
"os"
|
||||
"sync"
|
||||
"time"
|
||||
|
|
@ -30,9 +31,7 @@ import (
|
|||
)
|
||||
|
||||
// ClientOptions contains the optional parameters when creating a Client.
|
||||
type ClientOptions struct {
|
||||
azcore.ClientOptions
|
||||
}
|
||||
type ClientOptions base.ClientOptions
|
||||
|
||||
// Client defines a set of operations applicable to block blobs.
|
||||
type Client base.CompositeClient[generated.BlobClient, generated.BlockBlobClient]
|
||||
|
|
@ -42,7 +41,7 @@ type Client base.CompositeClient[generated.BlobClient, generated.BlockBlobClient
|
|||
// - cred - an Azure AD credential, typically obtained via the azidentity module
|
||||
// - options - client options; pass nil to accept the default values
|
||||
func NewClient(blobURL string, cred azcore.TokenCredential, options *ClientOptions) (*Client, error) {
|
||||
authPolicy := runtime.NewBearerTokenPolicy(cred, []string{shared.TokenScope}, nil)
|
||||
authPolicy := shared.NewStorageChallengePolicy(cred)
|
||||
conOptions := shared.GetClientOptions(options)
|
||||
conOptions.PerRetryPolicies = append(conOptions.PerRetryPolicies, authPolicy)
|
||||
pl := runtime.NewPipeline(exported.ModuleName, exported.ModuleVersion, runtime.PipelineOptions{}, &conOptions.ClientOptions)
|
||||
|
|
@ -165,6 +164,19 @@ func (bb *Client) Upload(ctx context.Context, body io.ReadSeekCloser, options *U
|
|||
return resp, err
|
||||
}
|
||||
|
||||
// UploadBlobFromURL - The Put Blob from URL operation creates a new Block Blob where the contents of the blob are read from
|
||||
// a given URL. Partial updates are not supported with Put Blob from URL; the content of an existing blob is overwritten
|
||||
// with the content of the new blob. To perform partial updates to a block blob’s contents using a source URL, use the Put
|
||||
// Block from URL API in conjunction with Put Block List.
|
||||
// For more information, see https://learn.microsoft.com/rest/api/storageservices/put-blob-from-url
|
||||
func (bb *Client) UploadBlobFromURL(ctx context.Context, copySource string, options *UploadBlobFromURLOptions) (UploadBlobFromURLResponse, error) {
|
||||
opts, httpHeaders, leaseAccessConditions, cpkInfo, cpkSourceInfo, modifiedAccessConditions, sourceModifiedConditions := options.format()
|
||||
|
||||
resp, err := bb.generated().PutBlobFromURL(ctx, int64(0), copySource, opts, httpHeaders, leaseAccessConditions, cpkInfo, cpkSourceInfo, modifiedAccessConditions, sourceModifiedConditions)
|
||||
|
||||
return resp, err
|
||||
}
|
||||
|
||||
// StageBlock uploads the specified block to the block blob's "staging area" to be later committed by a call to CommitBlockList.
|
||||
// Note that the http client closes the body stream after the request is sent to the service.
|
||||
// For more information, see https://docs.microsoft.com/rest/api/storageservices/put-block.
|
||||
|
|
@ -316,6 +328,12 @@ func (bb *Client) GetProperties(ctx context.Context, o *blob.GetPropertiesOption
|
|||
return bb.BlobClient().GetProperties(ctx, o)
|
||||
}
|
||||
|
||||
// GetAccountInfo provides account level information
|
||||
// For more information, see https://learn.microsoft.com/en-us/rest/api/storageservices/get-account-information?tabs=shared-access-signatures.
|
||||
func (bb *Client) GetAccountInfo(ctx context.Context, o *blob.GetAccountInfoOptions) (blob.GetAccountInfoResponse, error) {
|
||||
return bb.BlobClient().GetAccountInfo(ctx, o)
|
||||
}
|
||||
|
||||
// SetHTTPHeaders changes a blob's HTTP headers.
|
||||
// For more information, see https://docs.microsoft.com/rest/api/storageservices/set-blob-properties.
|
||||
func (bb *Client) SetHTTPHeaders(ctx context.Context, HTTPHeaders blob.HTTPHeaders, o *blob.SetHTTPHeadersOptions) (blob.SetHTTPHeadersResponse, error) {
|
||||
|
|
@ -370,31 +388,26 @@ func (bb *Client) CopyFromURL(ctx context.Context, copySource string, o *blob.Co
|
|||
|
||||
// uploadFromReader uploads a buffer in blocks to a block blob.
|
||||
func (bb *Client) uploadFromReader(ctx context.Context, reader io.ReaderAt, actualSize int64, o *uploadFromReaderOptions) (uploadFromReaderResponse, error) {
|
||||
readerSize := actualSize
|
||||
if o.BlockSize == 0 {
|
||||
// If bufferSize > (MaxStageBlockBytes * MaxBlocks), then error
|
||||
if readerSize > MaxStageBlockBytes*MaxBlocks {
|
||||
if actualSize > MaxStageBlockBytes*MaxBlocks {
|
||||
return uploadFromReaderResponse{}, errors.New("buffer is too large to upload to a block blob")
|
||||
}
|
||||
// If bufferSize <= MaxUploadBlobBytes, then Upload should be used with just 1 I/O request
|
||||
if readerSize <= MaxUploadBlobBytes {
|
||||
if actualSize <= MaxUploadBlobBytes {
|
||||
o.BlockSize = MaxUploadBlobBytes // Default if unspecified
|
||||
} else {
|
||||
if remainder := readerSize % MaxBlocks; remainder > 0 {
|
||||
// ensure readerSize is a multiple of MaxBlocks
|
||||
readerSize += (MaxBlocks - remainder)
|
||||
}
|
||||
o.BlockSize = readerSize / MaxBlocks // buffer / max blocks = block size to use all 50,000 blocks
|
||||
if o.BlockSize < blob.DefaultDownloadBlockSize { // If the block size is smaller than 4MB, round up to 4MB
|
||||
o.BlockSize = int64(math.Ceil(float64(actualSize) / MaxBlocks)) // ceil(buffer / max blocks) = block size to use all 50,000 blocks
|
||||
if o.BlockSize < blob.DefaultDownloadBlockSize { // If the block size is smaller than 4MB, round up to 4MB
|
||||
o.BlockSize = blob.DefaultDownloadBlockSize
|
||||
}
|
||||
// StageBlock will be called with blockSize blocks and a Concurrency of (BufferSize / BlockSize).
|
||||
}
|
||||
}
|
||||
|
||||
if readerSize <= MaxUploadBlobBytes {
|
||||
if actualSize <= MaxUploadBlobBytes {
|
||||
// If the size can fit in 1 Upload call, do it this way
|
||||
var body io.ReadSeeker = io.NewSectionReader(reader, 0, readerSize)
|
||||
var body io.ReadSeeker = io.NewSectionReader(reader, 0, actualSize)
|
||||
if o.Progress != nil {
|
||||
body = streaming.NewRequestProgress(shared.NopCloser(body), o.Progress)
|
||||
}
|
||||
|
|
@ -405,7 +418,7 @@ func (bb *Client) uploadFromReader(ctx context.Context, reader io.ReaderAt, actu
|
|||
return toUploadReaderAtResponseFromUploadResponse(resp), err
|
||||
}
|
||||
|
||||
var numBlocks = uint16(((readerSize - 1) / o.BlockSize) + 1)
|
||||
var numBlocks = uint16(((actualSize - 1) / o.BlockSize) + 1)
|
||||
if numBlocks > MaxBlocks {
|
||||
// prevent any math bugs from attempting to upload too many blocks which will always fail
|
||||
return uploadFromReaderResponse{}, errors.New("block limit exceeded")
|
||||
|
|
@ -425,7 +438,7 @@ func (bb *Client) uploadFromReader(ctx context.Context, reader io.ReaderAt, actu
|
|||
|
||||
err := shared.DoBatchTransfer(ctx, &shared.BatchTransferOptions{
|
||||
OperationName: "uploadFromReader",
|
||||
TransferSize: readerSize,
|
||||
TransferSize: actualSize,
|
||||
ChunkSize: o.BlockSize,
|
||||
Concurrency: o.Concurrency,
|
||||
Operation: func(ctx context.Context, offset int64, chunkSize int64) error {
|
||||
|
|
|
|||
4
vendor/github.com/Azure/azure-sdk-for-go/sdk/storage/azblob/blockblob/mmf_unix.go
generated
vendored
4
vendor/github.com/Azure/azure-sdk-for-go/sdk/storage/azblob/blockblob/mmf_unix.go
generated
vendored
|
|
@ -1,6 +1,6 @@
|
|||
//go:build go1.18 && (linux || darwin || freebsd || openbsd || netbsd || solaris)
|
||||
//go:build go1.18 && (linux || darwin || dragonfly || freebsd || openbsd || netbsd || solaris || aix)
|
||||
// +build go1.18
|
||||
// +build linux darwin freebsd openbsd netbsd solaris
|
||||
// +build linux darwin dragonfly freebsd openbsd netbsd solaris aix
|
||||
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// Licensed under the MIT License. See License.txt in the project root for license information.
|
||||
|
|
|
|||
4
vendor/github.com/Azure/azure-sdk-for-go/sdk/storage/azblob/blockblob/mmf_windows.go
generated
vendored
4
vendor/github.com/Azure/azure-sdk-for-go/sdk/storage/azblob/blockblob/mmf_windows.go
generated
vendored
|
|
@ -26,7 +26,9 @@ func newMMB(size int64) (mmb, error) {
|
|||
if err != nil {
|
||||
return nil, os.NewSyscallError("CreateFileMapping", err)
|
||||
}
|
||||
defer syscall.CloseHandle(hMMF)
|
||||
defer func() {
|
||||
_ = syscall.CloseHandle(hMMF)
|
||||
}()
|
||||
|
||||
addr, err := syscall.MapViewOfFile(hMMF, access, 0, 0, uintptr(size))
|
||||
if err != nil {
|
||||
|
|
|
|||
50
vendor/github.com/Azure/azure-sdk-for-go/sdk/storage/azblob/blockblob/models.go
generated
vendored
50
vendor/github.com/Azure/azure-sdk-for-go/sdk/storage/azblob/blockblob/models.go
generated
vendored
|
|
@ -70,6 +70,56 @@ func (o *UploadOptions) format() (*generated.BlockBlobClientUploadOptions, *gene
|
|||
|
||||
// ---------------------------------------------------------------------------------------------------------------------
|
||||
|
||||
// UploadBlobFromURLOptions contains the optional parameters for the Client.UploadBlobFromURL method.
|
||||
type UploadBlobFromURLOptions struct {
|
||||
// Optional. Used to set blob tags in various blob operations.
|
||||
Tags map[string]string
|
||||
|
||||
// Only Bearer type is supported. Credentials should be a valid OAuth access token to copy source.
|
||||
CopySourceAuthorization *string
|
||||
|
||||
// Optional, default is true. Indicates if properties from the source blob should be copied.
|
||||
CopySourceBlobProperties *bool
|
||||
|
||||
// Optional. Specifies a user-defined name-value pair associated with the blob.
|
||||
Metadata map[string]*string
|
||||
|
||||
// Optional. Specifies the md5 calculated for the range of bytes that must be read from the copy source.
|
||||
SourceContentMD5 []byte
|
||||
|
||||
// Optional. Indicates the tier to be set on the blob.
|
||||
Tier *blob.AccessTier
|
||||
|
||||
// Additional optional headers
|
||||
HTTPHeaders *blob.HTTPHeaders
|
||||
AccessConditions *blob.AccessConditions
|
||||
CPKInfo *blob.CPKInfo
|
||||
CPKScopeInfo *blob.CPKScopeInfo
|
||||
SourceModifiedAccessConditions *blob.SourceModifiedAccessConditions
|
||||
}
|
||||
|
||||
func (o *UploadBlobFromURLOptions) format() (*generated.BlockBlobClientPutBlobFromURLOptions, *generated.BlobHTTPHeaders,
|
||||
*generated.LeaseAccessConditions, *generated.CPKInfo, *generated.CPKScopeInfo, *generated.ModifiedAccessConditions,
|
||||
*generated.SourceModifiedAccessConditions) {
|
||||
if o == nil {
|
||||
return nil, nil, nil, nil, nil, nil, nil
|
||||
}
|
||||
|
||||
options := generated.BlockBlobClientPutBlobFromURLOptions{
|
||||
BlobTagsString: shared.SerializeBlobTagsToStrPtr(o.Tags),
|
||||
CopySourceAuthorization: o.CopySourceAuthorization,
|
||||
CopySourceBlobProperties: o.CopySourceBlobProperties,
|
||||
Metadata: o.Metadata,
|
||||
SourceContentMD5: o.SourceContentMD5,
|
||||
Tier: o.Tier,
|
||||
}
|
||||
|
||||
leaseAccessConditions, modifiedAccessConditions := exported.FormatBlobAccessConditions(o.AccessConditions)
|
||||
return &options, o.HTTPHeaders, leaseAccessConditions, o.CPKInfo, o.CPKScopeInfo, modifiedAccessConditions, o.SourceModifiedAccessConditions
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------------------------------------------------
|
||||
|
||||
// StageBlockOptions contains the optional parameters for the Client.StageBlock method.
|
||||
type StageBlockOptions struct {
|
||||
CPKInfo *blob.CPKInfo
|
||||
|
|
|
|||
3
vendor/github.com/Azure/azure-sdk-for-go/sdk/storage/azblob/blockblob/responses.go
generated
vendored
3
vendor/github.com/Azure/azure-sdk-for-go/sdk/storage/azblob/blockblob/responses.go
generated
vendored
|
|
@ -16,6 +16,9 @@ import (
|
|||
// UploadResponse contains the response from method Client.Upload.
|
||||
type UploadResponse = generated.BlockBlobClientUploadResponse
|
||||
|
||||
// UploadBlobFromURLResponse contains the response from the method Client.UploadBlobFromURL
|
||||
type UploadBlobFromURLResponse = generated.BlockBlobClientPutBlobFromURLResponse
|
||||
|
||||
// StageBlockResponse contains the response from method Client.StageBlock.
|
||||
type StageBlockResponse = generated.BlockBlobClientStageBlockResponse
|
||||
|
||||
|
|
|
|||
5
vendor/github.com/Azure/azure-sdk-for-go/sdk/storage/azblob/ci.yml
generated
vendored
5
vendor/github.com/Azure/azure-sdk-for-go/sdk/storage/azblob/ci.yml
generated
vendored
|
|
@ -26,3 +26,8 @@ stages:
|
|||
parameters:
|
||||
ServiceDirectory: 'storage/azblob'
|
||||
RunLiveTests: true
|
||||
EnvVars:
|
||||
AZURE_CLIENT_ID: $(AZBLOB_CLIENT_ID)
|
||||
AZURE_TENANT_ID: $(AZBLOB_TENANT_ID)
|
||||
AZURE_CLIENT_SECRET: $(AZBLOB_CLIENT_SECRET)
|
||||
AZURE_SUBSCRIPTION_ID: $(AZBLOB_SUBSCRIPTION_ID)
|
||||
|
|
|
|||
5
vendor/github.com/Azure/azure-sdk-for-go/sdk/storage/azblob/client.go
generated
vendored
5
vendor/github.com/Azure/azure-sdk-for-go/sdk/storage/azblob/client.go
generated
vendored
|
|
@ -13,14 +13,13 @@ import (
|
|||
|
||||
"github.com/Azure/azure-sdk-for-go/sdk/azcore"
|
||||
"github.com/Azure/azure-sdk-for-go/sdk/azcore/runtime"
|
||||
"github.com/Azure/azure-sdk-for-go/sdk/storage/azblob/internal/base"
|
||||
"github.com/Azure/azure-sdk-for-go/sdk/storage/azblob/internal/shared"
|
||||
"github.com/Azure/azure-sdk-for-go/sdk/storage/azblob/service"
|
||||
)
|
||||
|
||||
// ClientOptions contains the optional parameters when creating a Client.
|
||||
type ClientOptions struct {
|
||||
azcore.ClientOptions
|
||||
}
|
||||
type ClientOptions base.ClientOptions
|
||||
|
||||
// Client represents a URL to an Azure Storage blob; the blob may be a block blob, append blob, or page blob.
|
||||
type Client struct {
|
||||
|
|
|
|||
94
vendor/github.com/Azure/azure-sdk-for-go/sdk/storage/azblob/container/batch_builder.go
generated
vendored
Normal file
94
vendor/github.com/Azure/azure-sdk-for-go/sdk/storage/azblob/container/batch_builder.go
generated
vendored
Normal file
|
|
@ -0,0 +1,94 @@
|
|||
//go:build go1.18
|
||||
// +build go1.18
|
||||
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// Licensed under the MIT License. See License.txt in the project root for license information.
|
||||
|
||||
package container
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"net/url"
|
||||
|
||||
"github.com/Azure/azure-sdk-for-go/sdk/azcore/policy"
|
||||
"github.com/Azure/azure-sdk-for-go/sdk/azcore/runtime"
|
||||
"github.com/Azure/azure-sdk-for-go/sdk/storage/azblob/blob"
|
||||
"github.com/Azure/azure-sdk-for-go/sdk/storage/azblob/internal/exported"
|
||||
)
|
||||
|
||||
// BatchBuilder is used for creating the batch operations list. It contains the list of either delete or set tier sub-requests.
|
||||
// NOTE: All sub-requests in the batch must be of the same type, either delete or set tier.
|
||||
type BatchBuilder struct {
|
||||
endpoint string
|
||||
authPolicy policy.Policy
|
||||
subRequests []*policy.Request
|
||||
operationType *exported.BlobBatchOperationType
|
||||
}
|
||||
|
||||
func (bb *BatchBuilder) checkOperationType(operationType exported.BlobBatchOperationType) error {
|
||||
if bb.operationType == nil {
|
||||
bb.operationType = &operationType
|
||||
return nil
|
||||
}
|
||||
if *bb.operationType != operationType {
|
||||
return fmt.Errorf("BlobBatch only supports one operation type per batch and is already being used for %s operations", *bb.operationType)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// Delete operation is used to add delete sub-request to the batch builder.
|
||||
func (bb *BatchBuilder) Delete(blobName string, options *BatchDeleteOptions) error {
|
||||
err := bb.checkOperationType(exported.BatchDeleteOperationType)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
blobName = url.PathEscape(blobName)
|
||||
blobURL := runtime.JoinPaths(bb.endpoint, blobName)
|
||||
|
||||
blobClient, err := blob.NewClientWithNoCredential(blobURL, nil)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
deleteOptions, leaseInfo, accessConditions := options.format()
|
||||
req, err := getGeneratedBlobClient(blobClient).DeleteCreateRequest(context.TODO(), deleteOptions, leaseInfo, accessConditions)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// remove x-ms-version header
|
||||
exported.UpdateSubRequestHeaders(req)
|
||||
|
||||
bb.subRequests = append(bb.subRequests, req)
|
||||
return nil
|
||||
}
|
||||
|
||||
// SetTier operation is used to add set tier sub-request to the batch builder.
|
||||
func (bb *BatchBuilder) SetTier(blobName string, accessTier blob.AccessTier, options *BatchSetTierOptions) error {
|
||||
err := bb.checkOperationType(exported.BatchSetTierOperationType)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
blobName = url.PathEscape(blobName)
|
||||
blobURL := runtime.JoinPaths(bb.endpoint, blobName)
|
||||
|
||||
blobClient, err := blob.NewClientWithNoCredential(blobURL, nil)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
setTierOptions, leaseInfo, accessConditions := options.format()
|
||||
req, err := getGeneratedBlobClient(blobClient).SetTierCreateRequest(context.TODO(), accessTier, setTierOptions, leaseInfo, accessConditions)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// remove x-ms-version header
|
||||
exported.UpdateSubRequestHeaders(req)
|
||||
|
||||
bb.subRequests = append(bb.subRequests, req)
|
||||
return nil
|
||||
}
|
||||
97
vendor/github.com/Azure/azure-sdk-for-go/sdk/storage/azblob/container/client.go
generated
vendored
97
vendor/github.com/Azure/azure-sdk-for-go/sdk/storage/azblob/container/client.go
generated
vendored
|
|
@ -7,7 +7,11 @@
|
|||
package container
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"context"
|
||||
"errors"
|
||||
"fmt"
|
||||
"github.com/Azure/azure-sdk-for-go/sdk/azcore/streaming"
|
||||
"github.com/Azure/azure-sdk-for-go/sdk/storage/azblob/bloberror"
|
||||
"net/http"
|
||||
"net/url"
|
||||
|
|
@ -28,9 +32,7 @@ import (
|
|||
)
|
||||
|
||||
// ClientOptions contains the optional parameters when creating a Client.
|
||||
type ClientOptions struct {
|
||||
azcore.ClientOptions
|
||||
}
|
||||
type ClientOptions base.ClientOptions
|
||||
|
||||
// Client represents a URL to the Azure Storage container allowing you to manipulate its blobs.
|
||||
type Client base.Client[generated.ContainerClient]
|
||||
|
|
@ -40,12 +42,12 @@ type Client base.Client[generated.ContainerClient]
|
|||
// - cred - an Azure AD credential, typically obtained via the azidentity module
|
||||
// - options - client options; pass nil to accept the default values
|
||||
func NewClient(containerURL string, cred azcore.TokenCredential, options *ClientOptions) (*Client, error) {
|
||||
authPolicy := runtime.NewBearerTokenPolicy(cred, []string{shared.TokenScope}, nil)
|
||||
authPolicy := shared.NewStorageChallengePolicy(cred)
|
||||
conOptions := shared.GetClientOptions(options)
|
||||
conOptions.PerRetryPolicies = append(conOptions.PerRetryPolicies, authPolicy)
|
||||
pl := runtime.NewPipeline(exported.ModuleName, exported.ModuleVersion, runtime.PipelineOptions{}, &conOptions.ClientOptions)
|
||||
|
||||
return (*Client)(base.NewContainerClient(containerURL, pl, nil)), nil
|
||||
return (*Client)(base.NewContainerClient(containerURL, pl, &cred)), nil
|
||||
}
|
||||
|
||||
// NewClientWithNoCredential creates an instance of Client with the specified values.
|
||||
|
|
@ -102,6 +104,15 @@ func (c *Client) sharedKey() *SharedKeyCredential {
|
|||
return base.SharedKey((*base.Client[generated.ContainerClient])(c))
|
||||
}
|
||||
|
||||
func (c *Client) credential() any {
|
||||
return base.Credential((*base.Client[generated.ContainerClient])(c))
|
||||
}
|
||||
|
||||
// helper method to return the generated.BlobClient which is used for creating the sub-requests
|
||||
func getGeneratedBlobClient(b *blob.Client) *generated.BlobClient {
|
||||
return base.InnerClient((*base.Client[generated.BlobClient])(b))
|
||||
}
|
||||
|
||||
// URL returns the URL endpoint used by the Client object.
|
||||
func (c *Client) URL() string {
|
||||
return c.generated().Endpoint()
|
||||
|
|
@ -113,7 +124,7 @@ func (c *Client) URL() string {
|
|||
func (c *Client) NewBlobClient(blobName string) *blob.Client {
|
||||
blobName = url.PathEscape(blobName)
|
||||
blobURL := runtime.JoinPaths(c.URL(), blobName)
|
||||
return (*blob.Client)(base.NewBlobClient(blobURL, c.generated().Pipeline(), c.sharedKey()))
|
||||
return (*blob.Client)(base.NewBlobClient(blobURL, c.generated().Pipeline(), c.credential()))
|
||||
}
|
||||
|
||||
// NewAppendBlobClient creates a new appendblob.Client object by concatenating blobName to the end of
|
||||
|
|
@ -190,7 +201,7 @@ func (c *Client) Restore(ctx context.Context, deletedContainerVersion string, op
|
|||
// For more information, see https://docs.microsoft.com/rest/api/storageservices/get-container-metadata.
|
||||
func (c *Client) GetProperties(ctx context.Context, o *GetPropertiesOptions) (GetPropertiesResponse, error) {
|
||||
// NOTE: GetMetadata actually calls GetProperties internally because GetProperties returns the metadata AND the properties.
|
||||
// This allows us to not expose a GetProperties method at all simplifying the API.
|
||||
// This allows us to not expose a GetMetadata method at all simplifying the API.
|
||||
// The optionals are nil, like they were in track 1.5
|
||||
opts, leaseAccessConditions := o.format()
|
||||
|
||||
|
|
@ -226,6 +237,14 @@ func (c *Client) SetAccessPolicy(ctx context.Context, o *SetAccessPolicyOptions)
|
|||
return resp, err
|
||||
}
|
||||
|
||||
// GetAccountInfo provides account level information
|
||||
// For more information, see https://learn.microsoft.com/en-us/rest/api/storageservices/get-account-information?tabs=shared-access-signatures.
|
||||
func (c *Client) GetAccountInfo(ctx context.Context, o *GetAccountInfoOptions) (GetAccountInfoResponse, error) {
|
||||
getAccountInfoOptions := o.format()
|
||||
resp, err := c.generated().GetAccountInfo(ctx, getAccountInfoOptions)
|
||||
return resp, err
|
||||
}
|
||||
|
||||
// NewListBlobsFlatPager returns a pager for blobs starting from the specified Marker. Use an empty
|
||||
// Marker to start enumeration from the beginning. Blob names are returned in lexicographic order.
|
||||
// For more information, see https://docs.microsoft.com/rest/api/storageservices/list-blobs.
|
||||
|
|
@ -329,3 +348,67 @@ func (c *Client) GetSASURL(permissions sas.ContainerPermissions, expiry time.Tim
|
|||
|
||||
return endpoint, nil
|
||||
}
|
||||
|
||||
// NewBatchBuilder creates an instance of BatchBuilder using the same auth policy as the client.
|
||||
// BatchBuilder is used to build the batch consisting of either delete or set tier sub-requests.
|
||||
// All sub-requests in the batch must be of the same type, either delete or set tier.
|
||||
func (c *Client) NewBatchBuilder() (*BatchBuilder, error) {
|
||||
var authPolicy policy.Policy
|
||||
|
||||
switch cred := c.credential().(type) {
|
||||
case *azcore.TokenCredential:
|
||||
authPolicy = shared.NewStorageChallengePolicy(*cred)
|
||||
case *SharedKeyCredential:
|
||||
authPolicy = exported.NewSharedKeyCredPolicy(cred)
|
||||
case nil:
|
||||
// for authentication using SAS
|
||||
authPolicy = nil
|
||||
default:
|
||||
return nil, fmt.Errorf("unrecognised authentication type %T", cred)
|
||||
}
|
||||
|
||||
return &BatchBuilder{
|
||||
endpoint: c.URL(),
|
||||
authPolicy: authPolicy,
|
||||
}, nil
|
||||
}
|
||||
|
||||
// SubmitBatch operation allows multiple API calls to be embedded into a single HTTP request.
|
||||
// It builds the request body using the BatchBuilder object passed.
|
||||
// BatchBuilder contains the list of operations to be submitted. It supports up to 256 sub-requests in a single batch.
|
||||
// For more information, see https://docs.microsoft.com/rest/api/storageservices/blob-batch.
|
||||
func (c *Client) SubmitBatch(ctx context.Context, bb *BatchBuilder, options *SubmitBatchOptions) (SubmitBatchResponse, error) {
|
||||
if bb == nil || len(bb.subRequests) == 0 {
|
||||
return SubmitBatchResponse{}, errors.New("batch builder is empty")
|
||||
}
|
||||
|
||||
// create the request body
|
||||
batchReq, batchID, err := exported.CreateBatchRequest(&exported.BlobBatchBuilder{
|
||||
AuthPolicy: bb.authPolicy,
|
||||
SubRequests: bb.subRequests,
|
||||
})
|
||||
if err != nil {
|
||||
return SubmitBatchResponse{}, err
|
||||
}
|
||||
|
||||
reader := bytes.NewReader(batchReq)
|
||||
rsc := streaming.NopCloser(reader)
|
||||
multipartContentType := "multipart/mixed; boundary=" + batchID
|
||||
|
||||
resp, err := c.generated().SubmitBatch(ctx, int64(len(batchReq)), multipartContentType, rsc, options.format())
|
||||
if err != nil {
|
||||
return SubmitBatchResponse{}, err
|
||||
}
|
||||
|
||||
batchResponses, err := exported.ParseBlobBatchResponse(resp.Body, resp.ContentType, bb.subRequests)
|
||||
if err != nil {
|
||||
return SubmitBatchResponse{}, err
|
||||
}
|
||||
|
||||
return SubmitBatchResponse{
|
||||
Responses: batchResponses,
|
||||
ContentType: resp.ContentType,
|
||||
RequestID: resp.RequestID,
|
||||
Version: resp.Version,
|
||||
}, nil
|
||||
}
|
||||
|
|
|
|||
68
vendor/github.com/Azure/azure-sdk-for-go/sdk/storage/azblob/container/models.go
generated
vendored
68
vendor/github.com/Azure/azure-sdk-for-go/sdk/storage/azblob/container/models.go
generated
vendored
|
|
@ -7,6 +7,7 @@
|
|||
package container
|
||||
|
||||
import (
|
||||
"github.com/Azure/azure-sdk-for-go/sdk/storage/azblob/blob"
|
||||
"reflect"
|
||||
"time"
|
||||
|
||||
|
|
@ -329,3 +330,70 @@ func formatTime(c *SignedIdentifier) error {
|
|||
|
||||
return nil
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------------------------------------------------
|
||||
|
||||
// GetAccountInfoOptions provides set of options for Client.GetAccountInfo
|
||||
type GetAccountInfoOptions struct {
|
||||
// placeholder for future options
|
||||
}
|
||||
|
||||
func (o *GetAccountInfoOptions) format() *generated.ContainerClientGetAccountInfoOptions {
|
||||
return nil
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------------------------------------------------
|
||||
|
||||
// BatchDeleteOptions contains the optional parameters for the BatchBuilder.Delete method.
|
||||
type BatchDeleteOptions struct {
|
||||
blob.DeleteOptions
|
||||
VersionID *string
|
||||
Snapshot *string
|
||||
}
|
||||
|
||||
func (o *BatchDeleteOptions) format() (*generated.BlobClientDeleteOptions, *generated.LeaseAccessConditions, *generated.ModifiedAccessConditions) {
|
||||
if o == nil {
|
||||
return nil, nil, nil
|
||||
}
|
||||
|
||||
basics := generated.BlobClientDeleteOptions{
|
||||
DeleteSnapshots: o.DeleteSnapshots,
|
||||
DeleteType: o.BlobDeleteType, // None by default
|
||||
Snapshot: o.Snapshot,
|
||||
VersionID: o.VersionID,
|
||||
}
|
||||
|
||||
leaseAccessConditions, modifiedAccessConditions := exported.FormatBlobAccessConditions(o.AccessConditions)
|
||||
return &basics, leaseAccessConditions, modifiedAccessConditions
|
||||
}
|
||||
|
||||
// BatchSetTierOptions contains the optional parameters for the BatchBuilder.SetTier method.
|
||||
type BatchSetTierOptions struct {
|
||||
blob.SetTierOptions
|
||||
VersionID *string
|
||||
Snapshot *string
|
||||
}
|
||||
|
||||
func (o *BatchSetTierOptions) format() (*generated.BlobClientSetTierOptions, *generated.LeaseAccessConditions, *generated.ModifiedAccessConditions) {
|
||||
if o == nil {
|
||||
return nil, nil, nil
|
||||
}
|
||||
|
||||
basics := generated.BlobClientSetTierOptions{
|
||||
RehydratePriority: o.RehydratePriority,
|
||||
Snapshot: o.Snapshot,
|
||||
VersionID: o.VersionID,
|
||||
}
|
||||
|
||||
leaseAccessConditions, modifiedAccessConditions := exported.FormatBlobAccessConditions(o.AccessConditions)
|
||||
return &basics, leaseAccessConditions, modifiedAccessConditions
|
||||
}
|
||||
|
||||
// SubmitBatchOptions contains the optional parameters for the Client.SubmitBatch method.
|
||||
type SubmitBatchOptions struct {
|
||||
// placeholder for future options
|
||||
}
|
||||
|
||||
func (o *SubmitBatchOptions) format() *generated.ContainerClientSubmitBatchOptions {
|
||||
return nil
|
||||
}
|
||||
|
|
|
|||
22
vendor/github.com/Azure/azure-sdk-for-go/sdk/storage/azblob/container/responses.go
generated
vendored
22
vendor/github.com/Azure/azure-sdk-for-go/sdk/storage/azblob/container/responses.go
generated
vendored
|
|
@ -7,6 +7,7 @@
|
|||
package container
|
||||
|
||||
import (
|
||||
"github.com/Azure/azure-sdk-for-go/sdk/storage/azblob/internal/exported"
|
||||
"github.com/Azure/azure-sdk-for-go/sdk/storage/azblob/internal/generated"
|
||||
)
|
||||
|
||||
|
|
@ -42,3 +43,24 @@ type GetAccessPolicyResponse = generated.ContainerClientGetAccessPolicyResponse
|
|||
|
||||
// SetAccessPolicyResponse contains the response from method Client.SetAccessPolicy.
|
||||
type SetAccessPolicyResponse = generated.ContainerClientSetAccessPolicyResponse
|
||||
|
||||
// GetAccountInfoResponse contains the response from method Client.GetAccountInfo.
|
||||
type GetAccountInfoResponse = generated.ContainerClientGetAccountInfoResponse
|
||||
|
||||
// SubmitBatchResponse contains the response from method Client.SubmitBatch.
|
||||
type SubmitBatchResponse struct {
|
||||
// Responses contains the responses of the sub-requests in the batch
|
||||
Responses []*BatchResponseItem
|
||||
|
||||
// ContentType contains the information returned from the Content-Type header response.
|
||||
ContentType *string
|
||||
|
||||
// RequestID contains the information returned from the x-ms-request-id header response.
|
||||
RequestID *string
|
||||
|
||||
// Version contains the information returned from the x-ms-version header response.
|
||||
Version *string
|
||||
}
|
||||
|
||||
// BatchResponseItem contains the response for the individual sub-requests.
|
||||
type BatchResponseItem = exported.BatchResponseItem
|
||||
|
|
|
|||
43
vendor/github.com/Azure/azure-sdk-for-go/sdk/storage/azblob/doc.go
generated
vendored
43
vendor/github.com/Azure/azure-sdk-for-go/sdk/storage/azblob/doc.go
generated
vendored
|
|
@ -51,7 +51,7 @@ Use the key as the credential parameter to authenticate the client:
|
|||
cred, err := azblob.NewSharedKeyCredential(accountName, accountKey)
|
||||
handle(err)
|
||||
|
||||
serviceClient, err := azblob.NewServiceClientWithSharedKey(serviceURL, cred, nil)
|
||||
serviceClient, err := azblob.NewClientWithSharedKeyCredential(serviceURL, cred, nil)
|
||||
handle(err)
|
||||
|
||||
fmt.Println(serviceClient.URL())
|
||||
|
|
@ -59,11 +59,12 @@ Use the key as the credential parameter to authenticate the client:
|
|||
Using a Connection String
|
||||
|
||||
Depending on your use case and authorization method, you may prefer to initialize a client instance with a connection string instead of providing the account URL and credential separately.
|
||||
To do this, pass the connection string to the service client's `NewServiceClientFromConnectionString` method.
|
||||
To do this, pass the connection string to the service client's `NewClientFromConnectionString` method.
|
||||
The connection string can be found in your storage account in the Azure Portal under the "Access Keys" section.
|
||||
|
||||
connStr := "DefaultEndpointsProtocol=https;AccountName=<my_account_name>;AccountKey=<my_account_key>;EndpointSuffix=core.windows.net"
|
||||
serviceClient, err := azblob.NewServiceClientFromConnectionString(connStr, nil)
|
||||
serviceClient, err := azblob.NewClientFromConnectionString(connStr, nil)
|
||||
handle(err)
|
||||
|
||||
Using a Shared Access Signature (SAS) Token
|
||||
|
||||
|
|
@ -82,20 +83,20 @@ You can generate a SAS token from the Azure Portal under Shared Access Signature
|
|||
|
||||
cred, err := azblob.NewSharedKeyCredential(accountName, accountKey)
|
||||
handle(err)
|
||||
serviceClient, err := azblob.NewServiceClientWithSharedKey(serviceURL, cred, nil)
|
||||
serviceClient, err := azblob.NewClientWithSharedKeyCredential(serviceURL, cred, nil)
|
||||
handle(err)
|
||||
fmt.Println(serviceClient.URL())
|
||||
|
||||
// Alternatively, you can create SAS on the fly
|
||||
|
||||
resources := azblob.AccountSASResourceTypes{Service: true}
|
||||
permission := azblob.AccountSASPermissions{Read: true}
|
||||
resources := sas.AccountResourceTypes{Service: true}
|
||||
permission := sas.AccountPermissions{Read: true}
|
||||
start := time.Now()
|
||||
expiry := start.AddDate(0, 0, 1)
|
||||
serviceURLWithSAS, err := serviceClient.GetSASURL(resources, permission, start, expiry)
|
||||
serviceURLWithSAS, err := serviceClient.ServiceClient().GetSASURL(resources, permission, expiry, &service.GetSASURLOptions{StartTime: &start})
|
||||
handle(err)
|
||||
|
||||
serviceClientWithSAS, err := azblob.NewServiceClientWithNoCredential(serviceURLWithSAS, nil)
|
||||
serviceClientWithSAS, err := azblob.NewClientWithNoCredential(serviceURLWithSAS, nil)
|
||||
handle(err)
|
||||
|
||||
fmt.Println(serviceClientWithSAS.URL())
|
||||
|
|
@ -135,13 +136,13 @@ Examples
|
|||
handle(err)
|
||||
|
||||
// The service URL for blob endpoints is usually in the form: http(s)://<account>.blob.core.windows.net/
|
||||
serviceClient, err := azblob.NewServiceClientWithSharedKey(fmt.Sprintf("https://%s.blob.core.windows.net/", accountName), cred, nil)
|
||||
serviceClient, err := azblob.NewClientWithSharedKeyCredential(fmt.Sprintf("https://%s.blob.core.windows.net/", accountName), cred, nil)
|
||||
handle(err)
|
||||
|
||||
// ===== 1. Create a container =====
|
||||
|
||||
// First, create a container client, and use the Create method to create a new container in your account
|
||||
containerClient, err := serviceClient.NewContainerClient("testcontainer")
|
||||
containerClient := serviceClient.ServiceClient().NewContainerClient("testcontainer")
|
||||
handle(err)
|
||||
|
||||
// All APIs have an options' bag struct as a parameter.
|
||||
|
|
@ -154,13 +155,13 @@ Examples
|
|||
uploadData := "Hello world!"
|
||||
|
||||
// Create a new blockBlobClient from the containerClient
|
||||
blockBlobClient, err := containerClient.NewBlockBlobClient("HelloWorld.txt")
|
||||
blockBlobClient := containerClient.NewBlockBlobClient("HelloWorld.txt")
|
||||
handle(err)
|
||||
|
||||
// Upload data to the block blob
|
||||
blockBlobUploadOptions := azblob.BlockBlobUploadOptions{
|
||||
Metadata: map[string]string{"Foo": "Bar"},
|
||||
TagsMap: map[string]string{"Year": "2022"},
|
||||
blockBlobUploadOptions := blockblob.UploadOptions{
|
||||
Metadata: map[string]*string{"Foo": to.Ptr("Bar")},
|
||||
Tags: map[string]string{"Year": "2022"},
|
||||
}
|
||||
_, err = blockBlobClient.Upload(context.TODO(), streaming.NopCloser(strings.NewReader(uploadData)), &blockBlobUploadOptions)
|
||||
handle(err)
|
||||
|
|
@ -175,10 +176,9 @@ Examples
|
|||
downloadData, err := io.ReadAll(reader)
|
||||
handle(err)
|
||||
if string(downloadData) != uploadData {
|
||||
handle(errors.New("Uploaded data should be same as downloaded data"))
|
||||
handle(errors.New("uploaded data should be same as downloaded data"))
|
||||
}
|
||||
|
||||
|
||||
if err = reader.Close(); err != nil {
|
||||
handle(err)
|
||||
return
|
||||
|
|
@ -189,18 +189,15 @@ Examples
|
|||
// To iterate over a page use the NextPage(context.Context) to fetch the next page of results.
|
||||
// PageResponse() can be used to iterate over the results of the specific page.
|
||||
// Always check the Err() method after paging to see if an error was returned by the pager. A pager will return either an error or the page of results.
|
||||
pager := containerClient.ListBlobsFlat(nil)
|
||||
for pager.NextPage(context.TODO()) {
|
||||
resp := pager.PageResponse()
|
||||
pager := containerClient.NewListBlobsFlatPager(nil)
|
||||
for pager.More() {
|
||||
resp, err := pager.NextPage(context.TODO())
|
||||
handle(err)
|
||||
for _, v := range resp.Segment.BlobItems {
|
||||
fmt.Println(*v.Name)
|
||||
}
|
||||
}
|
||||
|
||||
if err = pager.Err(); err != nil {
|
||||
handle(err)
|
||||
}
|
||||
|
||||
// Delete the blob.
|
||||
_, err = blockBlobClient.Delete(context.TODO(), nil)
|
||||
handle(err)
|
||||
|
|
|
|||
39
vendor/github.com/Azure/azure-sdk-for-go/sdk/storage/azblob/internal/base/clients.go
generated
vendored
39
vendor/github.com/Azure/azure-sdk-for-go/sdk/storage/azblob/internal/base/clients.go
generated
vendored
|
|
@ -7,14 +7,20 @@
|
|||
package base
|
||||
|
||||
import (
|
||||
"github.com/Azure/azure-sdk-for-go/sdk/azcore"
|
||||
"github.com/Azure/azure-sdk-for-go/sdk/azcore/runtime"
|
||||
"github.com/Azure/azure-sdk-for-go/sdk/storage/azblob/internal/exported"
|
||||
"github.com/Azure/azure-sdk-for-go/sdk/storage/azblob/internal/generated"
|
||||
)
|
||||
|
||||
// ClientOptions contains the optional parameters when creating a Client.
|
||||
type ClientOptions struct {
|
||||
azcore.ClientOptions
|
||||
}
|
||||
|
||||
type Client[T any] struct {
|
||||
inner *T
|
||||
sharedKey *exported.SharedKeyCredential
|
||||
inner *T
|
||||
credential any
|
||||
}
|
||||
|
||||
func InnerClient[T any](client *Client[T]) *T {
|
||||
|
|
@ -22,31 +28,40 @@ func InnerClient[T any](client *Client[T]) *T {
|
|||
}
|
||||
|
||||
func SharedKey[T any](client *Client[T]) *exported.SharedKeyCredential {
|
||||
return client.sharedKey
|
||||
switch cred := client.credential.(type) {
|
||||
case *exported.SharedKeyCredential:
|
||||
return cred
|
||||
default:
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
func Credential[T any](client *Client[T]) any {
|
||||
return client.credential
|
||||
}
|
||||
|
||||
func NewClient[T any](inner *T) *Client[T] {
|
||||
return &Client[T]{inner: inner}
|
||||
}
|
||||
|
||||
func NewServiceClient(containerURL string, pipeline runtime.Pipeline, sharedKey *exported.SharedKeyCredential) *Client[generated.ServiceClient] {
|
||||
func NewServiceClient(containerURL string, pipeline runtime.Pipeline, credential any) *Client[generated.ServiceClient] {
|
||||
return &Client[generated.ServiceClient]{
|
||||
inner: generated.NewServiceClient(containerURL, pipeline),
|
||||
sharedKey: sharedKey,
|
||||
inner: generated.NewServiceClient(containerURL, pipeline),
|
||||
credential: credential,
|
||||
}
|
||||
}
|
||||
|
||||
func NewContainerClient(containerURL string, pipeline runtime.Pipeline, sharedKey *exported.SharedKeyCredential) *Client[generated.ContainerClient] {
|
||||
func NewContainerClient(containerURL string, pipeline runtime.Pipeline, credential any) *Client[generated.ContainerClient] {
|
||||
return &Client[generated.ContainerClient]{
|
||||
inner: generated.NewContainerClient(containerURL, pipeline),
|
||||
sharedKey: sharedKey,
|
||||
inner: generated.NewContainerClient(containerURL, pipeline),
|
||||
credential: credential,
|
||||
}
|
||||
}
|
||||
|
||||
func NewBlobClient(blobURL string, pipeline runtime.Pipeline, sharedKey *exported.SharedKeyCredential) *Client[generated.BlobClient] {
|
||||
func NewBlobClient(blobURL string, pipeline runtime.Pipeline, credential any) *Client[generated.BlobClient] {
|
||||
return &Client[generated.BlobClient]{
|
||||
inner: generated.NewBlobClient(blobURL, pipeline),
|
||||
sharedKey: sharedKey,
|
||||
inner: generated.NewBlobClient(blobURL, pipeline),
|
||||
credential: credential,
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
279
vendor/github.com/Azure/azure-sdk-for-go/sdk/storage/azblob/internal/exported/blob_batch.go
generated
vendored
Normal file
279
vendor/github.com/Azure/azure-sdk-for-go/sdk/storage/azblob/internal/exported/blob_batch.go
generated
vendored
Normal file
|
|
@ -0,0 +1,279 @@
|
|||
//go:build go1.18
|
||||
// +build go1.18
|
||||
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// Licensed under the MIT License. See License.txt in the project root for license information.
|
||||
|
||||
package exported
|
||||
|
||||
import (
|
||||
"bufio"
|
||||
"bytes"
|
||||
"errors"
|
||||
"fmt"
|
||||
"github.com/Azure/azure-sdk-for-go/sdk/azcore/policy"
|
||||
"github.com/Azure/azure-sdk-for-go/sdk/azcore/runtime"
|
||||
"github.com/Azure/azure-sdk-for-go/sdk/azcore/to"
|
||||
"github.com/Azure/azure-sdk-for-go/sdk/internal/log"
|
||||
"github.com/Azure/azure-sdk-for-go/sdk/internal/uuid"
|
||||
"github.com/Azure/azure-sdk-for-go/sdk/storage/azblob/internal/shared"
|
||||
"io"
|
||||
"mime"
|
||||
"mime/multipart"
|
||||
"net/http"
|
||||
"net/textproto"
|
||||
"strconv"
|
||||
"strings"
|
||||
)
|
||||
|
||||
const (
|
||||
batchIdPrefix = "batch_"
|
||||
httpVersion = "HTTP/1.1"
|
||||
httpNewline = "\r\n"
|
||||
)
|
||||
|
||||
// createBatchID is used for creating a new batch id which is used as batch boundary in the request body
|
||||
func createBatchID() (string, error) {
|
||||
batchID, err := uuid.New()
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
return batchIdPrefix + batchID.String(), nil
|
||||
}
|
||||
|
||||
// buildSubRequest is used for building the sub-request. Example:
|
||||
// DELETE /container0/blob0 HTTP/1.1
|
||||
// x-ms-date: Thu, 14 Jun 2018 16:46:54 GMT
|
||||
// Authorization: SharedKey account:G4jjBXA7LI/RnWKIOQ8i9xH4p76pAQ+4Fs4R1VxasaE=
|
||||
// Content-Length: 0
|
||||
func buildSubRequest(req *policy.Request) []byte {
|
||||
var batchSubRequest strings.Builder
|
||||
blobPath := req.Raw().URL.Path
|
||||
if len(req.Raw().URL.RawQuery) > 0 {
|
||||
blobPath += "?" + req.Raw().URL.RawQuery
|
||||
}
|
||||
|
||||
batchSubRequest.WriteString(fmt.Sprintf("%s %s %s%s", req.Raw().Method, blobPath, httpVersion, httpNewline))
|
||||
|
||||
for k, v := range req.Raw().Header {
|
||||
if strings.EqualFold(k, shared.HeaderXmsVersion) {
|
||||
continue
|
||||
}
|
||||
if len(v) > 0 {
|
||||
batchSubRequest.WriteString(fmt.Sprintf("%v: %v%v", k, v[0], httpNewline))
|
||||
}
|
||||
}
|
||||
|
||||
batchSubRequest.WriteString(httpNewline)
|
||||
return []byte(batchSubRequest.String())
|
||||
}
|
||||
|
||||
// CreateBatchRequest creates a new batch request using the sub-requests present in the BlobBatchBuilder.
|
||||
//
|
||||
// Example of a sub-request in the batch request body:
|
||||
//
|
||||
// --batch_357de4f7-6d0b-4e02-8cd2-6361411a9525
|
||||
// Content-Type: application/http
|
||||
// Content-Transfer-Encoding: binary
|
||||
// Content-ID: 0
|
||||
//
|
||||
// DELETE /container0/blob0 HTTP/1.1
|
||||
// x-ms-date: Thu, 14 Jun 2018 16:46:54 GMT
|
||||
// Authorization: SharedKey account:G4jjBXA7LI/RnWKIOQ8i9xH4p76pAQ+4Fs4R1VxasaE=
|
||||
// Content-Length: 0
|
||||
func CreateBatchRequest(bb *BlobBatchBuilder) ([]byte, string, error) {
|
||||
batchID, err := createBatchID()
|
||||
if err != nil {
|
||||
return nil, "", err
|
||||
}
|
||||
|
||||
// Create a new multipart buffer
|
||||
reqBody := &bytes.Buffer{}
|
||||
writer := multipart.NewWriter(reqBody)
|
||||
|
||||
// Set the boundary
|
||||
err = writer.SetBoundary(batchID)
|
||||
if err != nil {
|
||||
return nil, "", err
|
||||
}
|
||||
|
||||
partHeaders := make(textproto.MIMEHeader)
|
||||
partHeaders["Content-Type"] = []string{"application/http"}
|
||||
partHeaders["Content-Transfer-Encoding"] = []string{"binary"}
|
||||
var partWriter io.Writer
|
||||
|
||||
for i, req := range bb.SubRequests {
|
||||
if bb.AuthPolicy != nil {
|
||||
_, err := bb.AuthPolicy.Do(req)
|
||||
if err != nil && !strings.EqualFold(err.Error(), "no more policies") {
|
||||
if log.Should(EventSubmitBatch) {
|
||||
log.Writef(EventSubmitBatch, "failed to authorize sub-request for %v.\nError: %v", req.Raw().URL.Path, err.Error())
|
||||
}
|
||||
return nil, "", err
|
||||
}
|
||||
}
|
||||
|
||||
partHeaders["Content-ID"] = []string{fmt.Sprintf("%v", i)}
|
||||
partWriter, err = writer.CreatePart(partHeaders)
|
||||
if err != nil {
|
||||
return nil, "", err
|
||||
}
|
||||
|
||||
_, err = partWriter.Write(buildSubRequest(req))
|
||||
if err != nil {
|
||||
return nil, "", err
|
||||
}
|
||||
}
|
||||
|
||||
// Close the multipart writer
|
||||
err = writer.Close()
|
||||
if err != nil {
|
||||
return nil, "", err
|
||||
}
|
||||
|
||||
return reqBody.Bytes(), batchID, nil
|
||||
}
|
||||
|
||||
// UpdateSubRequestHeaders updates the sub-request headers.
|
||||
// Removes x-ms-version header.
|
||||
func UpdateSubRequestHeaders(req *policy.Request) {
|
||||
// remove x-ms-version header from the request header
|
||||
for k := range req.Raw().Header {
|
||||
if strings.EqualFold(k, shared.HeaderXmsVersion) {
|
||||
delete(req.Raw().Header, k)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// BatchResponseItem contains the response for the individual sub-requests.
|
||||
type BatchResponseItem struct {
|
||||
ContentID *int
|
||||
ContainerName *string
|
||||
BlobName *string
|
||||
RequestID *string
|
||||
Version *string
|
||||
Error error // nil error indicates that the batch sub-request operation is successful
|
||||
}
|
||||
|
||||
func getResponseBoundary(contentType *string) (string, error) {
|
||||
if contentType == nil {
|
||||
return "", fmt.Errorf("Content-Type returned in SubmitBatch response is nil")
|
||||
}
|
||||
|
||||
_, params, err := mime.ParseMediaType(*contentType)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
if val, ok := params["boundary"]; ok {
|
||||
return val, nil
|
||||
} else {
|
||||
return "", fmt.Errorf("batch boundary not present in Content-Type header of the SubmitBatch response.\nContent-Type: %v", *contentType)
|
||||
}
|
||||
}
|
||||
|
||||
func getContentID(part *multipart.Part) (*int, error) {
|
||||
contentID := part.Header.Get("Content-ID")
|
||||
if contentID == "" {
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
val, err := strconv.Atoi(strings.TrimSpace(contentID))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &val, nil
|
||||
}
|
||||
|
||||
func getResponseHeader(key string, resp *http.Response) *string {
|
||||
val := resp.Header.Get(key)
|
||||
if val == "" {
|
||||
return nil
|
||||
}
|
||||
return &val
|
||||
}
|
||||
|
||||
// ParseBlobBatchResponse is used for parsing the batch response body into individual sub-responses for each item in the batch.
|
||||
func ParseBlobBatchResponse(respBody io.ReadCloser, contentType *string, subRequests []*policy.Request) ([]*BatchResponseItem, error) {
|
||||
boundary, err := getResponseBoundary(contentType)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
respReader := multipart.NewReader(respBody, boundary)
|
||||
var responses []*BatchResponseItem
|
||||
|
||||
for {
|
||||
part, err := respReader.NextPart()
|
||||
if errors.Is(err, io.EOF) {
|
||||
break
|
||||
} else if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
batchSubResponse := &BatchResponseItem{}
|
||||
batchSubResponse.ContentID, err = getContentID(part)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if batchSubResponse.ContentID != nil {
|
||||
path := strings.Trim(subRequests[*batchSubResponse.ContentID].Raw().URL.Path, "/")
|
||||
p := strings.Split(path, "/")
|
||||
batchSubResponse.ContainerName = to.Ptr(p[0])
|
||||
batchSubResponse.BlobName = to.Ptr(strings.Join(p[1:], "/"))
|
||||
}
|
||||
|
||||
respBytes, err := io.ReadAll(part)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
respBytes = append(respBytes, byte('\n'))
|
||||
buf := bytes.NewBuffer(respBytes)
|
||||
resp, err := http.ReadResponse(bufio.NewReader(buf), nil)
|
||||
// sub-response parsing error
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
batchSubResponse.RequestID = getResponseHeader(shared.HeaderXmsRequestID, resp)
|
||||
batchSubResponse.Version = getResponseHeader(shared.HeaderXmsVersion, resp)
|
||||
|
||||
// sub-response failure
|
||||
if resp.StatusCode < 200 || resp.StatusCode >= 300 {
|
||||
if len(responses) == 0 && batchSubResponse.ContentID == nil {
|
||||
// this case can happen when the parent request fails.
|
||||
// For example, batch request having more than 256 sub-requests.
|
||||
return nil, fmt.Errorf("%v", string(respBytes))
|
||||
}
|
||||
|
||||
resp.Request = subRequests[*batchSubResponse.ContentID].Raw()
|
||||
batchSubResponse.Error = runtime.NewResponseError(resp)
|
||||
}
|
||||
|
||||
responses = append(responses, batchSubResponse)
|
||||
}
|
||||
|
||||
if len(responses) != len(subRequests) {
|
||||
return nil, fmt.Errorf("expected %v responses, got %v for the batch ID: %v", len(subRequests), len(responses), boundary)
|
||||
}
|
||||
|
||||
return responses, nil
|
||||
}
|
||||
|
||||
// not exported but used for batch request creation
|
||||
|
||||
// BlobBatchBuilder is used for creating the blob batch request
|
||||
type BlobBatchBuilder struct {
|
||||
AuthPolicy policy.Policy
|
||||
SubRequests []*policy.Request
|
||||
}
|
||||
|
||||
// BlobBatchOperationType defines the operation of the blob batch sub-requests.
|
||||
type BlobBatchOperationType string
|
||||
|
||||
const (
|
||||
BatchDeleteOperationType BlobBatchOperationType = "delete"
|
||||
BatchSetTierOperationType BlobBatchOperationType = "set tier"
|
||||
)
|
||||
|
|
@ -1,5 +1,8 @@
|
|||
//go:build go1.18
|
||||
// +build go1.18
|
||||
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// Licensed under the MIT License.
|
||||
// Licensed under the MIT License. See License.txt in the project root for license information.
|
||||
|
||||
package exported
|
||||
|
||||
|
|
@ -11,4 +14,7 @@ import (
|
|||
const (
|
||||
// EventUpload is used when we compute number of blocks to upload and size of each block.
|
||||
EventUpload log.Event = "azblob.Upload"
|
||||
|
||||
// EventSubmitBatch is used for logging events related to submit blob batch operation.
|
||||
EventSubmitBatch log.Event = "azblob.SubmitBatch"
|
||||
)
|
||||
|
|
|
|||
|
|
@ -8,5 +8,5 @@ package exported
|
|||
|
||||
const (
|
||||
ModuleName = "azblob"
|
||||
ModuleVersion = "v1.0.0"
|
||||
ModuleVersion = "v1.1.0"
|
||||
)
|
||||
|
|
|
|||
|
|
@ -30,7 +30,7 @@ directive:
|
|||
where: $
|
||||
transform: >-
|
||||
return $.
|
||||
replace(/func \(client \*ContainerClient\) NewListBlobFlatSegmentPager\(.+\/\/ listBlobFlatSegmentCreateRequest creates the ListBlobFlatSegment request/s, `// listBlobFlatSegmentCreateRequest creates the ListBlobFlatSegment request`).
|
||||
replace(/func \(client \*ContainerClient\) NewListBlobFlatSegmentPager\(.+\/\/ listBlobFlatSegmentCreateRequest creates the ListBlobFlatSegment request/s, `//\n// listBlobFlatSegmentCreateRequest creates the ListBlobFlatSegment request`).
|
||||
replace(/\(client \*ContainerClient\) listBlobFlatSegmentCreateRequest\(/, `(client *ContainerClient) ListBlobFlatSegmentCreateRequest(`).
|
||||
replace(/\(client \*ContainerClient\) listBlobFlatSegmentHandleResponse\(/, `(client *ContainerClient) ListBlobFlatSegmentHandleResponse(`);
|
||||
```
|
||||
|
|
@ -43,7 +43,7 @@ directive:
|
|||
where: $
|
||||
transform: >-
|
||||
return $.
|
||||
replace(/func \(client \*ServiceClient\) NewListContainersSegmentPager\(.+\/\/ listContainersSegmentCreateRequest creates the ListContainersSegment request/s, `// listContainersSegmentCreateRequest creates the ListContainersSegment request`).
|
||||
replace(/func \(client \*ServiceClient\) NewListContainersSegmentPager\(.+\/\/ listContainersSegmentCreateRequest creates the ListContainersSegment request/s, `//\n// listContainersSegmentCreateRequest creates the ListContainersSegment request`).
|
||||
replace(/\(client \*ServiceClient\) listContainersSegmentCreateRequest\(/, `(client *ServiceClient) ListContainersSegmentCreateRequest(`).
|
||||
replace(/\(client \*ServiceClient\) listContainersSegmentHandleResponse\(/, `(client *ServiceClient) ListContainersSegmentHandleResponse(`);
|
||||
```
|
||||
|
|
@ -384,4 +384,54 @@ directive:
|
|||
transform: >-
|
||||
return $.
|
||||
replace(/xml:"CORS>CORSRule"/g, "xml:\"Cors>CorsRule\"");
|
||||
```
|
||||
```
|
||||
|
||||
### Fix Content-Type header in submit batch request
|
||||
|
||||
``` yaml
|
||||
directive:
|
||||
- from:
|
||||
- zz_container_client.go
|
||||
- zz_service_client.go
|
||||
where: $
|
||||
transform: >-
|
||||
return $.
|
||||
replace (/req.SetBody\(body\,\s+\"application\/xml\"\)/g, `req.SetBody(body, multipartContentType)`);
|
||||
```
|
||||
|
||||
### Fix response status code check in submit batch request
|
||||
|
||||
``` yaml
|
||||
directive:
|
||||
- from: zz_service_client.go
|
||||
where: $
|
||||
transform: >-
|
||||
return $.
|
||||
replace(/if\s+!runtime\.HasStatusCode\(resp,\s+http\.StatusOK\)\s+\{\s*\n\t\treturn\s+ServiceClientSubmitBatchResponse\{\}\,\s+runtime\.NewResponseError\(resp\)\s*\n\t\}/g,
|
||||
`if !runtime.HasStatusCode(resp, http.StatusAccepted) {\n\t\treturn ServiceClientSubmitBatchResponse{}, runtime.NewResponseError(resp)\n\t}`);
|
||||
```
|
||||
|
||||
### Convert time to GMT for If-Modified-Since and If-Unmodified-Since request headers
|
||||
|
||||
``` yaml
|
||||
directive:
|
||||
- from:
|
||||
- zz_container_client.go
|
||||
- zz_blob_client.go
|
||||
- zz_appendblob_client.go
|
||||
- zz_blockblob_client.go
|
||||
- zz_pageblob_client.go
|
||||
where: $
|
||||
transform: >-
|
||||
return $.
|
||||
replace (/req\.Raw\(\)\.Header\[\"If-Modified-Since\"\]\s+=\s+\[\]string\{modifiedAccessConditions\.IfModifiedSince\.Format\(time\.RFC1123\)\}/g,
|
||||
`req.Raw().Header["If-Modified-Since"] = []string{(*modifiedAccessConditions.IfModifiedSince).In(gmt).Format(time.RFC1123)}`).
|
||||
replace (/req\.Raw\(\)\.Header\[\"If-Unmodified-Since\"\]\s+=\s+\[\]string\{modifiedAccessConditions\.IfUnmodifiedSince\.Format\(time\.RFC1123\)\}/g,
|
||||
`req.Raw().Header["If-Unmodified-Since"] = []string{(*modifiedAccessConditions.IfUnmodifiedSince).In(gmt).Format(time.RFC1123)}`).
|
||||
replace (/req\.Raw\(\)\.Header\[\"x-ms-source-if-modified-since\"\]\s+=\s+\[\]string\{sourceModifiedAccessConditions\.SourceIfModifiedSince\.Format\(time\.RFC1123\)\}/g,
|
||||
`req.Raw().Header["x-ms-source-if-modified-since"] = []string{(*sourceModifiedAccessConditions.SourceIfModifiedSince).In(gmt).Format(time.RFC1123)}`).
|
||||
replace (/req\.Raw\(\)\.Header\[\"x-ms-source-if-unmodified-since\"\]\s+=\s+\[\]string\{sourceModifiedAccessConditions\.SourceIfUnmodifiedSince\.Format\(time\.RFC1123\)\}/g,
|
||||
`req.Raw().Header["x-ms-source-if-unmodified-since"] = []string{(*sourceModifiedAccessConditions.SourceIfUnmodifiedSince).In(gmt).Format(time.RFC1123)}`).
|
||||
replace (/req\.Raw\(\)\.Header\[\"x-ms-immutability-policy-until-date\"\]\s+=\s+\[\]string\{options\.ImmutabilityPolicyExpiry\.Format\(time\.RFC1123\)\}/g,
|
||||
`req.Raw().Header["x-ms-immutability-policy-until-date"] = []string{(*options.ImmutabilityPolicyExpiry).In(gmt).Format(time.RFC1123)}`);
|
||||
|
||||
|
|
|
|||
|
|
@ -6,7 +6,15 @@
|
|||
|
||||
package generated
|
||||
|
||||
import "github.com/Azure/azure-sdk-for-go/sdk/azcore/runtime"
|
||||
import (
|
||||
"context"
|
||||
"github.com/Azure/azure-sdk-for-go/sdk/azcore/policy"
|
||||
"github.com/Azure/azure-sdk-for-go/sdk/azcore/runtime"
|
||||
"time"
|
||||
)
|
||||
|
||||
// used to convert times from UTC to GMT before sending across the wire
|
||||
var gmt = time.FixedZone("GMT", 0)
|
||||
|
||||
func (client *BlobClient) Endpoint() string {
|
||||
return client.endpoint
|
||||
|
|
@ -15,3 +23,11 @@ func (client *BlobClient) Endpoint() string {
|
|||
func (client *BlobClient) Pipeline() runtime.Pipeline {
|
||||
return client.pl
|
||||
}
|
||||
|
||||
func (client *BlobClient) DeleteCreateRequest(ctx context.Context, options *BlobClientDeleteOptions, leaseAccessConditions *LeaseAccessConditions, modifiedAccessConditions *ModifiedAccessConditions) (*policy.Request, error) {
|
||||
return client.deleteCreateRequest(ctx, options, leaseAccessConditions, modifiedAccessConditions)
|
||||
}
|
||||
|
||||
func (client *BlobClient) SetTierCreateRequest(ctx context.Context, tier AccessTier, options *BlobClientSetTierOptions, leaseAccessConditions *LeaseAccessConditions, modifiedAccessConditions *ModifiedAccessConditions) (*policy.Request, error) {
|
||||
return client.setTierCreateRequest(ctx, tier, options, leaseAccessConditions, modifiedAccessConditions)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -110,10 +110,10 @@ func (client *AppendBlobClient) appendBlockCreateRequest(ctx context.Context, co
|
|||
req.Raw().Header["x-ms-encryption-scope"] = []string{*cpkScopeInfo.EncryptionScope}
|
||||
}
|
||||
if modifiedAccessConditions != nil && modifiedAccessConditions.IfModifiedSince != nil {
|
||||
req.Raw().Header["If-Modified-Since"] = []string{modifiedAccessConditions.IfModifiedSince.Format(time.RFC1123)}
|
||||
req.Raw().Header["If-Modified-Since"] = []string{(*modifiedAccessConditions.IfModifiedSince).In(gmt).Format(time.RFC1123)}
|
||||
}
|
||||
if modifiedAccessConditions != nil && modifiedAccessConditions.IfUnmodifiedSince != nil {
|
||||
req.Raw().Header["If-Unmodified-Since"] = []string{modifiedAccessConditions.IfUnmodifiedSince.Format(time.RFC1123)}
|
||||
req.Raw().Header["If-Unmodified-Since"] = []string{(*modifiedAccessConditions.IfUnmodifiedSince).In(gmt).Format(time.RFC1123)}
|
||||
}
|
||||
if modifiedAccessConditions != nil && modifiedAccessConditions.IfMatch != nil {
|
||||
req.Raw().Header["If-Match"] = []string{string(*modifiedAccessConditions.IfMatch)}
|
||||
|
|
@ -283,10 +283,10 @@ func (client *AppendBlobClient) appendBlockFromURLCreateRequest(ctx context.Cont
|
|||
req.Raw().Header["x-ms-blob-condition-appendpos"] = []string{strconv.FormatInt(*appendPositionAccessConditions.AppendPosition, 10)}
|
||||
}
|
||||
if modifiedAccessConditions != nil && modifiedAccessConditions.IfModifiedSince != nil {
|
||||
req.Raw().Header["If-Modified-Since"] = []string{modifiedAccessConditions.IfModifiedSince.Format(time.RFC1123)}
|
||||
req.Raw().Header["If-Modified-Since"] = []string{(*modifiedAccessConditions.IfModifiedSince).In(gmt).Format(time.RFC1123)}
|
||||
}
|
||||
if modifiedAccessConditions != nil && modifiedAccessConditions.IfUnmodifiedSince != nil {
|
||||
req.Raw().Header["If-Unmodified-Since"] = []string{modifiedAccessConditions.IfUnmodifiedSince.Format(time.RFC1123)}
|
||||
req.Raw().Header["If-Unmodified-Since"] = []string{(*modifiedAccessConditions.IfUnmodifiedSince).In(gmt).Format(time.RFC1123)}
|
||||
}
|
||||
if modifiedAccessConditions != nil && modifiedAccessConditions.IfMatch != nil {
|
||||
req.Raw().Header["If-Match"] = []string{string(*modifiedAccessConditions.IfMatch)}
|
||||
|
|
@ -298,10 +298,10 @@ func (client *AppendBlobClient) appendBlockFromURLCreateRequest(ctx context.Cont
|
|||
req.Raw().Header["x-ms-if-tags"] = []string{*modifiedAccessConditions.IfTags}
|
||||
}
|
||||
if sourceModifiedAccessConditions != nil && sourceModifiedAccessConditions.SourceIfModifiedSince != nil {
|
||||
req.Raw().Header["x-ms-source-if-modified-since"] = []string{sourceModifiedAccessConditions.SourceIfModifiedSince.Format(time.RFC1123)}
|
||||
req.Raw().Header["x-ms-source-if-modified-since"] = []string{(*sourceModifiedAccessConditions.SourceIfModifiedSince).In(gmt).Format(time.RFC1123)}
|
||||
}
|
||||
if sourceModifiedAccessConditions != nil && sourceModifiedAccessConditions.SourceIfUnmodifiedSince != nil {
|
||||
req.Raw().Header["x-ms-source-if-unmodified-since"] = []string{sourceModifiedAccessConditions.SourceIfUnmodifiedSince.Format(time.RFC1123)}
|
||||
req.Raw().Header["x-ms-source-if-unmodified-since"] = []string{(*sourceModifiedAccessConditions.SourceIfUnmodifiedSince).In(gmt).Format(time.RFC1123)}
|
||||
}
|
||||
if sourceModifiedAccessConditions != nil && sourceModifiedAccessConditions.SourceIfMatch != nil {
|
||||
req.Raw().Header["x-ms-source-if-match"] = []string{string(*sourceModifiedAccessConditions.SourceIfMatch)}
|
||||
|
|
@ -467,10 +467,10 @@ func (client *AppendBlobClient) createCreateRequest(ctx context.Context, content
|
|||
req.Raw().Header["x-ms-encryption-scope"] = []string{*cpkScopeInfo.EncryptionScope}
|
||||
}
|
||||
if modifiedAccessConditions != nil && modifiedAccessConditions.IfModifiedSince != nil {
|
||||
req.Raw().Header["If-Modified-Since"] = []string{modifiedAccessConditions.IfModifiedSince.Format(time.RFC1123)}
|
||||
req.Raw().Header["If-Modified-Since"] = []string{(*modifiedAccessConditions.IfModifiedSince).In(gmt).Format(time.RFC1123)}
|
||||
}
|
||||
if modifiedAccessConditions != nil && modifiedAccessConditions.IfUnmodifiedSince != nil {
|
||||
req.Raw().Header["If-Unmodified-Since"] = []string{modifiedAccessConditions.IfUnmodifiedSince.Format(time.RFC1123)}
|
||||
req.Raw().Header["If-Unmodified-Since"] = []string{(*modifiedAccessConditions.IfUnmodifiedSince).In(gmt).Format(time.RFC1123)}
|
||||
}
|
||||
if modifiedAccessConditions != nil && modifiedAccessConditions.IfMatch != nil {
|
||||
req.Raw().Header["If-Match"] = []string{string(*modifiedAccessConditions.IfMatch)}
|
||||
|
|
@ -489,7 +489,7 @@ func (client *AppendBlobClient) createCreateRequest(ctx context.Context, content
|
|||
req.Raw().Header["x-ms-tags"] = []string{*options.BlobTagsString}
|
||||
}
|
||||
if options != nil && options.ImmutabilityPolicyExpiry != nil {
|
||||
req.Raw().Header["x-ms-immutability-policy-until-date"] = []string{options.ImmutabilityPolicyExpiry.Format(time.RFC1123)}
|
||||
req.Raw().Header["x-ms-immutability-policy-until-date"] = []string{(*options.ImmutabilityPolicyExpiry).In(gmt).Format(time.RFC1123)}
|
||||
}
|
||||
if options != nil && options.ImmutabilityPolicyMode != nil {
|
||||
req.Raw().Header["x-ms-immutability-policy-mode"] = []string{string(*options.ImmutabilityPolicyMode)}
|
||||
|
|
@ -601,10 +601,10 @@ func (client *AppendBlobClient) sealCreateRequest(ctx context.Context, options *
|
|||
req.Raw().Header["x-ms-lease-id"] = []string{*leaseAccessConditions.LeaseID}
|
||||
}
|
||||
if modifiedAccessConditions != nil && modifiedAccessConditions.IfModifiedSince != nil {
|
||||
req.Raw().Header["If-Modified-Since"] = []string{modifiedAccessConditions.IfModifiedSince.Format(time.RFC1123)}
|
||||
req.Raw().Header["If-Modified-Since"] = []string{(*modifiedAccessConditions.IfModifiedSince).In(gmt).Format(time.RFC1123)}
|
||||
}
|
||||
if modifiedAccessConditions != nil && modifiedAccessConditions.IfUnmodifiedSince != nil {
|
||||
req.Raw().Header["If-Unmodified-Since"] = []string{modifiedAccessConditions.IfUnmodifiedSince.Format(time.RFC1123)}
|
||||
req.Raw().Header["If-Unmodified-Since"] = []string{(*modifiedAccessConditions.IfUnmodifiedSince).In(gmt).Format(time.RFC1123)}
|
||||
}
|
||||
if modifiedAccessConditions != nil && modifiedAccessConditions.IfMatch != nil {
|
||||
req.Raw().Header["If-Match"] = []string{string(*modifiedAccessConditions.IfMatch)}
|
||||
|
|
|
|||
|
|
@ -152,10 +152,10 @@ func (client *BlobClient) acquireLeaseCreateRequest(ctx context.Context, duratio
|
|||
req.Raw().Header["x-ms-proposed-lease-id"] = []string{*options.ProposedLeaseID}
|
||||
}
|
||||
if modifiedAccessConditions != nil && modifiedAccessConditions.IfModifiedSince != nil {
|
||||
req.Raw().Header["If-Modified-Since"] = []string{modifiedAccessConditions.IfModifiedSince.Format(time.RFC1123)}
|
||||
req.Raw().Header["If-Modified-Since"] = []string{(*modifiedAccessConditions.IfModifiedSince).In(gmt).Format(time.RFC1123)}
|
||||
}
|
||||
if modifiedAccessConditions != nil && modifiedAccessConditions.IfUnmodifiedSince != nil {
|
||||
req.Raw().Header["If-Unmodified-Since"] = []string{modifiedAccessConditions.IfUnmodifiedSince.Format(time.RFC1123)}
|
||||
req.Raw().Header["If-Unmodified-Since"] = []string{(*modifiedAccessConditions.IfUnmodifiedSince).In(gmt).Format(time.RFC1123)}
|
||||
}
|
||||
if modifiedAccessConditions != nil && modifiedAccessConditions.IfMatch != nil {
|
||||
req.Raw().Header["If-Match"] = []string{string(*modifiedAccessConditions.IfMatch)}
|
||||
|
|
@ -247,10 +247,10 @@ func (client *BlobClient) breakLeaseCreateRequest(ctx context.Context, options *
|
|||
req.Raw().Header["x-ms-lease-break-period"] = []string{strconv.FormatInt(int64(*options.BreakPeriod), 10)}
|
||||
}
|
||||
if modifiedAccessConditions != nil && modifiedAccessConditions.IfModifiedSince != nil {
|
||||
req.Raw().Header["If-Modified-Since"] = []string{modifiedAccessConditions.IfModifiedSince.Format(time.RFC1123)}
|
||||
req.Raw().Header["If-Modified-Since"] = []string{(*modifiedAccessConditions.IfModifiedSince).In(gmt).Format(time.RFC1123)}
|
||||
}
|
||||
if modifiedAccessConditions != nil && modifiedAccessConditions.IfUnmodifiedSince != nil {
|
||||
req.Raw().Header["If-Unmodified-Since"] = []string{modifiedAccessConditions.IfUnmodifiedSince.Format(time.RFC1123)}
|
||||
req.Raw().Header["If-Unmodified-Since"] = []string{(*modifiedAccessConditions.IfUnmodifiedSince).In(gmt).Format(time.RFC1123)}
|
||||
}
|
||||
if modifiedAccessConditions != nil && modifiedAccessConditions.IfMatch != nil {
|
||||
req.Raw().Header["If-Match"] = []string{string(*modifiedAccessConditions.IfMatch)}
|
||||
|
|
@ -350,10 +350,10 @@ func (client *BlobClient) changeLeaseCreateRequest(ctx context.Context, leaseID
|
|||
req.Raw().Header["x-ms-lease-id"] = []string{leaseID}
|
||||
req.Raw().Header["x-ms-proposed-lease-id"] = []string{proposedLeaseID}
|
||||
if modifiedAccessConditions != nil && modifiedAccessConditions.IfModifiedSince != nil {
|
||||
req.Raw().Header["If-Modified-Since"] = []string{modifiedAccessConditions.IfModifiedSince.Format(time.RFC1123)}
|
||||
req.Raw().Header["If-Modified-Since"] = []string{(*modifiedAccessConditions.IfModifiedSince).In(gmt).Format(time.RFC1123)}
|
||||
}
|
||||
if modifiedAccessConditions != nil && modifiedAccessConditions.IfUnmodifiedSince != nil {
|
||||
req.Raw().Header["If-Unmodified-Since"] = []string{modifiedAccessConditions.IfUnmodifiedSince.Format(time.RFC1123)}
|
||||
req.Raw().Header["If-Unmodified-Since"] = []string{(*modifiedAccessConditions.IfUnmodifiedSince).In(gmt).Format(time.RFC1123)}
|
||||
}
|
||||
if modifiedAccessConditions != nil && modifiedAccessConditions.IfMatch != nil {
|
||||
req.Raw().Header["If-Match"] = []string{string(*modifiedAccessConditions.IfMatch)}
|
||||
|
|
@ -458,10 +458,10 @@ func (client *BlobClient) copyFromURLCreateRequest(ctx context.Context, copySour
|
|||
req.Raw().Header["x-ms-access-tier"] = []string{string(*options.Tier)}
|
||||
}
|
||||
if sourceModifiedAccessConditions != nil && sourceModifiedAccessConditions.SourceIfModifiedSince != nil {
|
||||
req.Raw().Header["x-ms-source-if-modified-since"] = []string{sourceModifiedAccessConditions.SourceIfModifiedSince.Format(time.RFC1123)}
|
||||
req.Raw().Header["x-ms-source-if-modified-since"] = []string{(*sourceModifiedAccessConditions.SourceIfModifiedSince).In(gmt).Format(time.RFC1123)}
|
||||
}
|
||||
if sourceModifiedAccessConditions != nil && sourceModifiedAccessConditions.SourceIfUnmodifiedSince != nil {
|
||||
req.Raw().Header["x-ms-source-if-unmodified-since"] = []string{sourceModifiedAccessConditions.SourceIfUnmodifiedSince.Format(time.RFC1123)}
|
||||
req.Raw().Header["x-ms-source-if-unmodified-since"] = []string{(*sourceModifiedAccessConditions.SourceIfUnmodifiedSince).In(gmt).Format(time.RFC1123)}
|
||||
}
|
||||
if sourceModifiedAccessConditions != nil && sourceModifiedAccessConditions.SourceIfMatch != nil {
|
||||
req.Raw().Header["x-ms-source-if-match"] = []string{string(*sourceModifiedAccessConditions.SourceIfMatch)}
|
||||
|
|
@ -470,10 +470,10 @@ func (client *BlobClient) copyFromURLCreateRequest(ctx context.Context, copySour
|
|||
req.Raw().Header["x-ms-source-if-none-match"] = []string{string(*sourceModifiedAccessConditions.SourceIfNoneMatch)}
|
||||
}
|
||||
if modifiedAccessConditions != nil && modifiedAccessConditions.IfModifiedSince != nil {
|
||||
req.Raw().Header["If-Modified-Since"] = []string{modifiedAccessConditions.IfModifiedSince.Format(time.RFC1123)}
|
||||
req.Raw().Header["If-Modified-Since"] = []string{(*modifiedAccessConditions.IfModifiedSince).In(gmt).Format(time.RFC1123)}
|
||||
}
|
||||
if modifiedAccessConditions != nil && modifiedAccessConditions.IfUnmodifiedSince != nil {
|
||||
req.Raw().Header["If-Unmodified-Since"] = []string{modifiedAccessConditions.IfUnmodifiedSince.Format(time.RFC1123)}
|
||||
req.Raw().Header["If-Unmodified-Since"] = []string{(*modifiedAccessConditions.IfUnmodifiedSince).In(gmt).Format(time.RFC1123)}
|
||||
}
|
||||
if modifiedAccessConditions != nil && modifiedAccessConditions.IfMatch != nil {
|
||||
req.Raw().Header["If-Match"] = []string{string(*modifiedAccessConditions.IfMatch)}
|
||||
|
|
@ -499,7 +499,7 @@ func (client *BlobClient) copyFromURLCreateRequest(ctx context.Context, copySour
|
|||
req.Raw().Header["x-ms-tags"] = []string{*options.BlobTagsString}
|
||||
}
|
||||
if options != nil && options.ImmutabilityPolicyExpiry != nil {
|
||||
req.Raw().Header["x-ms-immutability-policy-until-date"] = []string{options.ImmutabilityPolicyExpiry.Format(time.RFC1123)}
|
||||
req.Raw().Header["x-ms-immutability-policy-until-date"] = []string{(*options.ImmutabilityPolicyExpiry).In(gmt).Format(time.RFC1123)}
|
||||
}
|
||||
if options != nil && options.ImmutabilityPolicyMode != nil {
|
||||
req.Raw().Header["x-ms-immutability-policy-mode"] = []string{string(*options.ImmutabilityPolicyMode)}
|
||||
|
|
@ -625,10 +625,10 @@ func (client *BlobClient) createSnapshotCreateRequest(ctx context.Context, optio
|
|||
req.Raw().Header["x-ms-encryption-scope"] = []string{*cpkScopeInfo.EncryptionScope}
|
||||
}
|
||||
if modifiedAccessConditions != nil && modifiedAccessConditions.IfModifiedSince != nil {
|
||||
req.Raw().Header["If-Modified-Since"] = []string{modifiedAccessConditions.IfModifiedSince.Format(time.RFC1123)}
|
||||
req.Raw().Header["If-Modified-Since"] = []string{(*modifiedAccessConditions.IfModifiedSince).In(gmt).Format(time.RFC1123)}
|
||||
}
|
||||
if modifiedAccessConditions != nil && modifiedAccessConditions.IfUnmodifiedSince != nil {
|
||||
req.Raw().Header["If-Unmodified-Since"] = []string{modifiedAccessConditions.IfUnmodifiedSince.Format(time.RFC1123)}
|
||||
req.Raw().Header["If-Unmodified-Since"] = []string{(*modifiedAccessConditions.IfUnmodifiedSince).In(gmt).Format(time.RFC1123)}
|
||||
}
|
||||
if modifiedAccessConditions != nil && modifiedAccessConditions.IfMatch != nil {
|
||||
req.Raw().Header["If-Match"] = []string{string(*modifiedAccessConditions.IfMatch)}
|
||||
|
|
@ -754,10 +754,10 @@ func (client *BlobClient) deleteCreateRequest(ctx context.Context, options *Blob
|
|||
req.Raw().Header["x-ms-delete-snapshots"] = []string{string(*options.DeleteSnapshots)}
|
||||
}
|
||||
if modifiedAccessConditions != nil && modifiedAccessConditions.IfModifiedSince != nil {
|
||||
req.Raw().Header["If-Modified-Since"] = []string{modifiedAccessConditions.IfModifiedSince.Format(time.RFC1123)}
|
||||
req.Raw().Header["If-Modified-Since"] = []string{(*modifiedAccessConditions.IfModifiedSince).In(gmt).Format(time.RFC1123)}
|
||||
}
|
||||
if modifiedAccessConditions != nil && modifiedAccessConditions.IfUnmodifiedSince != nil {
|
||||
req.Raw().Header["If-Unmodified-Since"] = []string{modifiedAccessConditions.IfUnmodifiedSince.Format(time.RFC1123)}
|
||||
req.Raw().Header["If-Unmodified-Since"] = []string{(*modifiedAccessConditions.IfUnmodifiedSince).In(gmt).Format(time.RFC1123)}
|
||||
}
|
||||
if modifiedAccessConditions != nil && modifiedAccessConditions.IfMatch != nil {
|
||||
req.Raw().Header["If-Match"] = []string{string(*modifiedAccessConditions.IfMatch)}
|
||||
|
|
@ -925,10 +925,10 @@ func (client *BlobClient) downloadCreateRequest(ctx context.Context, options *Bl
|
|||
req.Raw().Header["x-ms-encryption-algorithm"] = []string{string(*cpkInfo.EncryptionAlgorithm)}
|
||||
}
|
||||
if modifiedAccessConditions != nil && modifiedAccessConditions.IfModifiedSince != nil {
|
||||
req.Raw().Header["If-Modified-Since"] = []string{modifiedAccessConditions.IfModifiedSince.Format(time.RFC1123)}
|
||||
req.Raw().Header["If-Modified-Since"] = []string{(*modifiedAccessConditions.IfModifiedSince).In(gmt).Format(time.RFC1123)}
|
||||
}
|
||||
if modifiedAccessConditions != nil && modifiedAccessConditions.IfUnmodifiedSince != nil {
|
||||
req.Raw().Header["If-Unmodified-Since"] = []string{modifiedAccessConditions.IfUnmodifiedSince.Format(time.RFC1123)}
|
||||
req.Raw().Header["If-Unmodified-Since"] = []string{(*modifiedAccessConditions.IfUnmodifiedSince).In(gmt).Format(time.RFC1123)}
|
||||
}
|
||||
if modifiedAccessConditions != nil && modifiedAccessConditions.IfMatch != nil {
|
||||
req.Raw().Header["If-Match"] = []string{string(*modifiedAccessConditions.IfMatch)}
|
||||
|
|
@ -1277,10 +1277,10 @@ func (client *BlobClient) getPropertiesCreateRequest(ctx context.Context, option
|
|||
req.Raw().Header["x-ms-encryption-algorithm"] = []string{string(*cpkInfo.EncryptionAlgorithm)}
|
||||
}
|
||||
if modifiedAccessConditions != nil && modifiedAccessConditions.IfModifiedSince != nil {
|
||||
req.Raw().Header["If-Modified-Since"] = []string{modifiedAccessConditions.IfModifiedSince.Format(time.RFC1123)}
|
||||
req.Raw().Header["If-Modified-Since"] = []string{(*modifiedAccessConditions.IfModifiedSince).In(gmt).Format(time.RFC1123)}
|
||||
}
|
||||
if modifiedAccessConditions != nil && modifiedAccessConditions.IfUnmodifiedSince != nil {
|
||||
req.Raw().Header["If-Unmodified-Since"] = []string{modifiedAccessConditions.IfUnmodifiedSince.Format(time.RFC1123)}
|
||||
req.Raw().Header["If-Unmodified-Since"] = []string{(*modifiedAccessConditions.IfUnmodifiedSince).In(gmt).Format(time.RFC1123)}
|
||||
}
|
||||
if modifiedAccessConditions != nil && modifiedAccessConditions.IfMatch != nil {
|
||||
req.Raw().Header["If-Match"] = []string{string(*modifiedAccessConditions.IfMatch)}
|
||||
|
|
@ -1670,10 +1670,10 @@ func (client *BlobClient) queryCreateRequest(ctx context.Context, options *BlobC
|
|||
req.Raw().Header["x-ms-encryption-algorithm"] = []string{string(*cpkInfo.EncryptionAlgorithm)}
|
||||
}
|
||||
if modifiedAccessConditions != nil && modifiedAccessConditions.IfModifiedSince != nil {
|
||||
req.Raw().Header["If-Modified-Since"] = []string{modifiedAccessConditions.IfModifiedSince.Format(time.RFC1123)}
|
||||
req.Raw().Header["If-Modified-Since"] = []string{(*modifiedAccessConditions.IfModifiedSince).In(gmt).Format(time.RFC1123)}
|
||||
}
|
||||
if modifiedAccessConditions != nil && modifiedAccessConditions.IfUnmodifiedSince != nil {
|
||||
req.Raw().Header["If-Unmodified-Since"] = []string{modifiedAccessConditions.IfUnmodifiedSince.Format(time.RFC1123)}
|
||||
req.Raw().Header["If-Unmodified-Since"] = []string{(*modifiedAccessConditions.IfUnmodifiedSince).In(gmt).Format(time.RFC1123)}
|
||||
}
|
||||
if modifiedAccessConditions != nil && modifiedAccessConditions.IfMatch != nil {
|
||||
req.Raw().Header["If-Match"] = []string{string(*modifiedAccessConditions.IfMatch)}
|
||||
|
|
@ -1883,10 +1883,10 @@ func (client *BlobClient) releaseLeaseCreateRequest(ctx context.Context, leaseID
|
|||
req.Raw().Header["x-ms-lease-action"] = []string{"release"}
|
||||
req.Raw().Header["x-ms-lease-id"] = []string{leaseID}
|
||||
if modifiedAccessConditions != nil && modifiedAccessConditions.IfModifiedSince != nil {
|
||||
req.Raw().Header["If-Modified-Since"] = []string{modifiedAccessConditions.IfModifiedSince.Format(time.RFC1123)}
|
||||
req.Raw().Header["If-Modified-Since"] = []string{(*modifiedAccessConditions.IfModifiedSince).In(gmt).Format(time.RFC1123)}
|
||||
}
|
||||
if modifiedAccessConditions != nil && modifiedAccessConditions.IfUnmodifiedSince != nil {
|
||||
req.Raw().Header["If-Unmodified-Since"] = []string{modifiedAccessConditions.IfUnmodifiedSince.Format(time.RFC1123)}
|
||||
req.Raw().Header["If-Unmodified-Since"] = []string{(*modifiedAccessConditions.IfUnmodifiedSince).In(gmt).Format(time.RFC1123)}
|
||||
}
|
||||
if modifiedAccessConditions != nil && modifiedAccessConditions.IfMatch != nil {
|
||||
req.Raw().Header["If-Match"] = []string{string(*modifiedAccessConditions.IfMatch)}
|
||||
|
|
@ -1974,10 +1974,10 @@ func (client *BlobClient) renewLeaseCreateRequest(ctx context.Context, leaseID s
|
|||
req.Raw().Header["x-ms-lease-action"] = []string{"renew"}
|
||||
req.Raw().Header["x-ms-lease-id"] = []string{leaseID}
|
||||
if modifiedAccessConditions != nil && modifiedAccessConditions.IfModifiedSince != nil {
|
||||
req.Raw().Header["If-Modified-Since"] = []string{modifiedAccessConditions.IfModifiedSince.Format(time.RFC1123)}
|
||||
req.Raw().Header["If-Modified-Since"] = []string{(*modifiedAccessConditions.IfModifiedSince).In(gmt).Format(time.RFC1123)}
|
||||
}
|
||||
if modifiedAccessConditions != nil && modifiedAccessConditions.IfUnmodifiedSince != nil {
|
||||
req.Raw().Header["If-Unmodified-Since"] = []string{modifiedAccessConditions.IfUnmodifiedSince.Format(time.RFC1123)}
|
||||
req.Raw().Header["If-Unmodified-Since"] = []string{(*modifiedAccessConditions.IfUnmodifiedSince).In(gmt).Format(time.RFC1123)}
|
||||
}
|
||||
if modifiedAccessConditions != nil && modifiedAccessConditions.IfMatch != nil {
|
||||
req.Raw().Header["If-Match"] = []string{string(*modifiedAccessConditions.IfMatch)}
|
||||
|
|
@ -2162,10 +2162,10 @@ func (client *BlobClient) setHTTPHeadersCreateRequest(ctx context.Context, optio
|
|||
req.Raw().Header["x-ms-lease-id"] = []string{*leaseAccessConditions.LeaseID}
|
||||
}
|
||||
if modifiedAccessConditions != nil && modifiedAccessConditions.IfModifiedSince != nil {
|
||||
req.Raw().Header["If-Modified-Since"] = []string{modifiedAccessConditions.IfModifiedSince.Format(time.RFC1123)}
|
||||
req.Raw().Header["If-Modified-Since"] = []string{(*modifiedAccessConditions.IfModifiedSince).In(gmt).Format(time.RFC1123)}
|
||||
}
|
||||
if modifiedAccessConditions != nil && modifiedAccessConditions.IfUnmodifiedSince != nil {
|
||||
req.Raw().Header["If-Unmodified-Since"] = []string{modifiedAccessConditions.IfUnmodifiedSince.Format(time.RFC1123)}
|
||||
req.Raw().Header["If-Unmodified-Since"] = []string{(*modifiedAccessConditions.IfUnmodifiedSince).In(gmt).Format(time.RFC1123)}
|
||||
}
|
||||
if modifiedAccessConditions != nil && modifiedAccessConditions.IfMatch != nil {
|
||||
req.Raw().Header["If-Match"] = []string{string(*modifiedAccessConditions.IfMatch)}
|
||||
|
|
@ -2265,10 +2265,10 @@ func (client *BlobClient) setImmutabilityPolicyCreateRequest(ctx context.Context
|
|||
req.Raw().Header["x-ms-client-request-id"] = []string{*options.RequestID}
|
||||
}
|
||||
if modifiedAccessConditions != nil && modifiedAccessConditions.IfUnmodifiedSince != nil {
|
||||
req.Raw().Header["If-Unmodified-Since"] = []string{modifiedAccessConditions.IfUnmodifiedSince.Format(time.RFC1123)}
|
||||
req.Raw().Header["If-Unmodified-Since"] = []string{(*modifiedAccessConditions.IfUnmodifiedSince).In(gmt).Format(time.RFC1123)}
|
||||
}
|
||||
if options != nil && options.ImmutabilityPolicyExpiry != nil {
|
||||
req.Raw().Header["x-ms-immutability-policy-until-date"] = []string{options.ImmutabilityPolicyExpiry.Format(time.RFC1123)}
|
||||
req.Raw().Header["x-ms-immutability-policy-until-date"] = []string{(*options.ImmutabilityPolicyExpiry).In(gmt).Format(time.RFC1123)}
|
||||
}
|
||||
if options != nil && options.ImmutabilityPolicyMode != nil {
|
||||
req.Raw().Header["x-ms-immutability-policy-mode"] = []string{string(*options.ImmutabilityPolicyMode)}
|
||||
|
|
@ -2440,10 +2440,10 @@ func (client *BlobClient) setMetadataCreateRequest(ctx context.Context, options
|
|||
req.Raw().Header["x-ms-encryption-scope"] = []string{*cpkScopeInfo.EncryptionScope}
|
||||
}
|
||||
if modifiedAccessConditions != nil && modifiedAccessConditions.IfModifiedSince != nil {
|
||||
req.Raw().Header["If-Modified-Since"] = []string{modifiedAccessConditions.IfModifiedSince.Format(time.RFC1123)}
|
||||
req.Raw().Header["If-Modified-Since"] = []string{(*modifiedAccessConditions.IfModifiedSince).In(gmt).Format(time.RFC1123)}
|
||||
}
|
||||
if modifiedAccessConditions != nil && modifiedAccessConditions.IfUnmodifiedSince != nil {
|
||||
req.Raw().Header["If-Unmodified-Since"] = []string{modifiedAccessConditions.IfUnmodifiedSince.Format(time.RFC1123)}
|
||||
req.Raw().Header["If-Unmodified-Since"] = []string{(*modifiedAccessConditions.IfUnmodifiedSince).In(gmt).Format(time.RFC1123)}
|
||||
}
|
||||
if modifiedAccessConditions != nil && modifiedAccessConditions.IfMatch != nil {
|
||||
req.Raw().Header["If-Match"] = []string{string(*modifiedAccessConditions.IfMatch)}
|
||||
|
|
@ -2719,10 +2719,10 @@ func (client *BlobClient) startCopyFromURLCreateRequest(ctx context.Context, cop
|
|||
req.Raw().Header["x-ms-rehydrate-priority"] = []string{string(*options.RehydratePriority)}
|
||||
}
|
||||
if sourceModifiedAccessConditions != nil && sourceModifiedAccessConditions.SourceIfModifiedSince != nil {
|
||||
req.Raw().Header["x-ms-source-if-modified-since"] = []string{sourceModifiedAccessConditions.SourceIfModifiedSince.Format(time.RFC1123)}
|
||||
req.Raw().Header["x-ms-source-if-modified-since"] = []string{(*sourceModifiedAccessConditions.SourceIfModifiedSince).In(gmt).Format(time.RFC1123)}
|
||||
}
|
||||
if sourceModifiedAccessConditions != nil && sourceModifiedAccessConditions.SourceIfUnmodifiedSince != nil {
|
||||
req.Raw().Header["x-ms-source-if-unmodified-since"] = []string{sourceModifiedAccessConditions.SourceIfUnmodifiedSince.Format(time.RFC1123)}
|
||||
req.Raw().Header["x-ms-source-if-unmodified-since"] = []string{(*sourceModifiedAccessConditions.SourceIfUnmodifiedSince).In(gmt).Format(time.RFC1123)}
|
||||
}
|
||||
if sourceModifiedAccessConditions != nil && sourceModifiedAccessConditions.SourceIfMatch != nil {
|
||||
req.Raw().Header["x-ms-source-if-match"] = []string{string(*sourceModifiedAccessConditions.SourceIfMatch)}
|
||||
|
|
@ -2734,10 +2734,10 @@ func (client *BlobClient) startCopyFromURLCreateRequest(ctx context.Context, cop
|
|||
req.Raw().Header["x-ms-source-if-tags"] = []string{*sourceModifiedAccessConditions.SourceIfTags}
|
||||
}
|
||||
if modifiedAccessConditions != nil && modifiedAccessConditions.IfModifiedSince != nil {
|
||||
req.Raw().Header["If-Modified-Since"] = []string{modifiedAccessConditions.IfModifiedSince.Format(time.RFC1123)}
|
||||
req.Raw().Header["If-Modified-Since"] = []string{(*modifiedAccessConditions.IfModifiedSince).In(gmt).Format(time.RFC1123)}
|
||||
}
|
||||
if modifiedAccessConditions != nil && modifiedAccessConditions.IfUnmodifiedSince != nil {
|
||||
req.Raw().Header["If-Unmodified-Since"] = []string{modifiedAccessConditions.IfUnmodifiedSince.Format(time.RFC1123)}
|
||||
req.Raw().Header["If-Unmodified-Since"] = []string{(*modifiedAccessConditions.IfUnmodifiedSince).In(gmt).Format(time.RFC1123)}
|
||||
}
|
||||
if modifiedAccessConditions != nil && modifiedAccessConditions.IfMatch != nil {
|
||||
req.Raw().Header["If-Match"] = []string{string(*modifiedAccessConditions.IfMatch)}
|
||||
|
|
@ -2763,7 +2763,7 @@ func (client *BlobClient) startCopyFromURLCreateRequest(ctx context.Context, cop
|
|||
req.Raw().Header["x-ms-seal-blob"] = []string{strconv.FormatBool(*options.SealBlob)}
|
||||
}
|
||||
if options != nil && options.ImmutabilityPolicyExpiry != nil {
|
||||
req.Raw().Header["x-ms-immutability-policy-until-date"] = []string{options.ImmutabilityPolicyExpiry.Format(time.RFC1123)}
|
||||
req.Raw().Header["x-ms-immutability-policy-until-date"] = []string{(*options.ImmutabilityPolicyExpiry).In(gmt).Format(time.RFC1123)}
|
||||
}
|
||||
if options != nil && options.ImmutabilityPolicyMode != nil {
|
||||
req.Raw().Header["x-ms-immutability-policy-mode"] = []string{string(*options.ImmutabilityPolicyMode)}
|
||||
|
|
|
|||
|
|
@ -134,10 +134,10 @@ func (client *BlockBlobClient) commitBlockListCreateRequest(ctx context.Context,
|
|||
req.Raw().Header["x-ms-access-tier"] = []string{string(*options.Tier)}
|
||||
}
|
||||
if modifiedAccessConditions != nil && modifiedAccessConditions.IfModifiedSince != nil {
|
||||
req.Raw().Header["If-Modified-Since"] = []string{modifiedAccessConditions.IfModifiedSince.Format(time.RFC1123)}
|
||||
req.Raw().Header["If-Modified-Since"] = []string{(*modifiedAccessConditions.IfModifiedSince).In(gmt).Format(time.RFC1123)}
|
||||
}
|
||||
if modifiedAccessConditions != nil && modifiedAccessConditions.IfUnmodifiedSince != nil {
|
||||
req.Raw().Header["If-Unmodified-Since"] = []string{modifiedAccessConditions.IfUnmodifiedSince.Format(time.RFC1123)}
|
||||
req.Raw().Header["If-Unmodified-Since"] = []string{(*modifiedAccessConditions.IfUnmodifiedSince).In(gmt).Format(time.RFC1123)}
|
||||
}
|
||||
if modifiedAccessConditions != nil && modifiedAccessConditions.IfMatch != nil {
|
||||
req.Raw().Header["If-Match"] = []string{string(*modifiedAccessConditions.IfMatch)}
|
||||
|
|
@ -156,7 +156,7 @@ func (client *BlockBlobClient) commitBlockListCreateRequest(ctx context.Context,
|
|||
req.Raw().Header["x-ms-tags"] = []string{*options.BlobTagsString}
|
||||
}
|
||||
if options != nil && options.ImmutabilityPolicyExpiry != nil {
|
||||
req.Raw().Header["x-ms-immutability-policy-until-date"] = []string{options.ImmutabilityPolicyExpiry.Format(time.RFC1123)}
|
||||
req.Raw().Header["x-ms-immutability-policy-until-date"] = []string{(*options.ImmutabilityPolicyExpiry).In(gmt).Format(time.RFC1123)}
|
||||
}
|
||||
if options != nil && options.ImmutabilityPolicyMode != nil {
|
||||
req.Raw().Header["x-ms-immutability-policy-mode"] = []string{string(*options.ImmutabilityPolicyMode)}
|
||||
|
|
@ -424,10 +424,10 @@ func (client *BlockBlobClient) putBlobFromURLCreateRequest(ctx context.Context,
|
|||
req.Raw().Header["x-ms-access-tier"] = []string{string(*options.Tier)}
|
||||
}
|
||||
if modifiedAccessConditions != nil && modifiedAccessConditions.IfModifiedSince != nil {
|
||||
req.Raw().Header["If-Modified-Since"] = []string{modifiedAccessConditions.IfModifiedSince.Format(time.RFC1123)}
|
||||
req.Raw().Header["If-Modified-Since"] = []string{(*modifiedAccessConditions.IfModifiedSince).In(gmt).Format(time.RFC1123)}
|
||||
}
|
||||
if modifiedAccessConditions != nil && modifiedAccessConditions.IfUnmodifiedSince != nil {
|
||||
req.Raw().Header["If-Unmodified-Since"] = []string{modifiedAccessConditions.IfUnmodifiedSince.Format(time.RFC1123)}
|
||||
req.Raw().Header["If-Unmodified-Since"] = []string{(*modifiedAccessConditions.IfUnmodifiedSince).In(gmt).Format(time.RFC1123)}
|
||||
}
|
||||
if modifiedAccessConditions != nil && modifiedAccessConditions.IfMatch != nil {
|
||||
req.Raw().Header["If-Match"] = []string{string(*modifiedAccessConditions.IfMatch)}
|
||||
|
|
@ -439,10 +439,10 @@ func (client *BlockBlobClient) putBlobFromURLCreateRequest(ctx context.Context,
|
|||
req.Raw().Header["x-ms-if-tags"] = []string{*modifiedAccessConditions.IfTags}
|
||||
}
|
||||
if sourceModifiedAccessConditions != nil && sourceModifiedAccessConditions.SourceIfModifiedSince != nil {
|
||||
req.Raw().Header["x-ms-source-if-modified-since"] = []string{sourceModifiedAccessConditions.SourceIfModifiedSince.Format(time.RFC1123)}
|
||||
req.Raw().Header["x-ms-source-if-modified-since"] = []string{(*sourceModifiedAccessConditions.SourceIfModifiedSince).In(gmt).Format(time.RFC1123)}
|
||||
}
|
||||
if sourceModifiedAccessConditions != nil && sourceModifiedAccessConditions.SourceIfUnmodifiedSince != nil {
|
||||
req.Raw().Header["x-ms-source-if-unmodified-since"] = []string{sourceModifiedAccessConditions.SourceIfUnmodifiedSince.Format(time.RFC1123)}
|
||||
req.Raw().Header["x-ms-source-if-unmodified-since"] = []string{(*sourceModifiedAccessConditions.SourceIfUnmodifiedSince).In(gmt).Format(time.RFC1123)}
|
||||
}
|
||||
if sourceModifiedAccessConditions != nil && sourceModifiedAccessConditions.SourceIfMatch != nil {
|
||||
req.Raw().Header["x-ms-source-if-match"] = []string{string(*sourceModifiedAccessConditions.SourceIfMatch)}
|
||||
|
|
@ -721,10 +721,10 @@ func (client *BlockBlobClient) stageBlockFromURLCreateRequest(ctx context.Contex
|
|||
req.Raw().Header["x-ms-lease-id"] = []string{*leaseAccessConditions.LeaseID}
|
||||
}
|
||||
if sourceModifiedAccessConditions != nil && sourceModifiedAccessConditions.SourceIfModifiedSince != nil {
|
||||
req.Raw().Header["x-ms-source-if-modified-since"] = []string{sourceModifiedAccessConditions.SourceIfModifiedSince.Format(time.RFC1123)}
|
||||
req.Raw().Header["x-ms-source-if-modified-since"] = []string{(*sourceModifiedAccessConditions.SourceIfModifiedSince).In(gmt).Format(time.RFC1123)}
|
||||
}
|
||||
if sourceModifiedAccessConditions != nil && sourceModifiedAccessConditions.SourceIfUnmodifiedSince != nil {
|
||||
req.Raw().Header["x-ms-source-if-unmodified-since"] = []string{sourceModifiedAccessConditions.SourceIfUnmodifiedSince.Format(time.RFC1123)}
|
||||
req.Raw().Header["x-ms-source-if-unmodified-since"] = []string{(*sourceModifiedAccessConditions.SourceIfUnmodifiedSince).In(gmt).Format(time.RFC1123)}
|
||||
}
|
||||
if sourceModifiedAccessConditions != nil && sourceModifiedAccessConditions.SourceIfMatch != nil {
|
||||
req.Raw().Header["x-ms-source-if-match"] = []string{string(*sourceModifiedAccessConditions.SourceIfMatch)}
|
||||
|
|
@ -882,10 +882,10 @@ func (client *BlockBlobClient) uploadCreateRequest(ctx context.Context, contentL
|
|||
req.Raw().Header["x-ms-access-tier"] = []string{string(*options.Tier)}
|
||||
}
|
||||
if modifiedAccessConditions != nil && modifiedAccessConditions.IfModifiedSince != nil {
|
||||
req.Raw().Header["If-Modified-Since"] = []string{modifiedAccessConditions.IfModifiedSince.Format(time.RFC1123)}
|
||||
req.Raw().Header["If-Modified-Since"] = []string{(*modifiedAccessConditions.IfModifiedSince).In(gmt).Format(time.RFC1123)}
|
||||
}
|
||||
if modifiedAccessConditions != nil && modifiedAccessConditions.IfUnmodifiedSince != nil {
|
||||
req.Raw().Header["If-Unmodified-Since"] = []string{modifiedAccessConditions.IfUnmodifiedSince.Format(time.RFC1123)}
|
||||
req.Raw().Header["If-Unmodified-Since"] = []string{(*modifiedAccessConditions.IfUnmodifiedSince).In(gmt).Format(time.RFC1123)}
|
||||
}
|
||||
if modifiedAccessConditions != nil && modifiedAccessConditions.IfMatch != nil {
|
||||
req.Raw().Header["If-Match"] = []string{string(*modifiedAccessConditions.IfMatch)}
|
||||
|
|
@ -904,7 +904,7 @@ func (client *BlockBlobClient) uploadCreateRequest(ctx context.Context, contentL
|
|||
req.Raw().Header["x-ms-tags"] = []string{*options.BlobTagsString}
|
||||
}
|
||||
if options != nil && options.ImmutabilityPolicyExpiry != nil {
|
||||
req.Raw().Header["x-ms-immutability-policy-until-date"] = []string{options.ImmutabilityPolicyExpiry.Format(time.RFC1123)}
|
||||
req.Raw().Header["x-ms-immutability-policy-until-date"] = []string{(*options.ImmutabilityPolicyExpiry).In(gmt).Format(time.RFC1123)}
|
||||
}
|
||||
if options != nil && options.ImmutabilityPolicyMode != nil {
|
||||
req.Raw().Header["x-ms-immutability-policy-mode"] = []string{string(*options.ImmutabilityPolicyMode)}
|
||||
|
|
|
|||
|
|
@ -86,10 +86,10 @@ func (client *ContainerClient) acquireLeaseCreateRequest(ctx context.Context, du
|
|||
req.Raw().Header["x-ms-proposed-lease-id"] = []string{*options.ProposedLeaseID}
|
||||
}
|
||||
if modifiedAccessConditions != nil && modifiedAccessConditions.IfModifiedSince != nil {
|
||||
req.Raw().Header["If-Modified-Since"] = []string{modifiedAccessConditions.IfModifiedSince.Format(time.RFC1123)}
|
||||
req.Raw().Header["If-Modified-Since"] = []string{(*modifiedAccessConditions.IfModifiedSince).In(gmt).Format(time.RFC1123)}
|
||||
}
|
||||
if modifiedAccessConditions != nil && modifiedAccessConditions.IfUnmodifiedSince != nil {
|
||||
req.Raw().Header["If-Unmodified-Since"] = []string{modifiedAccessConditions.IfUnmodifiedSince.Format(time.RFC1123)}
|
||||
req.Raw().Header["If-Unmodified-Since"] = []string{(*modifiedAccessConditions.IfUnmodifiedSince).In(gmt).Format(time.RFC1123)}
|
||||
}
|
||||
req.Raw().Header["x-ms-version"] = []string{"2020-10-02"}
|
||||
if options != nil && options.RequestID != nil {
|
||||
|
|
@ -174,10 +174,10 @@ func (client *ContainerClient) breakLeaseCreateRequest(ctx context.Context, opti
|
|||
req.Raw().Header["x-ms-lease-break-period"] = []string{strconv.FormatInt(int64(*options.BreakPeriod), 10)}
|
||||
}
|
||||
if modifiedAccessConditions != nil && modifiedAccessConditions.IfModifiedSince != nil {
|
||||
req.Raw().Header["If-Modified-Since"] = []string{modifiedAccessConditions.IfModifiedSince.Format(time.RFC1123)}
|
||||
req.Raw().Header["If-Modified-Since"] = []string{(*modifiedAccessConditions.IfModifiedSince).In(gmt).Format(time.RFC1123)}
|
||||
}
|
||||
if modifiedAccessConditions != nil && modifiedAccessConditions.IfUnmodifiedSince != nil {
|
||||
req.Raw().Header["If-Unmodified-Since"] = []string{modifiedAccessConditions.IfUnmodifiedSince.Format(time.RFC1123)}
|
||||
req.Raw().Header["If-Unmodified-Since"] = []string{(*modifiedAccessConditions.IfUnmodifiedSince).In(gmt).Format(time.RFC1123)}
|
||||
}
|
||||
req.Raw().Header["x-ms-version"] = []string{"2020-10-02"}
|
||||
if options != nil && options.RequestID != nil {
|
||||
|
|
@ -270,10 +270,10 @@ func (client *ContainerClient) changeLeaseCreateRequest(ctx context.Context, lea
|
|||
req.Raw().Header["x-ms-lease-id"] = []string{leaseID}
|
||||
req.Raw().Header["x-ms-proposed-lease-id"] = []string{proposedLeaseID}
|
||||
if modifiedAccessConditions != nil && modifiedAccessConditions.IfModifiedSince != nil {
|
||||
req.Raw().Header["If-Modified-Since"] = []string{modifiedAccessConditions.IfModifiedSince.Format(time.RFC1123)}
|
||||
req.Raw().Header["If-Modified-Since"] = []string{(*modifiedAccessConditions.IfModifiedSince).In(gmt).Format(time.RFC1123)}
|
||||
}
|
||||
if modifiedAccessConditions != nil && modifiedAccessConditions.IfUnmodifiedSince != nil {
|
||||
req.Raw().Header["If-Unmodified-Since"] = []string{modifiedAccessConditions.IfUnmodifiedSince.Format(time.RFC1123)}
|
||||
req.Raw().Header["If-Unmodified-Since"] = []string{(*modifiedAccessConditions.IfUnmodifiedSince).In(gmt).Format(time.RFC1123)}
|
||||
}
|
||||
req.Raw().Header["x-ms-version"] = []string{"2020-10-02"}
|
||||
if options != nil && options.RequestID != nil {
|
||||
|
|
@ -447,10 +447,10 @@ func (client *ContainerClient) deleteCreateRequest(ctx context.Context, options
|
|||
req.Raw().Header["x-ms-lease-id"] = []string{*leaseAccessConditions.LeaseID}
|
||||
}
|
||||
if modifiedAccessConditions != nil && modifiedAccessConditions.IfModifiedSince != nil {
|
||||
req.Raw().Header["If-Modified-Since"] = []string{modifiedAccessConditions.IfModifiedSince.Format(time.RFC1123)}
|
||||
req.Raw().Header["If-Modified-Since"] = []string{(*modifiedAccessConditions.IfModifiedSince).In(gmt).Format(time.RFC1123)}
|
||||
}
|
||||
if modifiedAccessConditions != nil && modifiedAccessConditions.IfUnmodifiedSince != nil {
|
||||
req.Raw().Header["If-Unmodified-Since"] = []string{modifiedAccessConditions.IfUnmodifiedSince.Format(time.RFC1123)}
|
||||
req.Raw().Header["If-Unmodified-Since"] = []string{(*modifiedAccessConditions.IfUnmodifiedSince).In(gmt).Format(time.RFC1123)}
|
||||
}
|
||||
req.Raw().Header["x-ms-version"] = []string{"2020-10-02"}
|
||||
if options != nil && options.RequestID != nil {
|
||||
|
|
@ -963,10 +963,10 @@ func (client *ContainerClient) releaseLeaseCreateRequest(ctx context.Context, le
|
|||
req.Raw().Header["x-ms-lease-action"] = []string{"release"}
|
||||
req.Raw().Header["x-ms-lease-id"] = []string{leaseID}
|
||||
if modifiedAccessConditions != nil && modifiedAccessConditions.IfModifiedSince != nil {
|
||||
req.Raw().Header["If-Modified-Since"] = []string{modifiedAccessConditions.IfModifiedSince.Format(time.RFC1123)}
|
||||
req.Raw().Header["If-Modified-Since"] = []string{(*modifiedAccessConditions.IfModifiedSince).In(gmt).Format(time.RFC1123)}
|
||||
}
|
||||
if modifiedAccessConditions != nil && modifiedAccessConditions.IfUnmodifiedSince != nil {
|
||||
req.Raw().Header["If-Unmodified-Since"] = []string{modifiedAccessConditions.IfUnmodifiedSince.Format(time.RFC1123)}
|
||||
req.Raw().Header["If-Unmodified-Since"] = []string{(*modifiedAccessConditions.IfUnmodifiedSince).In(gmt).Format(time.RFC1123)}
|
||||
}
|
||||
req.Raw().Header["x-ms-version"] = []string{"2020-10-02"}
|
||||
if options != nil && options.RequestID != nil {
|
||||
|
|
@ -1115,10 +1115,10 @@ func (client *ContainerClient) renewLeaseCreateRequest(ctx context.Context, leas
|
|||
req.Raw().Header["x-ms-lease-action"] = []string{"renew"}
|
||||
req.Raw().Header["x-ms-lease-id"] = []string{leaseID}
|
||||
if modifiedAccessConditions != nil && modifiedAccessConditions.IfModifiedSince != nil {
|
||||
req.Raw().Header["If-Modified-Since"] = []string{modifiedAccessConditions.IfModifiedSince.Format(time.RFC1123)}
|
||||
req.Raw().Header["If-Modified-Since"] = []string{(*modifiedAccessConditions.IfModifiedSince).In(gmt).Format(time.RFC1123)}
|
||||
}
|
||||
if modifiedAccessConditions != nil && modifiedAccessConditions.IfUnmodifiedSince != nil {
|
||||
req.Raw().Header["If-Unmodified-Since"] = []string{modifiedAccessConditions.IfUnmodifiedSince.Format(time.RFC1123)}
|
||||
req.Raw().Header["If-Unmodified-Since"] = []string{(*modifiedAccessConditions.IfUnmodifiedSince).In(gmt).Format(time.RFC1123)}
|
||||
}
|
||||
req.Raw().Header["x-ms-version"] = []string{"2020-10-02"}
|
||||
if options != nil && options.RequestID != nil {
|
||||
|
|
@ -1277,10 +1277,10 @@ func (client *ContainerClient) setAccessPolicyCreateRequest(ctx context.Context,
|
|||
req.Raw().Header["x-ms-blob-public-access"] = []string{string(*options.Access)}
|
||||
}
|
||||
if modifiedAccessConditions != nil && modifiedAccessConditions.IfModifiedSince != nil {
|
||||
req.Raw().Header["If-Modified-Since"] = []string{modifiedAccessConditions.IfModifiedSince.Format(time.RFC1123)}
|
||||
req.Raw().Header["If-Modified-Since"] = []string{(*modifiedAccessConditions.IfModifiedSince).In(gmt).Format(time.RFC1123)}
|
||||
}
|
||||
if modifiedAccessConditions != nil && modifiedAccessConditions.IfUnmodifiedSince != nil {
|
||||
req.Raw().Header["If-Unmodified-Since"] = []string{modifiedAccessConditions.IfUnmodifiedSince.Format(time.RFC1123)}
|
||||
req.Raw().Header["If-Unmodified-Since"] = []string{(*modifiedAccessConditions.IfUnmodifiedSince).In(gmt).Format(time.RFC1123)}
|
||||
}
|
||||
req.Raw().Header["x-ms-version"] = []string{"2020-10-02"}
|
||||
if options != nil && options.RequestID != nil {
|
||||
|
|
@ -1372,7 +1372,7 @@ func (client *ContainerClient) setMetadataCreateRequest(ctx context.Context, opt
|
|||
}
|
||||
}
|
||||
if modifiedAccessConditions != nil && modifiedAccessConditions.IfModifiedSince != nil {
|
||||
req.Raw().Header["If-Modified-Since"] = []string{modifiedAccessConditions.IfModifiedSince.Format(time.RFC1123)}
|
||||
req.Raw().Header["If-Modified-Since"] = []string{(*modifiedAccessConditions.IfModifiedSince).In(gmt).Format(time.RFC1123)}
|
||||
}
|
||||
req.Raw().Header["x-ms-version"] = []string{"2020-10-02"}
|
||||
if options != nil && options.RequestID != nil {
|
||||
|
|
@ -1459,7 +1459,7 @@ func (client *ContainerClient) submitBatchCreateRequest(ctx context.Context, con
|
|||
req.Raw().Header["x-ms-client-request-id"] = []string{*options.RequestID}
|
||||
}
|
||||
req.Raw().Header["Accept"] = []string{"application/xml"}
|
||||
return req, req.SetBody(body, "application/xml")
|
||||
return req, req.SetBody(body, multipartContentType)
|
||||
}
|
||||
|
||||
// submitBatchHandleResponse handles the SubmitBatch response.
|
||||
|
|
|
|||
|
|
@ -108,10 +108,10 @@ func (client *PageBlobClient) clearPagesCreateRequest(ctx context.Context, conte
|
|||
req.Raw().Header["x-ms-if-sequence-number-eq"] = []string{strconv.FormatInt(*sequenceNumberAccessConditions.IfSequenceNumberEqualTo, 10)}
|
||||
}
|
||||
if modifiedAccessConditions != nil && modifiedAccessConditions.IfModifiedSince != nil {
|
||||
req.Raw().Header["If-Modified-Since"] = []string{modifiedAccessConditions.IfModifiedSince.Format(time.RFC1123)}
|
||||
req.Raw().Header["If-Modified-Since"] = []string{(*modifiedAccessConditions.IfModifiedSince).In(gmt).Format(time.RFC1123)}
|
||||
}
|
||||
if modifiedAccessConditions != nil && modifiedAccessConditions.IfUnmodifiedSince != nil {
|
||||
req.Raw().Header["If-Unmodified-Since"] = []string{modifiedAccessConditions.IfUnmodifiedSince.Format(time.RFC1123)}
|
||||
req.Raw().Header["If-Unmodified-Since"] = []string{(*modifiedAccessConditions.IfUnmodifiedSince).In(gmt).Format(time.RFC1123)}
|
||||
}
|
||||
if modifiedAccessConditions != nil && modifiedAccessConditions.IfMatch != nil {
|
||||
req.Raw().Header["If-Match"] = []string{string(*modifiedAccessConditions.IfMatch)}
|
||||
|
|
@ -225,10 +225,10 @@ func (client *PageBlobClient) copyIncrementalCreateRequest(ctx context.Context,
|
|||
}
|
||||
req.Raw().URL.RawQuery = reqQP.Encode()
|
||||
if modifiedAccessConditions != nil && modifiedAccessConditions.IfModifiedSince != nil {
|
||||
req.Raw().Header["If-Modified-Since"] = []string{modifiedAccessConditions.IfModifiedSince.Format(time.RFC1123)}
|
||||
req.Raw().Header["If-Modified-Since"] = []string{(*modifiedAccessConditions.IfModifiedSince).In(gmt).Format(time.RFC1123)}
|
||||
}
|
||||
if modifiedAccessConditions != nil && modifiedAccessConditions.IfUnmodifiedSince != nil {
|
||||
req.Raw().Header["If-Unmodified-Since"] = []string{modifiedAccessConditions.IfUnmodifiedSince.Format(time.RFC1123)}
|
||||
req.Raw().Header["If-Unmodified-Since"] = []string{(*modifiedAccessConditions.IfUnmodifiedSince).In(gmt).Format(time.RFC1123)}
|
||||
}
|
||||
if modifiedAccessConditions != nil && modifiedAccessConditions.IfMatch != nil {
|
||||
req.Raw().Header["If-Match"] = []string{string(*modifiedAccessConditions.IfMatch)}
|
||||
|
|
@ -371,10 +371,10 @@ func (client *PageBlobClient) createCreateRequest(ctx context.Context, contentLe
|
|||
req.Raw().Header["x-ms-encryption-scope"] = []string{*cpkScopeInfo.EncryptionScope}
|
||||
}
|
||||
if modifiedAccessConditions != nil && modifiedAccessConditions.IfModifiedSince != nil {
|
||||
req.Raw().Header["If-Modified-Since"] = []string{modifiedAccessConditions.IfModifiedSince.Format(time.RFC1123)}
|
||||
req.Raw().Header["If-Modified-Since"] = []string{(*modifiedAccessConditions.IfModifiedSince).In(gmt).Format(time.RFC1123)}
|
||||
}
|
||||
if modifiedAccessConditions != nil && modifiedAccessConditions.IfUnmodifiedSince != nil {
|
||||
req.Raw().Header["If-Unmodified-Since"] = []string{modifiedAccessConditions.IfUnmodifiedSince.Format(time.RFC1123)}
|
||||
req.Raw().Header["If-Unmodified-Since"] = []string{(*modifiedAccessConditions.IfUnmodifiedSince).In(gmt).Format(time.RFC1123)}
|
||||
}
|
||||
if modifiedAccessConditions != nil && modifiedAccessConditions.IfMatch != nil {
|
||||
req.Raw().Header["If-Match"] = []string{string(*modifiedAccessConditions.IfMatch)}
|
||||
|
|
@ -397,7 +397,7 @@ func (client *PageBlobClient) createCreateRequest(ctx context.Context, contentLe
|
|||
req.Raw().Header["x-ms-tags"] = []string{*options.BlobTagsString}
|
||||
}
|
||||
if options != nil && options.ImmutabilityPolicyExpiry != nil {
|
||||
req.Raw().Header["x-ms-immutability-policy-until-date"] = []string{options.ImmutabilityPolicyExpiry.Format(time.RFC1123)}
|
||||
req.Raw().Header["x-ms-immutability-policy-until-date"] = []string{(*options.ImmutabilityPolicyExpiry).In(gmt).Format(time.RFC1123)}
|
||||
}
|
||||
if options != nil && options.ImmutabilityPolicyMode != nil {
|
||||
req.Raw().Header["x-ms-immutability-policy-mode"] = []string{string(*options.ImmutabilityPolicyMode)}
|
||||
|
|
@ -528,10 +528,10 @@ func (client *PageBlobClient) GetPageRangesCreateRequest(ctx context.Context, op
|
|||
req.Raw().Header["x-ms-lease-id"] = []string{*leaseAccessConditions.LeaseID}
|
||||
}
|
||||
if modifiedAccessConditions != nil && modifiedAccessConditions.IfModifiedSince != nil {
|
||||
req.Raw().Header["If-Modified-Since"] = []string{modifiedAccessConditions.IfModifiedSince.Format(time.RFC1123)}
|
||||
req.Raw().Header["If-Modified-Since"] = []string{(*modifiedAccessConditions.IfModifiedSince).In(gmt).Format(time.RFC1123)}
|
||||
}
|
||||
if modifiedAccessConditions != nil && modifiedAccessConditions.IfUnmodifiedSince != nil {
|
||||
req.Raw().Header["If-Unmodified-Since"] = []string{modifiedAccessConditions.IfUnmodifiedSince.Format(time.RFC1123)}
|
||||
req.Raw().Header["If-Unmodified-Since"] = []string{(*modifiedAccessConditions.IfUnmodifiedSince).In(gmt).Format(time.RFC1123)}
|
||||
}
|
||||
if modifiedAccessConditions != nil && modifiedAccessConditions.IfMatch != nil {
|
||||
req.Raw().Header["If-Match"] = []string{string(*modifiedAccessConditions.IfMatch)}
|
||||
|
|
@ -662,10 +662,10 @@ func (client *PageBlobClient) GetPageRangesDiffCreateRequest(ctx context.Context
|
|||
req.Raw().Header["x-ms-lease-id"] = []string{*leaseAccessConditions.LeaseID}
|
||||
}
|
||||
if modifiedAccessConditions != nil && modifiedAccessConditions.IfModifiedSince != nil {
|
||||
req.Raw().Header["If-Modified-Since"] = []string{modifiedAccessConditions.IfModifiedSince.Format(time.RFC1123)}
|
||||
req.Raw().Header["If-Modified-Since"] = []string{(*modifiedAccessConditions.IfModifiedSince).In(gmt).Format(time.RFC1123)}
|
||||
}
|
||||
if modifiedAccessConditions != nil && modifiedAccessConditions.IfUnmodifiedSince != nil {
|
||||
req.Raw().Header["If-Unmodified-Since"] = []string{modifiedAccessConditions.IfUnmodifiedSince.Format(time.RFC1123)}
|
||||
req.Raw().Header["If-Unmodified-Since"] = []string{(*modifiedAccessConditions.IfUnmodifiedSince).In(gmt).Format(time.RFC1123)}
|
||||
}
|
||||
if modifiedAccessConditions != nil && modifiedAccessConditions.IfMatch != nil {
|
||||
req.Raw().Header["If-Match"] = []string{string(*modifiedAccessConditions.IfMatch)}
|
||||
|
|
@ -780,10 +780,10 @@ func (client *PageBlobClient) resizeCreateRequest(ctx context.Context, blobConte
|
|||
req.Raw().Header["x-ms-encryption-scope"] = []string{*cpkScopeInfo.EncryptionScope}
|
||||
}
|
||||
if modifiedAccessConditions != nil && modifiedAccessConditions.IfModifiedSince != nil {
|
||||
req.Raw().Header["If-Modified-Since"] = []string{modifiedAccessConditions.IfModifiedSince.Format(time.RFC1123)}
|
||||
req.Raw().Header["If-Modified-Since"] = []string{(*modifiedAccessConditions.IfModifiedSince).In(gmt).Format(time.RFC1123)}
|
||||
}
|
||||
if modifiedAccessConditions != nil && modifiedAccessConditions.IfUnmodifiedSince != nil {
|
||||
req.Raw().Header["If-Unmodified-Since"] = []string{modifiedAccessConditions.IfUnmodifiedSince.Format(time.RFC1123)}
|
||||
req.Raw().Header["If-Unmodified-Since"] = []string{(*modifiedAccessConditions.IfUnmodifiedSince).In(gmt).Format(time.RFC1123)}
|
||||
}
|
||||
if modifiedAccessConditions != nil && modifiedAccessConditions.IfMatch != nil {
|
||||
req.Raw().Header["If-Match"] = []string{string(*modifiedAccessConditions.IfMatch)}
|
||||
|
|
@ -883,10 +883,10 @@ func (client *PageBlobClient) updateSequenceNumberCreateRequest(ctx context.Cont
|
|||
req.Raw().Header["x-ms-lease-id"] = []string{*leaseAccessConditions.LeaseID}
|
||||
}
|
||||
if modifiedAccessConditions != nil && modifiedAccessConditions.IfModifiedSince != nil {
|
||||
req.Raw().Header["If-Modified-Since"] = []string{modifiedAccessConditions.IfModifiedSince.Format(time.RFC1123)}
|
||||
req.Raw().Header["If-Modified-Since"] = []string{(*modifiedAccessConditions.IfModifiedSince).In(gmt).Format(time.RFC1123)}
|
||||
}
|
||||
if modifiedAccessConditions != nil && modifiedAccessConditions.IfUnmodifiedSince != nil {
|
||||
req.Raw().Header["If-Unmodified-Since"] = []string{modifiedAccessConditions.IfUnmodifiedSince.Format(time.RFC1123)}
|
||||
req.Raw().Header["If-Unmodified-Since"] = []string{(*modifiedAccessConditions.IfUnmodifiedSince).In(gmt).Format(time.RFC1123)}
|
||||
}
|
||||
if modifiedAccessConditions != nil && modifiedAccessConditions.IfMatch != nil {
|
||||
req.Raw().Header["If-Match"] = []string{string(*modifiedAccessConditions.IfMatch)}
|
||||
|
|
@ -1024,10 +1024,10 @@ func (client *PageBlobClient) uploadPagesCreateRequest(ctx context.Context, cont
|
|||
req.Raw().Header["x-ms-if-sequence-number-eq"] = []string{strconv.FormatInt(*sequenceNumberAccessConditions.IfSequenceNumberEqualTo, 10)}
|
||||
}
|
||||
if modifiedAccessConditions != nil && modifiedAccessConditions.IfModifiedSince != nil {
|
||||
req.Raw().Header["If-Modified-Since"] = []string{modifiedAccessConditions.IfModifiedSince.Format(time.RFC1123)}
|
||||
req.Raw().Header["If-Modified-Since"] = []string{(*modifiedAccessConditions.IfModifiedSince).In(gmt).Format(time.RFC1123)}
|
||||
}
|
||||
if modifiedAccessConditions != nil && modifiedAccessConditions.IfUnmodifiedSince != nil {
|
||||
req.Raw().Header["If-Unmodified-Since"] = []string{modifiedAccessConditions.IfUnmodifiedSince.Format(time.RFC1123)}
|
||||
req.Raw().Header["If-Unmodified-Since"] = []string{(*modifiedAccessConditions.IfUnmodifiedSince).In(gmt).Format(time.RFC1123)}
|
||||
}
|
||||
if modifiedAccessConditions != nil && modifiedAccessConditions.IfMatch != nil {
|
||||
req.Raw().Header["If-Match"] = []string{string(*modifiedAccessConditions.IfMatch)}
|
||||
|
|
@ -1196,10 +1196,10 @@ func (client *PageBlobClient) uploadPagesFromURLCreateRequest(ctx context.Contex
|
|||
req.Raw().Header["x-ms-if-sequence-number-eq"] = []string{strconv.FormatInt(*sequenceNumberAccessConditions.IfSequenceNumberEqualTo, 10)}
|
||||
}
|
||||
if modifiedAccessConditions != nil && modifiedAccessConditions.IfModifiedSince != nil {
|
||||
req.Raw().Header["If-Modified-Since"] = []string{modifiedAccessConditions.IfModifiedSince.Format(time.RFC1123)}
|
||||
req.Raw().Header["If-Modified-Since"] = []string{(*modifiedAccessConditions.IfModifiedSince).In(gmt).Format(time.RFC1123)}
|
||||
}
|
||||
if modifiedAccessConditions != nil && modifiedAccessConditions.IfUnmodifiedSince != nil {
|
||||
req.Raw().Header["If-Unmodified-Since"] = []string{modifiedAccessConditions.IfUnmodifiedSince.Format(time.RFC1123)}
|
||||
req.Raw().Header["If-Unmodified-Since"] = []string{(*modifiedAccessConditions.IfUnmodifiedSince).In(gmt).Format(time.RFC1123)}
|
||||
}
|
||||
if modifiedAccessConditions != nil && modifiedAccessConditions.IfMatch != nil {
|
||||
req.Raw().Header["If-Match"] = []string{string(*modifiedAccessConditions.IfMatch)}
|
||||
|
|
@ -1211,10 +1211,10 @@ func (client *PageBlobClient) uploadPagesFromURLCreateRequest(ctx context.Contex
|
|||
req.Raw().Header["x-ms-if-tags"] = []string{*modifiedAccessConditions.IfTags}
|
||||
}
|
||||
if sourceModifiedAccessConditions != nil && sourceModifiedAccessConditions.SourceIfModifiedSince != nil {
|
||||
req.Raw().Header["x-ms-source-if-modified-since"] = []string{sourceModifiedAccessConditions.SourceIfModifiedSince.Format(time.RFC1123)}
|
||||
req.Raw().Header["x-ms-source-if-modified-since"] = []string{(*sourceModifiedAccessConditions.SourceIfModifiedSince).In(gmt).Format(time.RFC1123)}
|
||||
}
|
||||
if sourceModifiedAccessConditions != nil && sourceModifiedAccessConditions.SourceIfUnmodifiedSince != nil {
|
||||
req.Raw().Header["x-ms-source-if-unmodified-since"] = []string{sourceModifiedAccessConditions.SourceIfUnmodifiedSince.Format(time.RFC1123)}
|
||||
req.Raw().Header["x-ms-source-if-unmodified-since"] = []string{(*sourceModifiedAccessConditions.SourceIfUnmodifiedSince).In(gmt).Format(time.RFC1123)}
|
||||
}
|
||||
if sourceModifiedAccessConditions != nil && sourceModifiedAccessConditions.SourceIfMatch != nil {
|
||||
req.Raw().Header["x-ms-source-if-match"] = []string{string(*sourceModifiedAccessConditions.SourceIfMatch)}
|
||||
|
|
|
|||
|
|
@ -513,7 +513,7 @@ func (client *ServiceClient) SubmitBatch(ctx context.Context, contentLength int6
|
|||
if err != nil {
|
||||
return ServiceClientSubmitBatchResponse{}, err
|
||||
}
|
||||
if !runtime.HasStatusCode(resp, http.StatusOK) {
|
||||
if !runtime.HasStatusCode(resp, http.StatusAccepted) {
|
||||
return ServiceClientSubmitBatchResponse{}, runtime.NewResponseError(resp)
|
||||
}
|
||||
return client.submitBatchHandleResponse(resp)
|
||||
|
|
@ -539,7 +539,7 @@ func (client *ServiceClient) submitBatchCreateRequest(ctx context.Context, conte
|
|||
req.Raw().Header["x-ms-client-request-id"] = []string{*options.RequestID}
|
||||
}
|
||||
req.Raw().Header["Accept"] = []string{"application/xml"}
|
||||
return req, req.SetBody(body, "application/xml")
|
||||
return req, req.SetBody(body, multipartContentType)
|
||||
}
|
||||
|
||||
// submitBatchHandleResponse handles the SubmitBatch response.
|
||||
|
|
|
|||
113
vendor/github.com/Azure/azure-sdk-for-go/sdk/storage/azblob/internal/shared/challenge_policy.go
generated
vendored
Normal file
113
vendor/github.com/Azure/azure-sdk-for-go/sdk/storage/azblob/internal/shared/challenge_policy.go
generated
vendored
Normal file
|
|
@ -0,0 +1,113 @@
|
|||
//go:build go1.18
|
||||
// +build go1.18
|
||||
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// Licensed under the MIT License. See License.txt in the project root for license information.
|
||||
|
||||
package shared
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"github.com/Azure/azure-sdk-for-go/sdk/azcore"
|
||||
"github.com/Azure/azure-sdk-for-go/sdk/azcore/policy"
|
||||
"github.com/Azure/azure-sdk-for-go/sdk/azcore/runtime"
|
||||
"net/http"
|
||||
"strings"
|
||||
)
|
||||
|
||||
type storageAuthorizer struct {
|
||||
scopes []string
|
||||
tenantID string
|
||||
}
|
||||
|
||||
func NewStorageChallengePolicy(cred azcore.TokenCredential) policy.Policy {
|
||||
s := storageAuthorizer{scopes: []string{TokenScope}}
|
||||
return runtime.NewBearerTokenPolicy(cred, []string{TokenScope}, &policy.BearerTokenOptions{
|
||||
AuthorizationHandler: policy.AuthorizationHandler{
|
||||
OnRequest: s.onRequest,
|
||||
OnChallenge: s.onChallenge,
|
||||
},
|
||||
})
|
||||
}
|
||||
|
||||
func (s *storageAuthorizer) onRequest(req *policy.Request, authNZ func(policy.TokenRequestOptions) error) error {
|
||||
return authNZ(policy.TokenRequestOptions{Scopes: s.scopes})
|
||||
}
|
||||
|
||||
func (s *storageAuthorizer) onChallenge(req *policy.Request, resp *http.Response, authNZ func(policy.TokenRequestOptions) error) error {
|
||||
// parse the challenge
|
||||
err := s.parseChallenge(resp)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
// TODO: Set tenantID when policy.TokenRequestOptions supports it. https://github.com/Azure/azure-sdk-for-go/issues/19841
|
||||
return authNZ(policy.TokenRequestOptions{Scopes: s.scopes})
|
||||
}
|
||||
|
||||
type challengePolicyError struct {
|
||||
err error
|
||||
}
|
||||
|
||||
func (c *challengePolicyError) Error() string {
|
||||
return c.err.Error()
|
||||
}
|
||||
|
||||
func (*challengePolicyError) NonRetriable() {
|
||||
// marker method
|
||||
}
|
||||
|
||||
func (c *challengePolicyError) Unwrap() error {
|
||||
return c.err
|
||||
}
|
||||
|
||||
// parses Tenant ID from auth challenge
|
||||
// https://login.microsoftonline.com/00000000-0000-0000-0000-000000000000/oauth2/authorize
|
||||
func parseTenant(url string) string {
|
||||
if url == "" {
|
||||
return ""
|
||||
}
|
||||
parts := strings.Split(url, "/")
|
||||
if len(parts) >= 3 {
|
||||
tenant := parts[3]
|
||||
tenant = strings.ReplaceAll(tenant, ",", "")
|
||||
return tenant
|
||||
} else {
|
||||
return ""
|
||||
}
|
||||
}
|
||||
|
||||
func (s *storageAuthorizer) parseChallenge(resp *http.Response) error {
|
||||
authHeader := resp.Header.Get("WWW-Authenticate")
|
||||
if authHeader == "" {
|
||||
return &challengePolicyError{err: errors.New("response has no WWW-Authenticate header for challenge authentication")}
|
||||
}
|
||||
|
||||
// Strip down to auth and resource
|
||||
// Format is "Bearer authorization_uri=\"<site>\" resource_id=\"<site>\""
|
||||
authHeader = strings.ReplaceAll(authHeader, "Bearer ", "")
|
||||
|
||||
parts := strings.Split(authHeader, " ")
|
||||
|
||||
vals := map[string]string{}
|
||||
for _, part := range parts {
|
||||
subParts := strings.Split(part, "=")
|
||||
if len(subParts) == 2 {
|
||||
stripped := strings.ReplaceAll(subParts[1], "\"", "")
|
||||
stripped = strings.TrimSuffix(stripped, ",")
|
||||
vals[subParts[0]] = stripped
|
||||
}
|
||||
}
|
||||
|
||||
s.tenantID = parseTenant(vals["authorization_uri"])
|
||||
|
||||
scope := vals["resource_id"]
|
||||
if scope == "" {
|
||||
return &challengePolicyError{err: errors.New("could not find a valid resource in the WWW-Authenticate header")}
|
||||
}
|
||||
|
||||
if !strings.HasSuffix(scope, "/.default") {
|
||||
scope += "/.default"
|
||||
}
|
||||
s.scopes = []string{scope}
|
||||
return nil
|
||||
}
|
||||
57
vendor/github.com/Azure/azure-sdk-for-go/sdk/storage/azblob/internal/shared/shared.go
generated
vendored
57
vendor/github.com/Azure/azure-sdk-for-go/sdk/storage/azblob/internal/shared/shared.go
generated
vendored
|
|
@ -38,6 +38,8 @@ const (
|
|||
HeaderIfNoneMatch = "If-None-Match"
|
||||
HeaderIfUnmodifiedSince = "If-Unmodified-Since"
|
||||
HeaderRange = "Range"
|
||||
HeaderXmsVersion = "x-ms-version"
|
||||
HeaderXmsRequestID = "x-ms-request-id"
|
||||
)
|
||||
|
||||
const crc64Polynomial uint64 = 0x9A6C9329AC4BC9B5
|
||||
|
|
@ -85,22 +87,6 @@ func ParseConnectionString(connectionString string) (ParsedConnectionString, err
|
|||
connStrMap[parts[0]] = parts[1]
|
||||
}
|
||||
|
||||
accountName, ok := connStrMap["AccountName"]
|
||||
if !ok {
|
||||
return ParsedConnectionString{}, errors.New("connection string missing AccountName")
|
||||
}
|
||||
|
||||
accountKey, ok := connStrMap["AccountKey"]
|
||||
if !ok {
|
||||
sharedAccessSignature, ok := connStrMap["SharedAccessSignature"]
|
||||
if !ok {
|
||||
return ParsedConnectionString{}, errors.New("connection string missing AccountKey and SharedAccessSignature")
|
||||
}
|
||||
return ParsedConnectionString{
|
||||
ServiceURL: fmt.Sprintf("%v://%v.blob.%v/?%v", defaultScheme, accountName, defaultSuffix, sharedAccessSignature),
|
||||
}, nil
|
||||
}
|
||||
|
||||
protocol, ok := connStrMap["DefaultEndpointsProtocol"]
|
||||
if !ok {
|
||||
protocol = defaultScheme
|
||||
|
|
@ -111,24 +97,45 @@ func ParseConnectionString(connectionString string) (ParsedConnectionString, err
|
|||
suffix = defaultSuffix
|
||||
}
|
||||
|
||||
if blobEndpoint, ok := connStrMap["BlobEndpoint"]; ok {
|
||||
blobEndpoint, has_blobEndpoint := connStrMap["BlobEndpoint"]
|
||||
accountName, has_accountName := connStrMap["AccountName"]
|
||||
|
||||
var serviceURL string
|
||||
if has_blobEndpoint {
|
||||
serviceURL = blobEndpoint
|
||||
} else if has_accountName {
|
||||
serviceURL = fmt.Sprintf("%v://%v.blob.%v", protocol, accountName, suffix)
|
||||
} else {
|
||||
return ParsedConnectionString{}, errors.New("connection string needs either AccountName or BlobEndpoint")
|
||||
}
|
||||
|
||||
if !strings.HasSuffix(serviceURL, "/") {
|
||||
// add a trailing slash to be consistent with the portal
|
||||
serviceURL += "/"
|
||||
}
|
||||
|
||||
accountKey, has_accountKey := connStrMap["AccountKey"]
|
||||
sharedAccessSignature, has_sharedAccessSignature := connStrMap["SharedAccessSignature"]
|
||||
|
||||
if has_accountName && has_accountKey {
|
||||
return ParsedConnectionString{
|
||||
ServiceURL: blobEndpoint,
|
||||
ServiceURL: serviceURL,
|
||||
AccountName: accountName,
|
||||
AccountKey: accountKey,
|
||||
}, nil
|
||||
} else if has_sharedAccessSignature {
|
||||
return ParsedConnectionString{
|
||||
ServiceURL: fmt.Sprintf("%v?%v", serviceURL, sharedAccessSignature),
|
||||
}, nil
|
||||
} else {
|
||||
return ParsedConnectionString{}, errors.New("connection string needs either AccountKey or SharedAccessSignature")
|
||||
}
|
||||
|
||||
return ParsedConnectionString{
|
||||
ServiceURL: fmt.Sprintf("%v://%v.blob.%v", protocol, accountName, suffix),
|
||||
AccountName: accountName,
|
||||
AccountKey: accountKey,
|
||||
}, nil
|
||||
}
|
||||
|
||||
// SerializeBlobTags converts tags to generated.BlobTags
|
||||
func SerializeBlobTags(tagsMap map[string]string) *generated.BlobTags {
|
||||
if tagsMap == nil {
|
||||
if len(tagsMap) == 0 {
|
||||
return nil
|
||||
}
|
||||
blobTagSet := make([]*generated.BlobTag, 0)
|
||||
|
|
@ -140,7 +147,7 @@ func SerializeBlobTags(tagsMap map[string]string) *generated.BlobTags {
|
|||
}
|
||||
|
||||
func SerializeBlobTagsToStrPtr(tagsMap map[string]string) *string {
|
||||
if tagsMap == nil {
|
||||
if len(tagsMap) == 0 {
|
||||
return nil
|
||||
}
|
||||
tags := make([]string, 0)
|
||||
|
|
|
|||
7
vendor/github.com/Azure/azure-sdk-for-go/sdk/storage/azblob/log.go
generated
vendored
7
vendor/github.com/Azure/azure-sdk-for-go/sdk/storage/azblob/log.go
generated
vendored
|
|
@ -3,9 +3,14 @@
|
|||
|
||||
package azblob
|
||||
|
||||
import "github.com/Azure/azure-sdk-for-go/sdk/storage/azblob/internal/exported"
|
||||
import (
|
||||
"github.com/Azure/azure-sdk-for-go/sdk/storage/azblob/internal/exported"
|
||||
)
|
||||
|
||||
const (
|
||||
// EventUpload is used for logging events related to upload operation.
|
||||
EventUpload = exported.EventUpload
|
||||
|
||||
// EventSubmitBatch is used for logging events related to submit blob batch operation.
|
||||
EventSubmitBatch = exported.EventSubmitBatch
|
||||
)
|
||||
|
|
|
|||
12
vendor/github.com/Azure/azure-sdk-for-go/sdk/storage/azblob/pageblob/client.go
generated
vendored
12
vendor/github.com/Azure/azure-sdk-for-go/sdk/storage/azblob/pageblob/client.go
generated
vendored
|
|
@ -25,9 +25,7 @@ import (
|
|||
)
|
||||
|
||||
// ClientOptions contains the optional parameters when creating a Client.
|
||||
type ClientOptions struct {
|
||||
azcore.ClientOptions
|
||||
}
|
||||
type ClientOptions base.ClientOptions
|
||||
|
||||
// Client represents a client to an Azure Storage page blob;
|
||||
type Client base.CompositeClient[generated.BlobClient, generated.PageBlobClient]
|
||||
|
|
@ -37,7 +35,7 @@ type Client base.CompositeClient[generated.BlobClient, generated.PageBlobClient]
|
|||
// - cred - an Azure AD credential, typically obtained via the azidentity module
|
||||
// - options - client options; pass nil to accept the default values
|
||||
func NewClient(blobURL string, cred azcore.TokenCredential, options *ClientOptions) (*Client, error) {
|
||||
authPolicy := runtime.NewBearerTokenPolicy(cred, []string{shared.TokenScope}, nil)
|
||||
authPolicy := shared.NewStorageChallengePolicy(cred)
|
||||
conOptions := shared.GetClientOptions(options)
|
||||
conOptions.PerRetryPolicies = append(conOptions.PerRetryPolicies, authPolicy)
|
||||
pl := runtime.NewPipeline(exported.ModuleName, exported.ModuleVersion, runtime.PipelineOptions{}, &conOptions.ClientOptions)
|
||||
|
|
@ -363,6 +361,12 @@ func (pb *Client) GetProperties(ctx context.Context, o *blob.GetPropertiesOption
|
|||
return pb.BlobClient().GetProperties(ctx, o)
|
||||
}
|
||||
|
||||
// GetAccountInfo provides account level information
|
||||
// For more information, see https://learn.microsoft.com/en-us/rest/api/storageservices/get-account-information?tabs=shared-access-signatures.
|
||||
func (pb *Client) GetAccountInfo(ctx context.Context, o *blob.GetAccountInfoOptions) (blob.GetAccountInfoResponse, error) {
|
||||
return pb.BlobClient().GetAccountInfo(ctx, o)
|
||||
}
|
||||
|
||||
// SetHTTPHeaders changes a blob's HTTP headers.
|
||||
// For more information, see https://docs.microsoft.com/rest/api/storageservices/set-blob-properties.
|
||||
func (pb *Client) SetHTTPHeaders(ctx context.Context, HTTPHeaders blob.HTTPHeaders, o *blob.SetHTTPHeadersOptions) (blob.SetHTTPHeadersResponse, error) {
|
||||
|
|
|
|||
38
vendor/github.com/Azure/azure-sdk-for-go/sdk/storage/azblob/sas/account.go
generated
vendored
38
vendor/github.com/Azure/azure-sdk-for-go/sdk/storage/azblob/sas/account.go
generated
vendored
|
|
@ -29,9 +29,9 @@ type AccountSignatureValues struct {
|
|||
Protocol Protocol `param:"spr"` // See the SASProtocol* constants
|
||||
StartTime time.Time `param:"st"` // Not specified if IsZero
|
||||
ExpiryTime time.Time `param:"se"` // Not specified if IsZero
|
||||
Permissions string `param:"sp"` // Create by initializing a AccountSASPermissions and then call String()
|
||||
Permissions string `param:"sp"` // Create by initializing AccountPermissions and then call String()
|
||||
IPRange IPRange `param:"sip"`
|
||||
ResourceTypes string `param:"srt"` // Create by initializing AccountSASResourceTypes and then call String()
|
||||
ResourceTypes string `param:"srt"` // Create by initializing AccountResourceTypes and then call String()
|
||||
}
|
||||
|
||||
// SignWithSharedKey uses an account's shared key credential to sign this signature values to produce
|
||||
|
|
@ -50,6 +50,12 @@ func (v AccountSignatureValues) SignWithSharedKey(sharedKeyCredential *SharedKey
|
|||
}
|
||||
v.Permissions = perms.String()
|
||||
|
||||
resources, err := parseAccountResourceTypes(v.ResourceTypes)
|
||||
if err != nil {
|
||||
return QueryParameters{}, err
|
||||
}
|
||||
v.ResourceTypes = resources.String()
|
||||
|
||||
startTime, expiryTime, _ := formatTimesForSigning(v.StartTime, v.ExpiryTime, time.Time{})
|
||||
|
||||
stringToSign := strings.Join([]string{
|
||||
|
|
@ -90,13 +96,13 @@ func (v AccountSignatureValues) SignWithSharedKey(sharedKeyCredential *SharedKey
|
|||
}
|
||||
|
||||
// AccountPermissions type simplifies creating the permissions string for an Azure Storage Account SAS.
|
||||
// Initialize an instance of this type and then call Client.GetSASURL with it or use the String method to set AccountSASSignatureValues Permissions field.
|
||||
// Initialize an instance of this type and then call its String method to set AccountSignatureValues' Permissions field.
|
||||
type AccountPermissions struct {
|
||||
Read, Write, Delete, DeletePreviousVersion, PermanentDelete, List, Add, Create, Update, Process, FilterByTags, Tag, SetImmutabilityPolicy bool
|
||||
}
|
||||
|
||||
// String produces the SAS permissions string for an Azure Storage account.
|
||||
// Call this method to set AccountSASSignatureValues' Permissions field.
|
||||
// Call this method to set AccountSignatureValues' Permissions field.
|
||||
func (p *AccountPermissions) String() string {
|
||||
var buffer bytes.Buffer
|
||||
if p.Read {
|
||||
|
|
@ -141,7 +147,7 @@ func (p *AccountPermissions) String() string {
|
|||
return buffer.String()
|
||||
}
|
||||
|
||||
// Parse initializes the AccountSASPermissions' fields from a string.
|
||||
// Parse initializes the AccountPermissions' fields from a string.
|
||||
func parseAccountPermissions(s string) (AccountPermissions, error) {
|
||||
p := AccountPermissions{} // Clear out the flags
|
||||
for _, r := range s {
|
||||
|
|
@ -180,13 +186,13 @@ func parseAccountPermissions(s string) (AccountPermissions, error) {
|
|||
}
|
||||
|
||||
// AccountResourceTypes type simplifies creating the resource types string for an Azure Storage Account SAS.
|
||||
// Initialize an instance of this type and then call its String method to set AccountSASSignatureValues' ResourceTypes field.
|
||||
// Initialize an instance of this type and then call its String method to set AccountSignatureValues' ResourceTypes field.
|
||||
type AccountResourceTypes struct {
|
||||
Service, Container, Object bool
|
||||
}
|
||||
|
||||
// String produces the SAS resource types string for an Azure Storage account.
|
||||
// Call this method to set AccountSASSignatureValues' ResourceTypes field.
|
||||
// Call this method to set AccountSignatureValues' ResourceTypes field.
|
||||
func (rt *AccountResourceTypes) String() string {
|
||||
var buffer bytes.Buffer
|
||||
if rt.Service {
|
||||
|
|
@ -200,3 +206,21 @@ func (rt *AccountResourceTypes) String() string {
|
|||
}
|
||||
return buffer.String()
|
||||
}
|
||||
|
||||
// parseAccountResourceTypes initializes the AccountResourceTypes' fields from a string.
|
||||
func parseAccountResourceTypes(s string) (AccountResourceTypes, error) {
|
||||
rt := AccountResourceTypes{}
|
||||
for _, r := range s {
|
||||
switch r {
|
||||
case 's':
|
||||
rt.Service = true
|
||||
case 'c':
|
||||
rt.Container = true
|
||||
case 'o':
|
||||
rt.Object = true
|
||||
default:
|
||||
return AccountResourceTypes{}, fmt.Errorf("invalid resource type character: '%v'", r)
|
||||
}
|
||||
}
|
||||
return rt, nil
|
||||
}
|
||||
|
|
|
|||
28
vendor/github.com/Azure/azure-sdk-for-go/sdk/storage/azblob/sas/service.go
generated
vendored
28
vendor/github.com/Azure/azure-sdk-for-go/sdk/storage/azblob/sas/service.go
generated
vendored
|
|
@ -8,6 +8,7 @@ package sas
|
|||
|
||||
import (
|
||||
"bytes"
|
||||
"errors"
|
||||
"fmt"
|
||||
"strings"
|
||||
"time"
|
||||
|
|
@ -24,7 +25,7 @@ type BlobSignatureValues struct {
|
|||
StartTime time.Time `param:"st"` // Not specified if IsZero
|
||||
ExpiryTime time.Time `param:"se"` // Not specified if IsZero
|
||||
SnapshotTime time.Time
|
||||
Permissions string `param:"sp"` // Create by initializing a ContainerSASPermissions or BlobSASPermissions and then call String()
|
||||
Permissions string `param:"sp"` // Create by initializing ContainerPermissions or BlobPermissions and then call String()
|
||||
IPRange IPRange `param:"sip"`
|
||||
Identifier string `param:"si"`
|
||||
ContainerName string
|
||||
|
|
@ -50,8 +51,8 @@ func getDirectoryDepth(path string) string {
|
|||
|
||||
// SignWithSharedKey uses an account's SharedKeyCredential to sign this signature values to produce the proper SAS query parameters.
|
||||
func (v BlobSignatureValues) SignWithSharedKey(sharedKeyCredential *SharedKeyCredential) (QueryParameters, error) {
|
||||
if sharedKeyCredential == nil {
|
||||
return QueryParameters{}, fmt.Errorf("cannot sign SAS query without Shared Key Credential")
|
||||
if v.ExpiryTime.IsZero() || v.Permissions == "" {
|
||||
return QueryParameters{}, errors.New("service SAS is missing at least one of these: ExpiryTime or Permissions")
|
||||
}
|
||||
|
||||
//Make sure the permission characters are in the correct order
|
||||
|
|
@ -141,6 +142,10 @@ func (v BlobSignatureValues) SignWithUserDelegation(userDelegationCredential *Us
|
|||
return QueryParameters{}, fmt.Errorf("cannot sign SAS query without User Delegation Key")
|
||||
}
|
||||
|
||||
if v.ExpiryTime.IsZero() || v.Permissions == "" {
|
||||
return QueryParameters{}, errors.New("user delegation SAS is missing at least one of these: ExpiryTime or Permissions")
|
||||
}
|
||||
|
||||
// Parse the resource
|
||||
resource := "c"
|
||||
if !v.SnapshotTime.IsZero() {
|
||||
|
|
@ -261,15 +266,15 @@ func getCanonicalName(account string, containerName string, blobName string, dir
|
|||
}
|
||||
|
||||
// ContainerPermissions type simplifies creating the permissions string for an Azure Storage container SAS.
|
||||
// Initialize an instance of this type and then call Client.GetSASURL with it or use the String method to set BlobSASSignatureValues Permissions field.
|
||||
// Initialize an instance of this type and then call its String method to set BlobSignatureValues' Permissions field.
|
||||
// All permissions descriptions can be found here: https://docs.microsoft.com/en-us/rest/api/storageservices/create-service-sas#permissions-for-a-directory-container-or-blob
|
||||
type ContainerPermissions struct {
|
||||
Read, Add, Create, Write, Delete, DeletePreviousVersion, List, FilterByTags, Move, SetImmutabilityPolicy bool
|
||||
Execute, ModifyOwnership, ModifyPermissions bool // Meant for hierarchical namespace accounts
|
||||
Read, Add, Create, Write, Delete, DeletePreviousVersion, List, Tag, FilterByTags, Move, SetImmutabilityPolicy bool
|
||||
Execute, ModifyOwnership, ModifyPermissions bool // Meant for hierarchical namespace accounts
|
||||
}
|
||||
|
||||
// String produces the SAS permissions string for an Azure Storage container.
|
||||
// Call this method to set BlobSASSignatureValues' Permissions field.
|
||||
// Call this method to set BlobSignatureValues' Permissions field.
|
||||
func (p *ContainerPermissions) String() string {
|
||||
var b bytes.Buffer
|
||||
if p.Read {
|
||||
|
|
@ -293,6 +298,9 @@ func (p *ContainerPermissions) String() string {
|
|||
if p.List {
|
||||
b.WriteRune('l')
|
||||
}
|
||||
if p.Tag {
|
||||
b.WriteRune('t')
|
||||
}
|
||||
if p.FilterByTags {
|
||||
b.WriteRune('f')
|
||||
}
|
||||
|
|
@ -333,6 +341,8 @@ func parseContainerPermissions(s string) (ContainerPermissions, error) {
|
|||
p.DeletePreviousVersion = true
|
||||
case 'l':
|
||||
p.List = true
|
||||
case 't':
|
||||
p.Tag = true
|
||||
case 'f':
|
||||
p.FilterByTags = true
|
||||
case 'm':
|
||||
|
|
@ -353,13 +363,13 @@ func parseContainerPermissions(s string) (ContainerPermissions, error) {
|
|||
}
|
||||
|
||||
// BlobPermissions type simplifies creating the permissions string for an Azure Storage blob SAS.
|
||||
// Initialize an instance of this type and then call Client.GetSASURL with it or use the String method to set BlobSASSignatureValues Permissions field.
|
||||
// Initialize an instance of this type and then call its String method to set BlobSignatureValues' Permissions field.
|
||||
type BlobPermissions struct {
|
||||
Read, Add, Create, Write, Delete, DeletePreviousVersion, PermanentDelete, List, Tag, Move, Execute, Ownership, Permissions, SetImmutabilityPolicy bool
|
||||
}
|
||||
|
||||
// String produces the SAS permissions string for an Azure Storage blob.
|
||||
// Call this method to set BlobSignatureValue's Permissions field.
|
||||
// Call this method to set BlobSignatureValues' Permissions field.
|
||||
func (p *BlobPermissions) String() string {
|
||||
var b bytes.Buffer
|
||||
if p.Read {
|
||||
|
|
|
|||
94
vendor/github.com/Azure/azure-sdk-for-go/sdk/storage/azblob/service/batch_builder.go
generated
vendored
Normal file
94
vendor/github.com/Azure/azure-sdk-for-go/sdk/storage/azblob/service/batch_builder.go
generated
vendored
Normal file
|
|
@ -0,0 +1,94 @@
|
|||
//go:build go1.18
|
||||
// +build go1.18
|
||||
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// Licensed under the MIT License. See License.txt in the project root for license information.
|
||||
|
||||
package service
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"net/url"
|
||||
|
||||
"github.com/Azure/azure-sdk-for-go/sdk/azcore/policy"
|
||||
"github.com/Azure/azure-sdk-for-go/sdk/azcore/runtime"
|
||||
"github.com/Azure/azure-sdk-for-go/sdk/storage/azblob/blob"
|
||||
"github.com/Azure/azure-sdk-for-go/sdk/storage/azblob/internal/exported"
|
||||
)
|
||||
|
||||
// BatchBuilder is used for creating the batch operations list. It contains the list of either delete or set tier sub-requests.
|
||||
// NOTE: All sub-requests in the batch must be of the same type, either delete or set tier.
|
||||
type BatchBuilder struct {
|
||||
endpoint string
|
||||
authPolicy policy.Policy
|
||||
subRequests []*policy.Request
|
||||
operationType *exported.BlobBatchOperationType
|
||||
}
|
||||
|
||||
func (bb *BatchBuilder) checkOperationType(operationType exported.BlobBatchOperationType) error {
|
||||
if bb.operationType == nil {
|
||||
bb.operationType = &operationType
|
||||
return nil
|
||||
}
|
||||
if *bb.operationType != operationType {
|
||||
return fmt.Errorf("BlobBatch only supports one operation type per batch and is already being used for %s operations", *bb.operationType)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// Delete operation is used to add delete sub-request to the batch builder.
|
||||
func (bb *BatchBuilder) Delete(containerName string, blobName string, options *BatchDeleteOptions) error {
|
||||
err := bb.checkOperationType(exported.BatchDeleteOperationType)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
blobName = url.PathEscape(blobName)
|
||||
blobURL := runtime.JoinPaths(bb.endpoint, containerName, blobName)
|
||||
|
||||
blobClient, err := blob.NewClientWithNoCredential(blobURL, nil)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
deleteOptions, leaseInfo, accessConditions := options.format()
|
||||
req, err := getGeneratedBlobClient(blobClient).DeleteCreateRequest(context.TODO(), deleteOptions, leaseInfo, accessConditions)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// remove x-ms-version header
|
||||
exported.UpdateSubRequestHeaders(req)
|
||||
|
||||
bb.subRequests = append(bb.subRequests, req)
|
||||
return nil
|
||||
}
|
||||
|
||||
// SetTier operation is used to add set tier sub-request to the batch builder.
|
||||
func (bb *BatchBuilder) SetTier(containerName string, blobName string, accessTier blob.AccessTier, options *BatchSetTierOptions) error {
|
||||
err := bb.checkOperationType(exported.BatchSetTierOperationType)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
blobName = url.PathEscape(blobName)
|
||||
blobURL := runtime.JoinPaths(bb.endpoint, containerName, blobName)
|
||||
|
||||
blobClient, err := blob.NewClientWithNoCredential(blobURL, nil)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
setTierOptions, leaseInfo, accessConditions := options.format()
|
||||
req, err := getGeneratedBlobClient(blobClient).SetTierCreateRequest(context.TODO(), accessTier, setTierOptions, leaseInfo, accessConditions)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// remove x-ms-version header
|
||||
exported.UpdateSubRequestHeaders(req)
|
||||
|
||||
bb.subRequests = append(bb.subRequests, req)
|
||||
return nil
|
||||
}
|
||||
91
vendor/github.com/Azure/azure-sdk-for-go/sdk/storage/azblob/service/client.go
generated
vendored
91
vendor/github.com/Azure/azure-sdk-for-go/sdk/storage/azblob/service/client.go
generated
vendored
|
|
@ -7,8 +7,13 @@
|
|||
package service
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"context"
|
||||
"errors"
|
||||
"fmt"
|
||||
"github.com/Azure/azure-sdk-for-go/sdk/azcore/streaming"
|
||||
"github.com/Azure/azure-sdk-for-go/sdk/storage/azblob/bloberror"
|
||||
"github.com/Azure/azure-sdk-for-go/sdk/storage/azblob/internal/base"
|
||||
"net/http"
|
||||
"strings"
|
||||
"time"
|
||||
|
|
@ -18,7 +23,6 @@ import (
|
|||
"github.com/Azure/azure-sdk-for-go/sdk/azcore/runtime"
|
||||
"github.com/Azure/azure-sdk-for-go/sdk/storage/azblob/blob"
|
||||
"github.com/Azure/azure-sdk-for-go/sdk/storage/azblob/container"
|
||||
"github.com/Azure/azure-sdk-for-go/sdk/storage/azblob/internal/base"
|
||||
"github.com/Azure/azure-sdk-for-go/sdk/storage/azblob/internal/exported"
|
||||
"github.com/Azure/azure-sdk-for-go/sdk/storage/azblob/internal/generated"
|
||||
"github.com/Azure/azure-sdk-for-go/sdk/storage/azblob/internal/shared"
|
||||
|
|
@ -26,9 +30,7 @@ import (
|
|||
)
|
||||
|
||||
// ClientOptions contains the optional parameters when creating a Client.
|
||||
type ClientOptions struct {
|
||||
azcore.ClientOptions
|
||||
}
|
||||
type ClientOptions base.ClientOptions
|
||||
|
||||
// Client represents a URL to the Azure Blob Storage service allowing you to manipulate blob containers.
|
||||
type Client base.Client[generated.ServiceClient]
|
||||
|
|
@ -38,12 +40,12 @@ type Client base.Client[generated.ServiceClient]
|
|||
// - cred - an Azure AD credential, typically obtained via the azidentity module
|
||||
// - options - client options; pass nil to accept the default values
|
||||
func NewClient(serviceURL string, cred azcore.TokenCredential, options *ClientOptions) (*Client, error) {
|
||||
authPolicy := runtime.NewBearerTokenPolicy(cred, []string{shared.TokenScope}, nil)
|
||||
authPolicy := shared.NewStorageChallengePolicy(cred)
|
||||
conOptions := shared.GetClientOptions(options)
|
||||
conOptions.PerRetryPolicies = append(conOptions.PerRetryPolicies, authPolicy)
|
||||
pl := runtime.NewPipeline(exported.ModuleName, exported.ModuleVersion, runtime.PipelineOptions{}, &conOptions.ClientOptions)
|
||||
|
||||
return (*Client)(base.NewServiceClient(serviceURL, pl, nil)), nil
|
||||
return (*Client)(base.NewServiceClient(serviceURL, pl, &cred)), nil
|
||||
}
|
||||
|
||||
// NewClientWithNoCredential creates an instance of Client with the specified values.
|
||||
|
|
@ -115,6 +117,15 @@ func (s *Client) sharedKey() *SharedKeyCredential {
|
|||
return base.SharedKey((*base.Client[generated.ServiceClient])(s))
|
||||
}
|
||||
|
||||
func (s *Client) credential() any {
|
||||
return base.Credential((*base.Client[generated.ServiceClient])(s))
|
||||
}
|
||||
|
||||
// helper method to return the generated.BlobClient which is used for creating the sub-requests
|
||||
func getGeneratedBlobClient(b *blob.Client) *generated.BlobClient {
|
||||
return base.InnerClient((*base.Client[generated.BlobClient])(b))
|
||||
}
|
||||
|
||||
// URL returns the URL endpoint used by the Client object.
|
||||
func (s *Client) URL() string {
|
||||
return s.generated().Endpoint()
|
||||
|
|
@ -124,7 +135,7 @@ func (s *Client) URL() string {
|
|||
// this Client's URL. The new container.Client uses the same request policy pipeline as the Client.
|
||||
func (s *Client) NewContainerClient(containerName string) *container.Client {
|
||||
containerURL := runtime.JoinPaths(s.generated().Endpoint(), containerName)
|
||||
return (*container.Client)(base.NewContainerClient(containerURL, s.generated().Pipeline(), s.sharedKey()))
|
||||
return (*container.Client)(base.NewContainerClient(containerURL, s.generated().Pipeline(), s.credential()))
|
||||
}
|
||||
|
||||
// CreateContainer is a lifecycle method to creates a new container under the specified account.
|
||||
|
|
@ -154,6 +165,7 @@ func (s *Client) RestoreContainer(ctx context.Context, deletedContainerName stri
|
|||
}
|
||||
|
||||
// GetAccountInfo provides account level information
|
||||
// For more information, see https://learn.microsoft.com/en-us/rest/api/storageservices/get-account-information?tabs=shared-access-signatures.
|
||||
func (s *Client) GetAccountInfo(ctx context.Context, o *GetAccountInfoOptions) (GetAccountInfoResponse, error) {
|
||||
getAccountInfoOptions := o.format()
|
||||
resp, err := s.generated().GetAccountInfo(ctx, getAccountInfoOptions)
|
||||
|
|
@ -280,3 +292,68 @@ func (s *Client) FilterBlobs(ctx context.Context, where string, o *FilterBlobsOp
|
|||
resp, err := s.generated().FilterBlobs(ctx, where, serviceFilterBlobsOptions)
|
||||
return resp, err
|
||||
}
|
||||
|
||||
// NewBatchBuilder creates an instance of BatchBuilder using the same auth policy as the client.
|
||||
// BatchBuilder is used to build the batch consisting of either delete or set tier sub-requests.
|
||||
// All sub-requests in the batch must be of the same type, either delete or set tier.
|
||||
// NOTE: Service level Blob Batch operation is supported only when the Client was created using SharedKeyCredential and Account SAS.
|
||||
func (s *Client) NewBatchBuilder() (*BatchBuilder, error) {
|
||||
var authPolicy policy.Policy
|
||||
|
||||
switch cred := s.credential().(type) {
|
||||
case *azcore.TokenCredential:
|
||||
authPolicy = shared.NewStorageChallengePolicy(*cred)
|
||||
case *SharedKeyCredential:
|
||||
authPolicy = exported.NewSharedKeyCredPolicy(cred)
|
||||
case nil:
|
||||
// for authentication using SAS
|
||||
authPolicy = nil
|
||||
default:
|
||||
return nil, fmt.Errorf("unrecognised authentication type %T", cred)
|
||||
}
|
||||
|
||||
return &BatchBuilder{
|
||||
endpoint: s.URL(),
|
||||
authPolicy: authPolicy,
|
||||
}, nil
|
||||
}
|
||||
|
||||
// SubmitBatch operation allows multiple API calls to be embedded into a single HTTP request.
|
||||
// It builds the request body using the BatchBuilder object passed.
|
||||
// BatchBuilder contains the list of operations to be submitted. It supports up to 256 sub-requests in a single batch.
|
||||
// For more information, see https://docs.microsoft.com/rest/api/storageservices/blob-batch.
|
||||
func (s *Client) SubmitBatch(ctx context.Context, bb *BatchBuilder, options *SubmitBatchOptions) (SubmitBatchResponse, error) {
|
||||
if bb == nil || len(bb.subRequests) == 0 {
|
||||
return SubmitBatchResponse{}, errors.New("batch builder is empty")
|
||||
}
|
||||
|
||||
// create the request body
|
||||
batchReq, batchID, err := exported.CreateBatchRequest(&exported.BlobBatchBuilder{
|
||||
AuthPolicy: bb.authPolicy,
|
||||
SubRequests: bb.subRequests,
|
||||
})
|
||||
if err != nil {
|
||||
return SubmitBatchResponse{}, err
|
||||
}
|
||||
|
||||
reader := bytes.NewReader(batchReq)
|
||||
rsc := streaming.NopCloser(reader)
|
||||
multipartContentType := "multipart/mixed; boundary=" + batchID
|
||||
|
||||
resp, err := s.generated().SubmitBatch(ctx, int64(len(batchReq)), multipartContentType, rsc, options.format())
|
||||
if err != nil {
|
||||
return SubmitBatchResponse{}, err
|
||||
}
|
||||
|
||||
batchResponses, err := exported.ParseBlobBatchResponse(resp.Body, resp.ContentType, bb.subRequests)
|
||||
if err != nil {
|
||||
return SubmitBatchResponse{}, err
|
||||
}
|
||||
|
||||
return SubmitBatchResponse{
|
||||
Responses: batchResponses,
|
||||
ContentType: resp.ContentType,
|
||||
RequestID: resp.RequestID,
|
||||
Version: resp.Version,
|
||||
}, nil
|
||||
}
|
||||
|
|
|
|||
57
vendor/github.com/Azure/azure-sdk-for-go/sdk/storage/azblob/service/models.go
generated
vendored
57
vendor/github.com/Azure/azure-sdk-for-go/sdk/storage/azblob/service/models.go
generated
vendored
|
|
@ -8,6 +8,7 @@ package service
|
|||
|
||||
import (
|
||||
"github.com/Azure/azure-sdk-for-go/sdk/azcore/to"
|
||||
"github.com/Azure/azure-sdk-for-go/sdk/storage/azblob/blob"
|
||||
"github.com/Azure/azure-sdk-for-go/sdk/storage/azblob/container"
|
||||
"github.com/Azure/azure-sdk-for-go/sdk/storage/azblob/internal/exported"
|
||||
"github.com/Azure/azure-sdk-for-go/sdk/storage/azblob/internal/generated"
|
||||
|
|
@ -299,3 +300,59 @@ func (o *FilterBlobsOptions) format() *generated.ServiceClientFilterBlobsOptions
|
|||
Maxresults: o.MaxResults,
|
||||
}
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------------------------------------------------
|
||||
|
||||
// BatchDeleteOptions contains the optional parameters for the BatchBuilder.Delete method.
|
||||
type BatchDeleteOptions struct {
|
||||
blob.DeleteOptions
|
||||
VersionID *string
|
||||
Snapshot *string
|
||||
}
|
||||
|
||||
func (o *BatchDeleteOptions) format() (*generated.BlobClientDeleteOptions, *generated.LeaseAccessConditions, *generated.ModifiedAccessConditions) {
|
||||
if o == nil {
|
||||
return nil, nil, nil
|
||||
}
|
||||
|
||||
basics := generated.BlobClientDeleteOptions{
|
||||
DeleteSnapshots: o.DeleteSnapshots,
|
||||
DeleteType: o.BlobDeleteType, // None by default
|
||||
Snapshot: o.Snapshot,
|
||||
VersionID: o.VersionID,
|
||||
}
|
||||
|
||||
leaseAccessConditions, modifiedAccessConditions := exported.FormatBlobAccessConditions(o.AccessConditions)
|
||||
return &basics, leaseAccessConditions, modifiedAccessConditions
|
||||
}
|
||||
|
||||
// BatchSetTierOptions contains the optional parameters for the BatchBuilder.SetTier method.
|
||||
type BatchSetTierOptions struct {
|
||||
blob.SetTierOptions
|
||||
VersionID *string
|
||||
Snapshot *string
|
||||
}
|
||||
|
||||
func (o *BatchSetTierOptions) format() (*generated.BlobClientSetTierOptions, *generated.LeaseAccessConditions, *generated.ModifiedAccessConditions) {
|
||||
if o == nil {
|
||||
return nil, nil, nil
|
||||
}
|
||||
|
||||
basics := generated.BlobClientSetTierOptions{
|
||||
RehydratePriority: o.RehydratePriority,
|
||||
Snapshot: o.Snapshot,
|
||||
VersionID: o.VersionID,
|
||||
}
|
||||
|
||||
leaseAccessConditions, modifiedAccessConditions := exported.FormatBlobAccessConditions(o.AccessConditions)
|
||||
return &basics, leaseAccessConditions, modifiedAccessConditions
|
||||
}
|
||||
|
||||
// SubmitBatchOptions contains the optional parameters for the Client.SubmitBatch method.
|
||||
type SubmitBatchOptions struct {
|
||||
// placeholder for future options
|
||||
}
|
||||
|
||||
func (o *SubmitBatchOptions) format() *generated.ServiceClientSubmitBatchOptions {
|
||||
return nil
|
||||
}
|
||||
|
|
|
|||
19
vendor/github.com/Azure/azure-sdk-for-go/sdk/storage/azblob/service/responses.go
generated
vendored
19
vendor/github.com/Azure/azure-sdk-for-go/sdk/storage/azblob/service/responses.go
generated
vendored
|
|
@ -7,6 +7,7 @@
|
|||
package service
|
||||
|
||||
import (
|
||||
"github.com/Azure/azure-sdk-for-go/sdk/storage/azblob/internal/exported"
|
||||
"github.com/Azure/azure-sdk-for-go/sdk/storage/azblob/internal/generated"
|
||||
)
|
||||
|
||||
|
|
@ -42,3 +43,21 @@ type FilterBlobsResponse = generated.ServiceClientFilterBlobsResponse
|
|||
|
||||
// GetUserDelegationKeyResponse contains the response from method ServiceClient.GetUserDelegationKey.
|
||||
type GetUserDelegationKeyResponse = generated.ServiceClientGetUserDelegationKeyResponse
|
||||
|
||||
// SubmitBatchResponse contains the response from method Client.SubmitBatch.
|
||||
type SubmitBatchResponse struct {
|
||||
// Responses contains the responses of the sub-requests in the batch
|
||||
Responses []*BatchResponseItem
|
||||
|
||||
// ContentType contains the information returned from the Content-Type header response.
|
||||
ContentType *string
|
||||
|
||||
// RequestID contains the information returned from the x-ms-request-id header response.
|
||||
RequestID *string
|
||||
|
||||
// Version contains the information returned from the x-ms-version header response.
|
||||
Version *string
|
||||
}
|
||||
|
||||
// BatchResponseItem contains the response for the individual sub-requests.
|
||||
type BatchResponseItem = exported.BatchResponseItem
|
||||
|
|
|
|||
8
vendor/github.com/Azure/go-autorest/autorest/adal/README.md
generated
vendored
8
vendor/github.com/Azure/go-autorest/autorest/adal/README.md
generated
vendored
|
|
@ -1,3 +1,5 @@
|
|||
# NOTE: This module will go out of support by March 31, 2023. For authenticating with Azure AD, use module [azidentity](https://pkg.go.dev/github.com/Azure/azure-sdk-for-go/sdk/azidentity) instead. For help migrating from `adal` to `azidentiy` please consult the [migration guide](https://aka.ms/azsdk/go/identity/migration). General information about the retirement of this and other legacy modules can be found [here](https://azure.microsoft.com/updates/support-for-azure-sdk-libraries-that-do-not-conform-to-our-current-azure-sdk-guidelines-will-be-retired-as-of-31-march-2023/).
|
||||
|
||||
# Azure Active Directory authentication for Go
|
||||
|
||||
This is a standalone package for authenticating with Azure Active
|
||||
|
|
@ -18,7 +20,7 @@ go get -u github.com/Azure/go-autorest/autorest/adal
|
|||
|
||||
## Usage
|
||||
|
||||
An Active Directory application is required in order to use this library. An application can be registered in the [Azure Portal](https://portal.azure.com/) by following these [guidelines](https://docs.microsoft.com/en-us/azure/active-directory/develop/active-directory-integrating-applications) or using the [Azure CLI](https://github.com/Azure/azure-cli).
|
||||
An Active Directory application is required in order to use this library. An application can be registered in the [Azure Portal](https://portal.azure.com/) by following these [guidelines](https://docs.microsoft.com/azure/active-directory/develop/active-directory-integrating-applications) or using the [Azure CLI](https://github.com/Azure/azure-cli).
|
||||
|
||||
### Register an Azure AD Application with secret
|
||||
|
||||
|
|
@ -88,7 +90,7 @@ An Active Directory application is required in order to use this library. An app
|
|||
### Grant the necessary permissions
|
||||
|
||||
Azure relies on a Role-Based Access Control (RBAC) model to manage the access to resources at a fine-grained
|
||||
level. There is a set of [pre-defined roles](https://docs.microsoft.com/en-us/azure/active-directory/role-based-access-built-in-roles)
|
||||
level. There is a set of [pre-defined roles](https://docs.microsoft.com/azure/active-directory/role-based-access-built-in-roles)
|
||||
which can be assigned to a service principal of an Azure AD application depending of your needs.
|
||||
|
||||
```
|
||||
|
|
@ -104,7 +106,7 @@ It is also possible to define custom role definitions.
|
|||
az role definition create --role-definition role-definition.json
|
||||
```
|
||||
|
||||
* Check [custom roles](https://docs.microsoft.com/en-us/azure/active-directory/role-based-access-control-custom-roles) for more details regarding the content of `role-definition.json` file.
|
||||
* Check [custom roles](https://docs.microsoft.com/azure/active-directory/role-based-access-control-custom-roles) for more details regarding the content of `role-definition.json` file.
|
||||
|
||||
|
||||
### Acquire Access Token
|
||||
|
|
|
|||
94
vendor/github.com/Azure/go-autorest/autorest/adal/token.go
generated
vendored
94
vendor/github.com/Azure/go-autorest/autorest/adal/token.go
generated
vendored
|
|
@ -177,7 +177,7 @@ func (t Token) WillExpireIn(d time.Duration) bool {
|
|||
return !t.Expires().After(time.Now().Add(d))
|
||||
}
|
||||
|
||||
//OAuthToken return the current access token
|
||||
// OAuthToken return the current access token
|
||||
func (t *Token) OAuthToken() string {
|
||||
return t.AccessToken
|
||||
}
|
||||
|
|
@ -365,6 +365,25 @@ func (secret ServicePrincipalAuthorizationCodeSecret) MarshalJSON() ([]byte, err
|
|||
})
|
||||
}
|
||||
|
||||
// ServicePrincipalFederatedSecret implements ServicePrincipalSecret for Federated JWTs.
|
||||
type ServicePrincipalFederatedSecret struct {
|
||||
jwt string
|
||||
}
|
||||
|
||||
// SetAuthenticationValues is a method of the interface ServicePrincipalSecret.
|
||||
// It will populate the form submitted during OAuth Token Acquisition using a JWT signed by an OIDC issuer.
|
||||
func (secret *ServicePrincipalFederatedSecret) SetAuthenticationValues(spt *ServicePrincipalToken, v *url.Values) error {
|
||||
|
||||
v.Set("client_assertion", secret.jwt)
|
||||
v.Set("client_assertion_type", "urn:ietf:params:oauth:client-assertion-type:jwt-bearer")
|
||||
return nil
|
||||
}
|
||||
|
||||
// MarshalJSON implements the json.Marshaler interface.
|
||||
func (secret ServicePrincipalFederatedSecret) MarshalJSON() ([]byte, error) {
|
||||
return nil, errors.New("marshalling ServicePrincipalFederatedSecret is not supported")
|
||||
}
|
||||
|
||||
// ServicePrincipalToken encapsulates a Token created for a Service Principal.
|
||||
type ServicePrincipalToken struct {
|
||||
inner servicePrincipalToken
|
||||
|
|
@ -419,6 +438,8 @@ func (spt *ServicePrincipalToken) UnmarshalJSON(data []byte) error {
|
|||
spt.inner.Secret = &ServicePrincipalUsernamePasswordSecret{}
|
||||
case "ServicePrincipalAuthorizationCodeSecret":
|
||||
spt.inner.Secret = &ServicePrincipalAuthorizationCodeSecret{}
|
||||
case "ServicePrincipalFederatedSecret":
|
||||
return errors.New("unmarshalling ServicePrincipalFederatedSecret is not supported")
|
||||
default:
|
||||
return fmt.Errorf("unrecognized token type '%s'", secret["type"])
|
||||
}
|
||||
|
|
@ -665,6 +686,31 @@ func NewServicePrincipalTokenFromAuthorizationCode(oauthConfig OAuthConfig, clie
|
|||
)
|
||||
}
|
||||
|
||||
// NewServicePrincipalTokenFromFederatedToken creates a ServicePrincipalToken from the supplied federated OIDC JWT.
|
||||
func NewServicePrincipalTokenFromFederatedToken(oauthConfig OAuthConfig, clientID string, jwt string, resource string, callbacks ...TokenRefreshCallback) (*ServicePrincipalToken, error) {
|
||||
if err := validateOAuthConfig(oauthConfig); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if err := validateStringParam(clientID, "clientID"); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if err := validateStringParam(resource, "resource"); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if jwt == "" {
|
||||
return nil, fmt.Errorf("parameter 'jwt' cannot be empty")
|
||||
}
|
||||
return NewServicePrincipalTokenWithSecret(
|
||||
oauthConfig,
|
||||
clientID,
|
||||
resource,
|
||||
&ServicePrincipalFederatedSecret{
|
||||
jwt: jwt,
|
||||
},
|
||||
callbacks...,
|
||||
)
|
||||
}
|
||||
|
||||
type msiType int
|
||||
|
||||
const (
|
||||
|
|
@ -1058,8 +1104,8 @@ func (spt *ServicePrincipalToken) refreshInternal(ctx context.Context, resource
|
|||
|
||||
// AAD returns expires_in as a string, ADFS returns it as an int
|
||||
ExpiresIn json.Number `json:"expires_in"`
|
||||
// expires_on can be in two formats, a UTC time stamp or the number of seconds.
|
||||
ExpiresOn string `json:"expires_on"`
|
||||
// expires_on can be in three formats, a UTC time stamp, or the number of seconds as a string *or* int.
|
||||
ExpiresOn interface{} `json:"expires_on"`
|
||||
NotBefore json.Number `json:"not_before"`
|
||||
|
||||
Resource string `json:"resource"`
|
||||
|
|
@ -1072,7 +1118,7 @@ func (spt *ServicePrincipalToken) refreshInternal(ctx context.Context, resource
|
|||
}
|
||||
expiresOn := json.Number("")
|
||||
// ADFS doesn't include the expires_on field
|
||||
if token.ExpiresOn != "" {
|
||||
if token.ExpiresOn != nil {
|
||||
if expiresOn, err = parseExpiresOn(token.ExpiresOn); err != nil {
|
||||
return newTokenRefreshError(fmt.Sprintf("adal: failed to parse expires_on: %v value '%s'", err, token.ExpiresOn), resp)
|
||||
}
|
||||
|
|
@ -1089,18 +1135,27 @@ func (spt *ServicePrincipalToken) refreshInternal(ctx context.Context, resource
|
|||
}
|
||||
|
||||
// converts expires_on to the number of seconds
|
||||
func parseExpiresOn(s string) (json.Number, error) {
|
||||
// convert the expiration date to the number of seconds from now
|
||||
timeToDuration := func(t time.Time) json.Number {
|
||||
dur := t.Sub(time.Now().UTC())
|
||||
return json.Number(strconv.FormatInt(int64(dur.Round(time.Second).Seconds()), 10))
|
||||
func parseExpiresOn(s interface{}) (json.Number, error) {
|
||||
// the JSON unmarshaler treats JSON numbers unmarshaled into an interface{} as float64
|
||||
asFloat64, ok := s.(float64)
|
||||
if ok {
|
||||
// this is the number of seconds as int case
|
||||
return json.Number(strconv.FormatInt(int64(asFloat64), 10)), nil
|
||||
}
|
||||
if _, err := strconv.ParseInt(s, 10, 64); err == nil {
|
||||
asStr, ok := s.(string)
|
||||
if !ok {
|
||||
return "", fmt.Errorf("unexpected expires_on type %T", s)
|
||||
}
|
||||
// convert the expiration date to the number of seconds from the unix epoch
|
||||
timeToDuration := func(t time.Time) json.Number {
|
||||
return json.Number(strconv.FormatInt(t.UTC().Unix(), 10))
|
||||
}
|
||||
if _, err := json.Number(asStr).Int64(); err == nil {
|
||||
// this is the number of seconds case, no conversion required
|
||||
return json.Number(s), nil
|
||||
} else if eo, err := time.Parse(expiresOnDateFormatPM, s); err == nil {
|
||||
return json.Number(asStr), nil
|
||||
} else if eo, err := time.Parse(expiresOnDateFormatPM, asStr); err == nil {
|
||||
return timeToDuration(eo), nil
|
||||
} else if eo, err := time.Parse(expiresOnDateFormat, s); err == nil {
|
||||
} else if eo, err := time.Parse(expiresOnDateFormat, asStr); err == nil {
|
||||
return timeToDuration(eo), nil
|
||||
} else {
|
||||
// unknown format
|
||||
|
|
@ -1317,12 +1372,25 @@ func NewMultiTenantServicePrincipalTokenFromCertificate(multiTenantCfg MultiTena
|
|||
|
||||
// MSIAvailable returns true if the MSI endpoint is available for authentication.
|
||||
func MSIAvailable(ctx context.Context, s Sender) bool {
|
||||
msiType, _, err := getMSIType()
|
||||
|
||||
if err != nil {
|
||||
return false
|
||||
}
|
||||
|
||||
if msiType != msiTypeIMDS {
|
||||
return true
|
||||
}
|
||||
|
||||
if s == nil {
|
||||
s = sender()
|
||||
}
|
||||
|
||||
resp, err := getMSIEndpoint(ctx, s)
|
||||
|
||||
if err == nil {
|
||||
resp.Body.Close()
|
||||
}
|
||||
|
||||
return err == nil
|
||||
}
|
||||
|
|
|
|||
32
vendor/github.com/Azure/go-autorest/autorest/autorest.go
generated
vendored
32
vendor/github.com/Azure/go-autorest/autorest/autorest.go
generated
vendored
|
|
@ -6,33 +6,33 @@ generated Go code.
|
|||
The package breaks sending and responding to HTTP requests into three phases: Preparing, Sending,
|
||||
and Responding. A typical pattern is:
|
||||
|
||||
req, err := Prepare(&http.Request{},
|
||||
token.WithAuthorization())
|
||||
req, err := Prepare(&http.Request{},
|
||||
token.WithAuthorization())
|
||||
|
||||
resp, err := Send(req,
|
||||
WithLogging(logger),
|
||||
DoErrorIfStatusCode(http.StatusInternalServerError),
|
||||
DoCloseIfError(),
|
||||
DoRetryForAttempts(5, time.Second))
|
||||
resp, err := Send(req,
|
||||
WithLogging(logger),
|
||||
DoErrorIfStatusCode(http.StatusInternalServerError),
|
||||
DoCloseIfError(),
|
||||
DoRetryForAttempts(5, time.Second))
|
||||
|
||||
err = Respond(resp,
|
||||
ByDiscardingBody(),
|
||||
ByClosing())
|
||||
err = Respond(resp,
|
||||
ByDiscardingBody(),
|
||||
ByClosing())
|
||||
|
||||
Each phase relies on decorators to modify and / or manage processing. Decorators may first modify
|
||||
and then pass the data along, pass the data first and then modify the result, or wrap themselves
|
||||
around passing the data (such as a logger might do). Decorators run in the order provided. For
|
||||
example, the following:
|
||||
|
||||
req, err := Prepare(&http.Request{},
|
||||
WithBaseURL("https://microsoft.com/"),
|
||||
WithPath("a"),
|
||||
WithPath("b"),
|
||||
WithPath("c"))
|
||||
req, err := Prepare(&http.Request{},
|
||||
WithBaseURL("https://microsoft.com/"),
|
||||
WithPath("a"),
|
||||
WithPath("b"),
|
||||
WithPath("c"))
|
||||
|
||||
will set the URL to:
|
||||
|
||||
https://microsoft.com/a/b/c
|
||||
https://microsoft.com/a/b/c
|
||||
|
||||
Preparers and Responders may be shared and re-used (assuming the underlying decorators support
|
||||
sharing and re-use). Performant use is obtained by creating one or more Preparers and Responders
|
||||
|
|
|
|||
2
vendor/github.com/Azure/go-autorest/autorest/azure/azure.go
generated
vendored
2
vendor/github.com/Azure/go-autorest/autorest/azure/azure.go
generated
vendored
|
|
@ -214,7 +214,7 @@ func (r Resource) String() string {
|
|||
// See https://docs.microsoft.com/en-us/azure/azure-resource-manager/templates/template-functions-resource?tabs=json#resourceid.
|
||||
func ParseResourceID(resourceID string) (Resource, error) {
|
||||
|
||||
const resourceIDPatternText = `(?i)subscriptions/(.+)/resourceGroups/(.+)/providers/(.+?)/(.+?)/(.+)`
|
||||
const resourceIDPatternText = `(?i)^/subscriptions/(.+)/resourceGroups/(.+)/providers/(.+?)/(.+?)/(.+)$`
|
||||
resourceIDPattern := regexp.MustCompile(resourceIDPatternText)
|
||||
match := resourceIDPattern.FindStringSubmatch(resourceID)
|
||||
|
||||
|
|
|
|||
6
vendor/github.com/Azure/go-autorest/autorest/utility.go
generated
vendored
6
vendor/github.com/Azure/go-autorest/autorest/utility.go
generated
vendored
|
|
@ -60,9 +60,9 @@ func NewDecoder(encodedAs EncodedAs, r io.Reader) Decoder {
|
|||
// is especially useful if there is a chance the data will fail to decode.
|
||||
// encodedAs specifies the expected encoding, r provides the io.Reader to the data, and v
|
||||
// is the decoding destination.
|
||||
func CopyAndDecode(encodedAs EncodedAs, r io.Reader, v interface{}) (bytes.Buffer, error) {
|
||||
b := bytes.Buffer{}
|
||||
return b, NewDecoder(encodedAs, io.TeeReader(r, &b)).Decode(v)
|
||||
func CopyAndDecode(encodedAs EncodedAs, r io.Reader, v interface{}) (b bytes.Buffer, err error) {
|
||||
err = NewDecoder(encodedAs, io.TeeReader(r, &b)).Decode(v)
|
||||
return
|
||||
}
|
||||
|
||||
// TeeReadCloser returns a ReadCloser that writes to w what it reads from rc.
|
||||
|
|
|
|||
4
vendor/github.com/BurntSushi/toml/decode.go
generated
vendored
4
vendor/github.com/BurntSushi/toml/decode.go
generated
vendored
|
|
@ -91,7 +91,7 @@ const (
|
|||
// UnmarshalText method. See the Unmarshaler example for a demonstration with
|
||||
// email addresses.
|
||||
//
|
||||
// ### Key mapping
|
||||
// # Key mapping
|
||||
//
|
||||
// TOML keys can map to either keys in a Go map or field names in a Go struct.
|
||||
// The special `toml` struct tag can be used to map TOML keys to struct fields
|
||||
|
|
@ -248,7 +248,7 @@ func (md *MetaData) unify(data interface{}, rv reflect.Value) error {
|
|||
case reflect.Bool:
|
||||
return md.unifyBool(data, rv)
|
||||
case reflect.Interface:
|
||||
if rv.NumMethod() > 0 { // Only support empty interfaces are supported.
|
||||
if rv.NumMethod() > 0 { /// Only empty interfaces are supported.
|
||||
return md.e("unsupported type %s", rv.Type())
|
||||
}
|
||||
return md.unifyAnything(data, rv)
|
||||
|
|
|
|||
8
vendor/github.com/BurntSushi/toml/deprecated.go
generated
vendored
8
vendor/github.com/BurntSushi/toml/deprecated.go
generated
vendored
|
|
@ -5,17 +5,25 @@ import (
|
|||
"io"
|
||||
)
|
||||
|
||||
// TextMarshaler is an alias for encoding.TextMarshaler.
|
||||
//
|
||||
// Deprecated: use encoding.TextMarshaler
|
||||
type TextMarshaler encoding.TextMarshaler
|
||||
|
||||
// TextUnmarshaler is an alias for encoding.TextUnmarshaler.
|
||||
//
|
||||
// Deprecated: use encoding.TextUnmarshaler
|
||||
type TextUnmarshaler encoding.TextUnmarshaler
|
||||
|
||||
// PrimitiveDecode is an alias for MetaData.PrimitiveDecode().
|
||||
//
|
||||
// Deprecated: use MetaData.PrimitiveDecode.
|
||||
func PrimitiveDecode(primValue Primitive, v interface{}) error {
|
||||
md := MetaData{decoded: make(map[string]struct{})}
|
||||
return md.unify(primValue.undecoded, rvalue(v))
|
||||
}
|
||||
|
||||
// DecodeReader is an alias for NewDecoder(r).Decode(v).
|
||||
//
|
||||
// Deprecated: use NewDecoder(reader).Decode(&value).
|
||||
func DecodeReader(r io.Reader, v interface{}) (MetaData, error) { return NewDecoder(r).Decode(v) }
|
||||
|
|
|
|||
55
vendor/github.com/BurntSushi/toml/encode.go
generated
vendored
55
vendor/github.com/BurntSushi/toml/encode.go
generated
vendored
|
|
@ -136,7 +136,8 @@ func NewEncoder(w io.Writer) *Encoder {
|
|||
// document.
|
||||
func (enc *Encoder) Encode(v interface{}) error {
|
||||
rv := eindirect(reflect.ValueOf(v))
|
||||
if err := enc.safeEncode(Key([]string{}), rv); err != nil {
|
||||
err := enc.safeEncode(Key([]string{}), rv)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return enc.w.Flush()
|
||||
|
|
@ -457,6 +458,16 @@ func (enc *Encoder) eStruct(key Key, rv reflect.Value, inline bool) {
|
|||
|
||||
frv := eindirect(rv.Field(i))
|
||||
|
||||
if is32Bit {
|
||||
// Copy so it works correct on 32bit archs; not clear why this
|
||||
// is needed. See #314, and https://www.reddit.com/r/golang/comments/pnx8v4
|
||||
// This also works fine on 64bit, but 32bit archs are somewhat
|
||||
// rare and this is a wee bit faster.
|
||||
copyStart := make([]int, len(start))
|
||||
copy(copyStart, start)
|
||||
start = copyStart
|
||||
}
|
||||
|
||||
// Treat anonymous struct fields with tag names as though they are
|
||||
// not anonymous, like encoding/json does.
|
||||
//
|
||||
|
|
@ -471,17 +482,7 @@ func (enc *Encoder) eStruct(key Key, rv reflect.Value, inline bool) {
|
|||
if typeIsTable(tomlTypeOfGo(frv)) {
|
||||
fieldsSub = append(fieldsSub, append(start, f.Index...))
|
||||
} else {
|
||||
// Copy so it works correct on 32bit archs; not clear why this
|
||||
// is needed. See #314, and https://www.reddit.com/r/golang/comments/pnx8v4
|
||||
// This also works fine on 64bit, but 32bit archs are somewhat
|
||||
// rare and this is a wee bit faster.
|
||||
if is32Bit {
|
||||
copyStart := make([]int, len(start))
|
||||
copy(copyStart, start)
|
||||
fieldsDirect = append(fieldsDirect, append(copyStart, f.Index...))
|
||||
} else {
|
||||
fieldsDirect = append(fieldsDirect, append(start, f.Index...))
|
||||
}
|
||||
fieldsDirect = append(fieldsDirect, append(start, f.Index...))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -490,24 +491,27 @@ func (enc *Encoder) eStruct(key Key, rv reflect.Value, inline bool) {
|
|||
writeFields := func(fields [][]int) {
|
||||
for _, fieldIndex := range fields {
|
||||
fieldType := rt.FieldByIndex(fieldIndex)
|
||||
fieldVal := eindirect(rv.FieldByIndex(fieldIndex))
|
||||
|
||||
if isNil(fieldVal) { /// Don't write anything for nil fields.
|
||||
continue
|
||||
}
|
||||
fieldVal := rv.FieldByIndex(fieldIndex)
|
||||
|
||||
opts := getOptions(fieldType.Tag)
|
||||
if opts.skip {
|
||||
continue
|
||||
}
|
||||
if opts.omitempty && isEmpty(fieldVal) {
|
||||
continue
|
||||
}
|
||||
|
||||
fieldVal = eindirect(fieldVal)
|
||||
|
||||
if isNil(fieldVal) { /// Don't write anything for nil fields.
|
||||
continue
|
||||
}
|
||||
|
||||
keyName := fieldType.Name
|
||||
if opts.name != "" {
|
||||
keyName = opts.name
|
||||
}
|
||||
|
||||
if opts.omitempty && enc.isEmpty(fieldVal) {
|
||||
continue
|
||||
}
|
||||
if opts.omitzero && isZero(fieldVal) {
|
||||
continue
|
||||
}
|
||||
|
|
@ -649,7 +653,7 @@ func isZero(rv reflect.Value) bool {
|
|||
return false
|
||||
}
|
||||
|
||||
func (enc *Encoder) isEmpty(rv reflect.Value) bool {
|
||||
func isEmpty(rv reflect.Value) bool {
|
||||
switch rv.Kind() {
|
||||
case reflect.Array, reflect.Slice, reflect.Map, reflect.String:
|
||||
return rv.Len() == 0
|
||||
|
|
@ -664,13 +668,15 @@ func (enc *Encoder) isEmpty(rv reflect.Value) bool {
|
|||
// type b struct{ s []string }
|
||||
// s := a{field: b{s: []string{"AAA"}}}
|
||||
for i := 0; i < rv.NumField(); i++ {
|
||||
if !enc.isEmpty(rv.Field(i)) {
|
||||
if !isEmpty(rv.Field(i)) {
|
||||
return false
|
||||
}
|
||||
}
|
||||
return true
|
||||
case reflect.Bool:
|
||||
return !rv.Bool()
|
||||
case reflect.Ptr:
|
||||
return rv.IsNil()
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
|
@ -693,8 +699,11 @@ func (enc *Encoder) newline() {
|
|||
// v v v v vv
|
||||
// key = {k = 1, k2 = 2}
|
||||
func (enc *Encoder) writeKeyValue(key Key, val reflect.Value, inline bool) {
|
||||
/// Marshaler used on top-level document; call eElement() to just call
|
||||
/// Marshal{TOML,Text}.
|
||||
if len(key) == 0 {
|
||||
encPanic(errNoKey)
|
||||
enc.eElement(val)
|
||||
return
|
||||
}
|
||||
enc.wf("%s%s = ", enc.indentStr(key), key.maybeQuoted(len(key)-1))
|
||||
enc.eElement(val)
|
||||
|
|
|
|||
4
vendor/github.com/BurntSushi/toml/error.go
generated
vendored
4
vendor/github.com/BurntSushi/toml/error.go
generated
vendored
|
|
@ -84,7 +84,7 @@ func (pe ParseError) Error() string {
|
|||
pe.Position.Line, pe.LastKey, msg)
|
||||
}
|
||||
|
||||
// ErrorWithUsage() returns the error with detailed location context.
|
||||
// ErrorWithPosition returns the error with detailed location context.
|
||||
//
|
||||
// See the documentation on [ParseError].
|
||||
func (pe ParseError) ErrorWithPosition() string {
|
||||
|
|
@ -124,7 +124,7 @@ func (pe ParseError) ErrorWithPosition() string {
|
|||
return b.String()
|
||||
}
|
||||
|
||||
// ErrorWithUsage() returns the error with detailed location context and usage
|
||||
// ErrorWithUsage returns the error with detailed location context and usage
|
||||
// guidance.
|
||||
//
|
||||
// See the documentation on [ParseError].
|
||||
|
|
|
|||
82
vendor/github.com/BurntSushi/toml/lex.go
generated
vendored
82
vendor/github.com/BurntSushi/toml/lex.go
generated
vendored
|
|
@ -46,12 +46,13 @@ func (p Position) String() string {
|
|||
}
|
||||
|
||||
type lexer struct {
|
||||
input string
|
||||
start int
|
||||
pos int
|
||||
line int
|
||||
state stateFn
|
||||
items chan item
|
||||
input string
|
||||
start int
|
||||
pos int
|
||||
line int
|
||||
state stateFn
|
||||
items chan item
|
||||
tomlNext bool
|
||||
|
||||
// Allow for backing up up to 4 runes. This is necessary because TOML
|
||||
// contains 3-rune tokens (""" and ''').
|
||||
|
|
@ -87,13 +88,14 @@ func (lx *lexer) nextItem() item {
|
|||
}
|
||||
}
|
||||
|
||||
func lex(input string) *lexer {
|
||||
func lex(input string, tomlNext bool) *lexer {
|
||||
lx := &lexer{
|
||||
input: input,
|
||||
state: lexTop,
|
||||
items: make(chan item, 10),
|
||||
stack: make([]stateFn, 0, 10),
|
||||
line: 1,
|
||||
input: input,
|
||||
state: lexTop,
|
||||
items: make(chan item, 10),
|
||||
stack: make([]stateFn, 0, 10),
|
||||
line: 1,
|
||||
tomlNext: tomlNext,
|
||||
}
|
||||
return lx
|
||||
}
|
||||
|
|
@ -408,7 +410,7 @@ func lexTableNameEnd(lx *lexer) stateFn {
|
|||
// Lexes only one part, e.g. only 'a' inside 'a.b'.
|
||||
func lexBareName(lx *lexer) stateFn {
|
||||
r := lx.next()
|
||||
if isBareKeyChar(r) {
|
||||
if isBareKeyChar(r, lx.tomlNext) {
|
||||
return lexBareName
|
||||
}
|
||||
lx.backup()
|
||||
|
|
@ -618,6 +620,9 @@ func lexInlineTableValue(lx *lexer) stateFn {
|
|||
case isWhitespace(r):
|
||||
return lexSkip(lx, lexInlineTableValue)
|
||||
case isNL(r):
|
||||
if lx.tomlNext {
|
||||
return lexSkip(lx, lexInlineTableValue)
|
||||
}
|
||||
return lx.errorPrevLine(errLexInlineTableNL{})
|
||||
case r == '#':
|
||||
lx.push(lexInlineTableValue)
|
||||
|
|
@ -640,6 +645,9 @@ func lexInlineTableValueEnd(lx *lexer) stateFn {
|
|||
case isWhitespace(r):
|
||||
return lexSkip(lx, lexInlineTableValueEnd)
|
||||
case isNL(r):
|
||||
if lx.tomlNext {
|
||||
return lexSkip(lx, lexInlineTableValueEnd)
|
||||
}
|
||||
return lx.errorPrevLine(errLexInlineTableNL{})
|
||||
case r == '#':
|
||||
lx.push(lexInlineTableValueEnd)
|
||||
|
|
@ -648,6 +656,9 @@ func lexInlineTableValueEnd(lx *lexer) stateFn {
|
|||
lx.ignore()
|
||||
lx.skip(isWhitespace)
|
||||
if lx.peek() == '}' {
|
||||
if lx.tomlNext {
|
||||
return lexInlineTableValueEnd
|
||||
}
|
||||
return lx.errorf("trailing comma not allowed in inline tables")
|
||||
}
|
||||
return lexInlineTableValue
|
||||
|
|
@ -770,8 +781,8 @@ func lexRawString(lx *lexer) stateFn {
|
|||
}
|
||||
}
|
||||
|
||||
// lexMultilineRawString consumes a raw string. Nothing can be escaped in such
|
||||
// a string. It assumes that the beginning ''' has already been consumed and
|
||||
// lexMultilineRawString consumes a raw string. Nothing can be escaped in such a
|
||||
// string. It assumes that the beginning triple-' has already been consumed and
|
||||
// ignored.
|
||||
func lexMultilineRawString(lx *lexer) stateFn {
|
||||
r := lx.next()
|
||||
|
|
@ -828,6 +839,11 @@ func lexMultilineStringEscape(lx *lexer) stateFn {
|
|||
func lexStringEscape(lx *lexer) stateFn {
|
||||
r := lx.next()
|
||||
switch r {
|
||||
case 'e':
|
||||
if !lx.tomlNext {
|
||||
return lx.error(errLexEscape{r})
|
||||
}
|
||||
fallthrough
|
||||
case 'b':
|
||||
fallthrough
|
||||
case 't':
|
||||
|
|
@ -846,6 +862,11 @@ func lexStringEscape(lx *lexer) stateFn {
|
|||
fallthrough
|
||||
case '\\':
|
||||
return lx.pop()
|
||||
case 'x':
|
||||
if !lx.tomlNext {
|
||||
return lx.error(errLexEscape{r})
|
||||
}
|
||||
return lexHexEscape
|
||||
case 'u':
|
||||
return lexShortUnicodeEscape
|
||||
case 'U':
|
||||
|
|
@ -854,6 +875,19 @@ func lexStringEscape(lx *lexer) stateFn {
|
|||
return lx.error(errLexEscape{r})
|
||||
}
|
||||
|
||||
func lexHexEscape(lx *lexer) stateFn {
|
||||
var r rune
|
||||
for i := 0; i < 2; i++ {
|
||||
r = lx.next()
|
||||
if !isHexadecimal(r) {
|
||||
return lx.errorf(
|
||||
`expected two hexadecimal digits after '\x', but got %q instead`,
|
||||
lx.current())
|
||||
}
|
||||
}
|
||||
return lx.pop()
|
||||
}
|
||||
|
||||
func lexShortUnicodeEscape(lx *lexer) stateFn {
|
||||
var r rune
|
||||
for i := 0; i < 4; i++ {
|
||||
|
|
@ -1225,7 +1259,23 @@ func isOctal(r rune) bool { return r >= '0' && r <= '7' }
|
|||
func isHexadecimal(r rune) bool {
|
||||
return (r >= '0' && r <= '9') || (r >= 'a' && r <= 'f') || (r >= 'A' && r <= 'F')
|
||||
}
|
||||
func isBareKeyChar(r rune) bool {
|
||||
|
||||
func isBareKeyChar(r rune, tomlNext bool) bool {
|
||||
if tomlNext {
|
||||
return (r >= 'A' && r <= 'Z') ||
|
||||
(r >= 'a' && r <= 'z') ||
|
||||
(r >= '0' && r <= '9') ||
|
||||
r == '_' || r == '-' ||
|
||||
r == 0xb2 || r == 0xb3 || r == 0xb9 || (r >= 0xbc && r <= 0xbe) ||
|
||||
(r >= 0xc0 && r <= 0xd6) || (r >= 0xd8 && r <= 0xf6) || (r >= 0xf8 && r <= 0x037d) ||
|
||||
(r >= 0x037f && r <= 0x1fff) ||
|
||||
(r >= 0x200c && r <= 0x200d) || (r >= 0x203f && r <= 0x2040) ||
|
||||
(r >= 0x2070 && r <= 0x218f) || (r >= 0x2460 && r <= 0x24ff) ||
|
||||
(r >= 0x2c00 && r <= 0x2fef) || (r >= 0x3001 && r <= 0xd7ff) ||
|
||||
(r >= 0xf900 && r <= 0xfdcf) || (r >= 0xfdf0 && r <= 0xfffd) ||
|
||||
(r >= 0x10000 && r <= 0xeffff)
|
||||
}
|
||||
|
||||
return (r >= 'A' && r <= 'Z') ||
|
||||
(r >= 'a' && r <= 'z') ||
|
||||
(r >= '0' && r <= '9') ||
|
||||
|
|
|
|||
2
vendor/github.com/BurntSushi/toml/meta.go
generated
vendored
2
vendor/github.com/BurntSushi/toml/meta.go
generated
vendored
|
|
@ -106,7 +106,7 @@ func (k Key) maybeQuoted(i int) string {
|
|||
return `""`
|
||||
}
|
||||
for _, c := range k[i] {
|
||||
if !isBareKeyChar(c) {
|
||||
if !isBareKeyChar(c, false) {
|
||||
return `"` + dblQuotedReplacer.Replace(k[i]) + `"`
|
||||
}
|
||||
}
|
||||
|
|
|
|||
138
vendor/github.com/BurntSushi/toml/parse.go
generated
vendored
138
vendor/github.com/BurntSushi/toml/parse.go
generated
vendored
|
|
@ -2,6 +2,7 @@ package toml
|
|||
|
||||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
"strconv"
|
||||
"strings"
|
||||
"time"
|
||||
|
|
@ -15,6 +16,7 @@ type parser struct {
|
|||
context Key // Full key for the current hash in scope.
|
||||
currentKey string // Base key name for everything except hashes.
|
||||
pos Position // Current position in the TOML file.
|
||||
tomlNext bool
|
||||
|
||||
ordered []Key // List of keys in the order that they appear in the TOML data.
|
||||
|
||||
|
|
@ -29,6 +31,8 @@ type keyInfo struct {
|
|||
}
|
||||
|
||||
func parse(data string) (p *parser, err error) {
|
||||
_, tomlNext := os.LookupEnv("BURNTSUSHI_TOML_110")
|
||||
|
||||
defer func() {
|
||||
if r := recover(); r != nil {
|
||||
if pErr, ok := r.(ParseError); ok {
|
||||
|
|
@ -41,9 +45,12 @@ func parse(data string) (p *parser, err error) {
|
|||
}()
|
||||
|
||||
// Read over BOM; do this here as the lexer calls utf8.DecodeRuneInString()
|
||||
// which mangles stuff.
|
||||
if strings.HasPrefix(data, "\xff\xfe") || strings.HasPrefix(data, "\xfe\xff") {
|
||||
// which mangles stuff. UTF-16 BOM isn't strictly valid, but some tools add
|
||||
// it anyway.
|
||||
if strings.HasPrefix(data, "\xff\xfe") || strings.HasPrefix(data, "\xfe\xff") { // UTF-16
|
||||
data = data[2:]
|
||||
} else if strings.HasPrefix(data, "\xef\xbb\xbf") { // UTF-8
|
||||
data = data[3:]
|
||||
}
|
||||
|
||||
// Examine first few bytes for NULL bytes; this probably means it's a UTF-16
|
||||
|
|
@ -65,9 +72,10 @@ func parse(data string) (p *parser, err error) {
|
|||
p = &parser{
|
||||
keyInfo: make(map[string]keyInfo),
|
||||
mapping: make(map[string]interface{}),
|
||||
lx: lex(data),
|
||||
lx: lex(data, tomlNext),
|
||||
ordered: make([]Key, 0),
|
||||
implicits: make(map[string]struct{}),
|
||||
tomlNext: tomlNext,
|
||||
}
|
||||
for {
|
||||
item := p.next()
|
||||
|
|
@ -194,12 +202,12 @@ func (p *parser) topLevel(item item) {
|
|||
for i := range context {
|
||||
p.addImplicitContext(append(p.context, context[i:i+1]...))
|
||||
}
|
||||
p.ordered = append(p.ordered, p.context.add(p.currentKey))
|
||||
|
||||
/// Set value.
|
||||
vItem := p.next()
|
||||
val, typ := p.value(vItem, false)
|
||||
p.set(p.currentKey, val, typ, vItem.pos)
|
||||
p.ordered = append(p.ordered, p.context.add(p.currentKey))
|
||||
|
||||
/// Remove the context we added (preserving any context from [tbl] lines).
|
||||
p.context = outerContext
|
||||
|
|
@ -236,7 +244,7 @@ func (p *parser) value(it item, parentIsArray bool) (interface{}, tomlType) {
|
|||
case itemString:
|
||||
return p.replaceEscapes(it, it.val), p.typeOfPrimitive(it)
|
||||
case itemMultilineString:
|
||||
return p.replaceEscapes(it, stripFirstNewline(p.stripEscapedNewlines(it.val))), p.typeOfPrimitive(it)
|
||||
return p.replaceEscapes(it, p.stripEscapedNewlines(stripFirstNewline(it.val))), p.typeOfPrimitive(it)
|
||||
case itemRawString:
|
||||
return it.val, p.typeOfPrimitive(it)
|
||||
case itemRawMultilineString:
|
||||
|
|
@ -331,11 +339,17 @@ func (p *parser) valueFloat(it item) (interface{}, tomlType) {
|
|||
var dtTypes = []struct {
|
||||
fmt string
|
||||
zone *time.Location
|
||||
next bool
|
||||
}{
|
||||
{time.RFC3339Nano, time.Local},
|
||||
{"2006-01-02T15:04:05.999999999", internal.LocalDatetime},
|
||||
{"2006-01-02", internal.LocalDate},
|
||||
{"15:04:05.999999999", internal.LocalTime},
|
||||
{time.RFC3339Nano, time.Local, false},
|
||||
{"2006-01-02T15:04:05.999999999", internal.LocalDatetime, false},
|
||||
{"2006-01-02", internal.LocalDate, false},
|
||||
{"15:04:05.999999999", internal.LocalTime, false},
|
||||
|
||||
// tomlNext
|
||||
{"2006-01-02T15:04Z07:00", time.Local, true},
|
||||
{"2006-01-02T15:04", internal.LocalDatetime, true},
|
||||
{"15:04", internal.LocalTime, true},
|
||||
}
|
||||
|
||||
func (p *parser) valueDatetime(it item) (interface{}, tomlType) {
|
||||
|
|
@ -346,6 +360,9 @@ func (p *parser) valueDatetime(it item) (interface{}, tomlType) {
|
|||
err error
|
||||
)
|
||||
for _, dt := range dtTypes {
|
||||
if dt.next && !p.tomlNext {
|
||||
continue
|
||||
}
|
||||
t, err = time.ParseInLocation(dt.fmt, it.val, dt.zone)
|
||||
if err == nil {
|
||||
ok = true
|
||||
|
|
@ -384,6 +401,7 @@ func (p *parser) valueArray(it item) (interface{}, tomlType) {
|
|||
//
|
||||
// Not entirely sure how to best store this; could use "key[0]",
|
||||
// "key[1]" notation, or maybe store it on the Array type?
|
||||
_ = types
|
||||
}
|
||||
return array, tomlArray
|
||||
}
|
||||
|
|
@ -426,11 +444,11 @@ func (p *parser) valueInlineTable(it item, parentIsArray bool) (interface{}, tom
|
|||
for i := range context {
|
||||
p.addImplicitContext(append(p.context, context[i:i+1]...))
|
||||
}
|
||||
p.ordered = append(p.ordered, p.context.add(p.currentKey))
|
||||
|
||||
/// Set the value.
|
||||
val, typ := p.value(p.next(), false)
|
||||
p.set(p.currentKey, val, typ, it.pos)
|
||||
p.ordered = append(p.ordered, p.context.add(p.currentKey))
|
||||
hash[p.currentKey] = val
|
||||
|
||||
/// Restore context.
|
||||
|
|
@ -551,7 +569,6 @@ func (p *parser) addContext(key Key, array bool) {
|
|||
func (p *parser) set(key string, val interface{}, typ tomlType, pos Position) {
|
||||
p.setValue(key, val)
|
||||
p.setType(key, typ, pos)
|
||||
|
||||
}
|
||||
|
||||
// setValue sets the given key to the given value in the current context.
|
||||
|
|
@ -632,14 +649,11 @@ func (p *parser) setType(key string, typ tomlType, pos Position) {
|
|||
|
||||
// Implicit keys need to be created when tables are implied in "a.b.c.d = 1" and
|
||||
// "[a.b.c]" (the "a", "b", and "c" hashes are never created explicitly).
|
||||
func (p *parser) addImplicit(key Key) { p.implicits[key.String()] = struct{}{} }
|
||||
func (p *parser) removeImplicit(key Key) { delete(p.implicits, key.String()) }
|
||||
func (p *parser) isImplicit(key Key) bool { _, ok := p.implicits[key.String()]; return ok }
|
||||
func (p *parser) isArray(key Key) bool { return p.keyInfo[key.String()].tomlType == tomlArray }
|
||||
func (p *parser) addImplicitContext(key Key) {
|
||||
p.addImplicit(key)
|
||||
p.addContext(key, false)
|
||||
}
|
||||
func (p *parser) addImplicit(key Key) { p.implicits[key.String()] = struct{}{} }
|
||||
func (p *parser) removeImplicit(key Key) { delete(p.implicits, key.String()) }
|
||||
func (p *parser) isImplicit(key Key) bool { _, ok := p.implicits[key.String()]; return ok }
|
||||
func (p *parser) isArray(key Key) bool { return p.keyInfo[key.String()].tomlType == tomlArray }
|
||||
func (p *parser) addImplicitContext(key Key) { p.addImplicit(key); p.addContext(key, false) }
|
||||
|
||||
// current returns the full key name of the current context.
|
||||
func (p *parser) current() string {
|
||||
|
|
@ -662,49 +676,54 @@ func stripFirstNewline(s string) string {
|
|||
return s
|
||||
}
|
||||
|
||||
// Remove newlines inside triple-quoted strings if a line ends with "\".
|
||||
// stripEscapedNewlines removes whitespace after line-ending backslashes in
|
||||
// multiline strings.
|
||||
//
|
||||
// A line-ending backslash is an unescaped \ followed only by whitespace until
|
||||
// the next newline. After a line-ending backslash, all whitespace is removed
|
||||
// until the next non-whitespace character.
|
||||
func (p *parser) stripEscapedNewlines(s string) string {
|
||||
split := strings.Split(s, "\n")
|
||||
if len(split) < 1 {
|
||||
return s
|
||||
}
|
||||
var b strings.Builder
|
||||
var i int
|
||||
for {
|
||||
ix := strings.Index(s[i:], `\`)
|
||||
if ix < 0 {
|
||||
b.WriteString(s)
|
||||
return b.String()
|
||||
}
|
||||
i += ix
|
||||
|
||||
escNL := false // Keep track of the last non-blank line was escaped.
|
||||
for i, line := range split {
|
||||
line = strings.TrimRight(line, " \t\r")
|
||||
|
||||
if len(line) == 0 || line[len(line)-1] != '\\' {
|
||||
split[i] = strings.TrimRight(split[i], "\r")
|
||||
if !escNL && i != len(split)-1 {
|
||||
split[i] += "\n"
|
||||
if len(s) > i+1 && s[i+1] == '\\' {
|
||||
// Escaped backslash.
|
||||
i += 2
|
||||
continue
|
||||
}
|
||||
// Scan until the next non-whitespace.
|
||||
j := i + 1
|
||||
whitespaceLoop:
|
||||
for ; j < len(s); j++ {
|
||||
switch s[j] {
|
||||
case ' ', '\t', '\r', '\n':
|
||||
default:
|
||||
break whitespaceLoop
|
||||
}
|
||||
}
|
||||
if j == i+1 {
|
||||
// Not a whitespace escape.
|
||||
i++
|
||||
continue
|
||||
}
|
||||
|
||||
escBS := true
|
||||
for j := len(line) - 1; j >= 0 && line[j] == '\\'; j-- {
|
||||
escBS = !escBS
|
||||
}
|
||||
if escNL {
|
||||
line = strings.TrimLeft(line, " \t\r")
|
||||
}
|
||||
escNL = !escBS
|
||||
|
||||
if escBS {
|
||||
split[i] += "\n"
|
||||
if !strings.Contains(s[i:j], "\n") {
|
||||
// This is not a line-ending backslash.
|
||||
// (It's a bad escape sequence, but we can let
|
||||
// replaceEscapes catch it.)
|
||||
i++
|
||||
continue
|
||||
}
|
||||
|
||||
if i == len(split)-1 {
|
||||
p.panicf("invalid escape: '\\ '")
|
||||
}
|
||||
|
||||
split[i] = line[:len(line)-1] // Remove \
|
||||
if len(split)-1 > i {
|
||||
split[i+1] = strings.TrimLeft(split[i+1], " \t\r")
|
||||
}
|
||||
b.WriteString(s[:i])
|
||||
s = s[j:]
|
||||
i = 0
|
||||
}
|
||||
return strings.Join(split, "")
|
||||
}
|
||||
|
||||
func (p *parser) replaceEscapes(it item, str string) string {
|
||||
|
|
@ -743,12 +762,23 @@ func (p *parser) replaceEscapes(it item, str string) string {
|
|||
case 'r':
|
||||
replaced = append(replaced, rune(0x000D))
|
||||
r += 1
|
||||
case 'e':
|
||||
if p.tomlNext {
|
||||
replaced = append(replaced, rune(0x001B))
|
||||
r += 1
|
||||
}
|
||||
case '"':
|
||||
replaced = append(replaced, rune(0x0022))
|
||||
r += 1
|
||||
case '\\':
|
||||
replaced = append(replaced, rune(0x005C))
|
||||
r += 1
|
||||
case 'x':
|
||||
if p.tomlNext {
|
||||
escaped := p.asciiEscapeToUnicode(it, s[r+1:r+3])
|
||||
replaced = append(replaced, escaped)
|
||||
r += 3
|
||||
}
|
||||
case 'u':
|
||||
// At this point, we know we have a Unicode escape of the form
|
||||
// `uXXXX` at [r, r+5). (Because the lexer guarantees this
|
||||
|
|
|
|||
1
vendor/github.com/Microsoft/go-winio/.gitignore
generated
vendored
1
vendor/github.com/Microsoft/go-winio/.gitignore
generated
vendored
|
|
@ -1 +0,0 @@
|
|||
*.exe
|
||||
1
vendor/github.com/Microsoft/go-winio/CODEOWNERS
generated
vendored
1
vendor/github.com/Microsoft/go-winio/CODEOWNERS
generated
vendored
|
|
@ -1 +0,0 @@
|
|||
* @microsoft/containerplat
|
||||
37
vendor/github.com/Microsoft/go-winio/README.md
generated
vendored
37
vendor/github.com/Microsoft/go-winio/README.md
generated
vendored
|
|
@ -1,37 +0,0 @@
|
|||
# go-winio [](https://github.com/microsoft/go-winio/actions/workflows/ci.yml)
|
||||
|
||||
This repository contains utilities for efficiently performing Win32 IO operations in
|
||||
Go. Currently, this is focused on accessing named pipes and other file handles, and
|
||||
for using named pipes as a net transport.
|
||||
|
||||
This code relies on IO completion ports to avoid blocking IO on system threads, allowing Go
|
||||
to reuse the thread to schedule another goroutine. This limits support to Windows Vista and
|
||||
newer operating systems. This is similar to the implementation of network sockets in Go's net
|
||||
package.
|
||||
|
||||
Please see the LICENSE file for licensing information.
|
||||
|
||||
## Contributing
|
||||
|
||||
This project welcomes contributions and suggestions. Most contributions require you to agree to a Contributor License Agreement (CLA)
|
||||
declaring that you have the right to, and actually do, grant us the rights to use your contribution. For details, visit https://cla.microsoft.com.
|
||||
|
||||
When you submit a pull request, a CLA-bot will automatically determine whether you need to provide a CLA and decorate the PR
|
||||
appropriately (e.g., label, comment). Simply follow the instructions provided by the bot. You will only need to do this once across all repos using our CLA.
|
||||
|
||||
We also require that contributors sign their commits using git commit -s or git commit --signoff to certify they either authored the work themselves
|
||||
or otherwise have permission to use it in this project. Please see https://developercertificate.org/ for more info, as well as to make sure that you can
|
||||
attest to the rules listed. Our CI uses the DCO Github app to ensure that all commits in a given PR are signed-off.
|
||||
|
||||
|
||||
## Code of Conduct
|
||||
|
||||
This project has adopted the [Microsoft Open Source Code of Conduct](https://opensource.microsoft.com/codeofconduct/).
|
||||
For more information see the [Code of Conduct FAQ](https://opensource.microsoft.com/codeofconduct/faq/) or
|
||||
contact [opencode@microsoft.com](mailto:opencode@microsoft.com) with any additional questions or comments.
|
||||
|
||||
|
||||
|
||||
## Special Thanks
|
||||
Thanks to natefinch for the inspiration for this library. See https://github.com/natefinch/npipe
|
||||
for another named pipe implementation.
|
||||
280
vendor/github.com/Microsoft/go-winio/backup.go
generated
vendored
280
vendor/github.com/Microsoft/go-winio/backup.go
generated
vendored
|
|
@ -1,280 +0,0 @@
|
|||
// +build windows
|
||||
|
||||
package winio
|
||||
|
||||
import (
|
||||
"encoding/binary"
|
||||
"errors"
|
||||
"fmt"
|
||||
"io"
|
||||
"io/ioutil"
|
||||
"os"
|
||||
"runtime"
|
||||
"syscall"
|
||||
"unicode/utf16"
|
||||
)
|
||||
|
||||
//sys backupRead(h syscall.Handle, b []byte, bytesRead *uint32, abort bool, processSecurity bool, context *uintptr) (err error) = BackupRead
|
||||
//sys backupWrite(h syscall.Handle, b []byte, bytesWritten *uint32, abort bool, processSecurity bool, context *uintptr) (err error) = BackupWrite
|
||||
|
||||
const (
|
||||
BackupData = uint32(iota + 1)
|
||||
BackupEaData
|
||||
BackupSecurity
|
||||
BackupAlternateData
|
||||
BackupLink
|
||||
BackupPropertyData
|
||||
BackupObjectId
|
||||
BackupReparseData
|
||||
BackupSparseBlock
|
||||
BackupTxfsData
|
||||
)
|
||||
|
||||
const (
|
||||
StreamSparseAttributes = uint32(8)
|
||||
)
|
||||
|
||||
const (
|
||||
WRITE_DAC = 0x40000
|
||||
WRITE_OWNER = 0x80000
|
||||
ACCESS_SYSTEM_SECURITY = 0x1000000
|
||||
)
|
||||
|
||||
// BackupHeader represents a backup stream of a file.
|
||||
type BackupHeader struct {
|
||||
Id uint32 // The backup stream ID
|
||||
Attributes uint32 // Stream attributes
|
||||
Size int64 // The size of the stream in bytes
|
||||
Name string // The name of the stream (for BackupAlternateData only).
|
||||
Offset int64 // The offset of the stream in the file (for BackupSparseBlock only).
|
||||
}
|
||||
|
||||
type win32StreamId struct {
|
||||
StreamId uint32
|
||||
Attributes uint32
|
||||
Size uint64
|
||||
NameSize uint32
|
||||
}
|
||||
|
||||
// BackupStreamReader reads from a stream produced by the BackupRead Win32 API and produces a series
|
||||
// of BackupHeader values.
|
||||
type BackupStreamReader struct {
|
||||
r io.Reader
|
||||
bytesLeft int64
|
||||
}
|
||||
|
||||
// NewBackupStreamReader produces a BackupStreamReader from any io.Reader.
|
||||
func NewBackupStreamReader(r io.Reader) *BackupStreamReader {
|
||||
return &BackupStreamReader{r, 0}
|
||||
}
|
||||
|
||||
// Next returns the next backup stream and prepares for calls to Read(). It skips the remainder of the current stream if
|
||||
// it was not completely read.
|
||||
func (r *BackupStreamReader) Next() (*BackupHeader, error) {
|
||||
if r.bytesLeft > 0 {
|
||||
if s, ok := r.r.(io.Seeker); ok {
|
||||
// Make sure Seek on io.SeekCurrent sometimes succeeds
|
||||
// before trying the actual seek.
|
||||
if _, err := s.Seek(0, io.SeekCurrent); err == nil {
|
||||
if _, err = s.Seek(r.bytesLeft, io.SeekCurrent); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
r.bytesLeft = 0
|
||||
}
|
||||
}
|
||||
if _, err := io.Copy(ioutil.Discard, r); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
var wsi win32StreamId
|
||||
if err := binary.Read(r.r, binary.LittleEndian, &wsi); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
hdr := &BackupHeader{
|
||||
Id: wsi.StreamId,
|
||||
Attributes: wsi.Attributes,
|
||||
Size: int64(wsi.Size),
|
||||
}
|
||||
if wsi.NameSize != 0 {
|
||||
name := make([]uint16, int(wsi.NameSize/2))
|
||||
if err := binary.Read(r.r, binary.LittleEndian, name); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
hdr.Name = syscall.UTF16ToString(name)
|
||||
}
|
||||
if wsi.StreamId == BackupSparseBlock {
|
||||
if err := binary.Read(r.r, binary.LittleEndian, &hdr.Offset); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
hdr.Size -= 8
|
||||
}
|
||||
r.bytesLeft = hdr.Size
|
||||
return hdr, nil
|
||||
}
|
||||
|
||||
// Read reads from the current backup stream.
|
||||
func (r *BackupStreamReader) Read(b []byte) (int, error) {
|
||||
if r.bytesLeft == 0 {
|
||||
return 0, io.EOF
|
||||
}
|
||||
if int64(len(b)) > r.bytesLeft {
|
||||
b = b[:r.bytesLeft]
|
||||
}
|
||||
n, err := r.r.Read(b)
|
||||
r.bytesLeft -= int64(n)
|
||||
if err == io.EOF {
|
||||
err = io.ErrUnexpectedEOF
|
||||
} else if r.bytesLeft == 0 && err == nil {
|
||||
err = io.EOF
|
||||
}
|
||||
return n, err
|
||||
}
|
||||
|
||||
// BackupStreamWriter writes a stream compatible with the BackupWrite Win32 API.
|
||||
type BackupStreamWriter struct {
|
||||
w io.Writer
|
||||
bytesLeft int64
|
||||
}
|
||||
|
||||
// NewBackupStreamWriter produces a BackupStreamWriter on top of an io.Writer.
|
||||
func NewBackupStreamWriter(w io.Writer) *BackupStreamWriter {
|
||||
return &BackupStreamWriter{w, 0}
|
||||
}
|
||||
|
||||
// WriteHeader writes the next backup stream header and prepares for calls to Write().
|
||||
func (w *BackupStreamWriter) WriteHeader(hdr *BackupHeader) error {
|
||||
if w.bytesLeft != 0 {
|
||||
return fmt.Errorf("missing %d bytes", w.bytesLeft)
|
||||
}
|
||||
name := utf16.Encode([]rune(hdr.Name))
|
||||
wsi := win32StreamId{
|
||||
StreamId: hdr.Id,
|
||||
Attributes: hdr.Attributes,
|
||||
Size: uint64(hdr.Size),
|
||||
NameSize: uint32(len(name) * 2),
|
||||
}
|
||||
if hdr.Id == BackupSparseBlock {
|
||||
// Include space for the int64 block offset
|
||||
wsi.Size += 8
|
||||
}
|
||||
if err := binary.Write(w.w, binary.LittleEndian, &wsi); err != nil {
|
||||
return err
|
||||
}
|
||||
if len(name) != 0 {
|
||||
if err := binary.Write(w.w, binary.LittleEndian, name); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
if hdr.Id == BackupSparseBlock {
|
||||
if err := binary.Write(w.w, binary.LittleEndian, hdr.Offset); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
w.bytesLeft = hdr.Size
|
||||
return nil
|
||||
}
|
||||
|
||||
// Write writes to the current backup stream.
|
||||
func (w *BackupStreamWriter) Write(b []byte) (int, error) {
|
||||
if w.bytesLeft < int64(len(b)) {
|
||||
return 0, fmt.Errorf("too many bytes by %d", int64(len(b))-w.bytesLeft)
|
||||
}
|
||||
n, err := w.w.Write(b)
|
||||
w.bytesLeft -= int64(n)
|
||||
return n, err
|
||||
}
|
||||
|
||||
// BackupFileReader provides an io.ReadCloser interface on top of the BackupRead Win32 API.
|
||||
type BackupFileReader struct {
|
||||
f *os.File
|
||||
includeSecurity bool
|
||||
ctx uintptr
|
||||
}
|
||||
|
||||
// NewBackupFileReader returns a new BackupFileReader from a file handle. If includeSecurity is true,
|
||||
// Read will attempt to read the security descriptor of the file.
|
||||
func NewBackupFileReader(f *os.File, includeSecurity bool) *BackupFileReader {
|
||||
r := &BackupFileReader{f, includeSecurity, 0}
|
||||
return r
|
||||
}
|
||||
|
||||
// Read reads a backup stream from the file by calling the Win32 API BackupRead().
|
||||
func (r *BackupFileReader) Read(b []byte) (int, error) {
|
||||
var bytesRead uint32
|
||||
err := backupRead(syscall.Handle(r.f.Fd()), b, &bytesRead, false, r.includeSecurity, &r.ctx)
|
||||
if err != nil {
|
||||
return 0, &os.PathError{"BackupRead", r.f.Name(), err}
|
||||
}
|
||||
runtime.KeepAlive(r.f)
|
||||
if bytesRead == 0 {
|
||||
return 0, io.EOF
|
||||
}
|
||||
return int(bytesRead), nil
|
||||
}
|
||||
|
||||
// Close frees Win32 resources associated with the BackupFileReader. It does not close
|
||||
// the underlying file.
|
||||
func (r *BackupFileReader) Close() error {
|
||||
if r.ctx != 0 {
|
||||
backupRead(syscall.Handle(r.f.Fd()), nil, nil, true, false, &r.ctx)
|
||||
runtime.KeepAlive(r.f)
|
||||
r.ctx = 0
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// BackupFileWriter provides an io.WriteCloser interface on top of the BackupWrite Win32 API.
|
||||
type BackupFileWriter struct {
|
||||
f *os.File
|
||||
includeSecurity bool
|
||||
ctx uintptr
|
||||
}
|
||||
|
||||
// NewBackupFileWriter returns a new BackupFileWriter from a file handle. If includeSecurity is true,
|
||||
// Write() will attempt to restore the security descriptor from the stream.
|
||||
func NewBackupFileWriter(f *os.File, includeSecurity bool) *BackupFileWriter {
|
||||
w := &BackupFileWriter{f, includeSecurity, 0}
|
||||
return w
|
||||
}
|
||||
|
||||
// Write restores a portion of the file using the provided backup stream.
|
||||
func (w *BackupFileWriter) Write(b []byte) (int, error) {
|
||||
var bytesWritten uint32
|
||||
err := backupWrite(syscall.Handle(w.f.Fd()), b, &bytesWritten, false, w.includeSecurity, &w.ctx)
|
||||
if err != nil {
|
||||
return 0, &os.PathError{"BackupWrite", w.f.Name(), err}
|
||||
}
|
||||
runtime.KeepAlive(w.f)
|
||||
if int(bytesWritten) != len(b) {
|
||||
return int(bytesWritten), errors.New("not all bytes could be written")
|
||||
}
|
||||
return len(b), nil
|
||||
}
|
||||
|
||||
// Close frees Win32 resources associated with the BackupFileWriter. It does not
|
||||
// close the underlying file.
|
||||
func (w *BackupFileWriter) Close() error {
|
||||
if w.ctx != 0 {
|
||||
backupWrite(syscall.Handle(w.f.Fd()), nil, nil, true, false, &w.ctx)
|
||||
runtime.KeepAlive(w.f)
|
||||
w.ctx = 0
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// OpenForBackup opens a file or directory, potentially skipping access checks if the backup
|
||||
// or restore privileges have been acquired.
|
||||
//
|
||||
// If the file opened was a directory, it cannot be used with Readdir().
|
||||
func OpenForBackup(path string, access uint32, share uint32, createmode uint32) (*os.File, error) {
|
||||
winPath, err := syscall.UTF16FromString(path)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
h, err := syscall.CreateFile(&winPath[0], access, share, nil, createmode, syscall.FILE_FLAG_BACKUP_SEMANTICS|syscall.FILE_FLAG_OPEN_REPARSE_POINT, 0)
|
||||
if err != nil {
|
||||
err = &os.PathError{Op: "open", Path: path, Err: err}
|
||||
return nil, err
|
||||
}
|
||||
return os.NewFile(uintptr(h), path), nil
|
||||
}
|
||||
137
vendor/github.com/Microsoft/go-winio/ea.go
generated
vendored
137
vendor/github.com/Microsoft/go-winio/ea.go
generated
vendored
|
|
@ -1,137 +0,0 @@
|
|||
package winio
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"encoding/binary"
|
||||
"errors"
|
||||
)
|
||||
|
||||
type fileFullEaInformation struct {
|
||||
NextEntryOffset uint32
|
||||
Flags uint8
|
||||
NameLength uint8
|
||||
ValueLength uint16
|
||||
}
|
||||
|
||||
var (
|
||||
fileFullEaInformationSize = binary.Size(&fileFullEaInformation{})
|
||||
|
||||
errInvalidEaBuffer = errors.New("invalid extended attribute buffer")
|
||||
errEaNameTooLarge = errors.New("extended attribute name too large")
|
||||
errEaValueTooLarge = errors.New("extended attribute value too large")
|
||||
)
|
||||
|
||||
// ExtendedAttribute represents a single Windows EA.
|
||||
type ExtendedAttribute struct {
|
||||
Name string
|
||||
Value []byte
|
||||
Flags uint8
|
||||
}
|
||||
|
||||
func parseEa(b []byte) (ea ExtendedAttribute, nb []byte, err error) {
|
||||
var info fileFullEaInformation
|
||||
err = binary.Read(bytes.NewReader(b), binary.LittleEndian, &info)
|
||||
if err != nil {
|
||||
err = errInvalidEaBuffer
|
||||
return
|
||||
}
|
||||
|
||||
nameOffset := fileFullEaInformationSize
|
||||
nameLen := int(info.NameLength)
|
||||
valueOffset := nameOffset + int(info.NameLength) + 1
|
||||
valueLen := int(info.ValueLength)
|
||||
nextOffset := int(info.NextEntryOffset)
|
||||
if valueLen+valueOffset > len(b) || nextOffset < 0 || nextOffset > len(b) {
|
||||
err = errInvalidEaBuffer
|
||||
return
|
||||
}
|
||||
|
||||
ea.Name = string(b[nameOffset : nameOffset+nameLen])
|
||||
ea.Value = b[valueOffset : valueOffset+valueLen]
|
||||
ea.Flags = info.Flags
|
||||
if info.NextEntryOffset != 0 {
|
||||
nb = b[info.NextEntryOffset:]
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// DecodeExtendedAttributes decodes a list of EAs from a FILE_FULL_EA_INFORMATION
|
||||
// buffer retrieved from BackupRead, ZwQueryEaFile, etc.
|
||||
func DecodeExtendedAttributes(b []byte) (eas []ExtendedAttribute, err error) {
|
||||
for len(b) != 0 {
|
||||
ea, nb, err := parseEa(b)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
eas = append(eas, ea)
|
||||
b = nb
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func writeEa(buf *bytes.Buffer, ea *ExtendedAttribute, last bool) error {
|
||||
if int(uint8(len(ea.Name))) != len(ea.Name) {
|
||||
return errEaNameTooLarge
|
||||
}
|
||||
if int(uint16(len(ea.Value))) != len(ea.Value) {
|
||||
return errEaValueTooLarge
|
||||
}
|
||||
entrySize := uint32(fileFullEaInformationSize + len(ea.Name) + 1 + len(ea.Value))
|
||||
withPadding := (entrySize + 3) &^ 3
|
||||
nextOffset := uint32(0)
|
||||
if !last {
|
||||
nextOffset = withPadding
|
||||
}
|
||||
info := fileFullEaInformation{
|
||||
NextEntryOffset: nextOffset,
|
||||
Flags: ea.Flags,
|
||||
NameLength: uint8(len(ea.Name)),
|
||||
ValueLength: uint16(len(ea.Value)),
|
||||
}
|
||||
|
||||
err := binary.Write(buf, binary.LittleEndian, &info)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
_, err = buf.Write([]byte(ea.Name))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
err = buf.WriteByte(0)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
_, err = buf.Write(ea.Value)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
_, err = buf.Write([]byte{0, 0, 0}[0 : withPadding-entrySize])
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// EncodeExtendedAttributes encodes a list of EAs into a FILE_FULL_EA_INFORMATION
|
||||
// buffer for use with BackupWrite, ZwSetEaFile, etc.
|
||||
func EncodeExtendedAttributes(eas []ExtendedAttribute) ([]byte, error) {
|
||||
var buf bytes.Buffer
|
||||
for i := range eas {
|
||||
last := false
|
||||
if i == len(eas)-1 {
|
||||
last = true
|
||||
}
|
||||
|
||||
err := writeEa(&buf, &eas[i], last)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
return buf.Bytes(), nil
|
||||
}
|
||||
329
vendor/github.com/Microsoft/go-winio/file.go
generated
vendored
329
vendor/github.com/Microsoft/go-winio/file.go
generated
vendored
|
|
@ -1,329 +0,0 @@
|
|||
//go:build windows
|
||||
// +build windows
|
||||
|
||||
package winio
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"io"
|
||||
"runtime"
|
||||
"sync"
|
||||
"sync/atomic"
|
||||
"syscall"
|
||||
"time"
|
||||
)
|
||||
|
||||
//sys cancelIoEx(file syscall.Handle, o *syscall.Overlapped) (err error) = CancelIoEx
|
||||
//sys createIoCompletionPort(file syscall.Handle, port syscall.Handle, key uintptr, threadCount uint32) (newport syscall.Handle, err error) = CreateIoCompletionPort
|
||||
//sys getQueuedCompletionStatus(port syscall.Handle, bytes *uint32, key *uintptr, o **ioOperation, timeout uint32) (err error) = GetQueuedCompletionStatus
|
||||
//sys setFileCompletionNotificationModes(h syscall.Handle, flags uint8) (err error) = SetFileCompletionNotificationModes
|
||||
//sys wsaGetOverlappedResult(h syscall.Handle, o *syscall.Overlapped, bytes *uint32, wait bool, flags *uint32) (err error) = ws2_32.WSAGetOverlappedResult
|
||||
|
||||
type atomicBool int32
|
||||
|
||||
func (b *atomicBool) isSet() bool { return atomic.LoadInt32((*int32)(b)) != 0 }
|
||||
func (b *atomicBool) setFalse() { atomic.StoreInt32((*int32)(b), 0) }
|
||||
func (b *atomicBool) setTrue() { atomic.StoreInt32((*int32)(b), 1) }
|
||||
func (b *atomicBool) swap(new bool) bool {
|
||||
var newInt int32
|
||||
if new {
|
||||
newInt = 1
|
||||
}
|
||||
return atomic.SwapInt32((*int32)(b), newInt) == 1
|
||||
}
|
||||
|
||||
const (
|
||||
cFILE_SKIP_COMPLETION_PORT_ON_SUCCESS = 1
|
||||
cFILE_SKIP_SET_EVENT_ON_HANDLE = 2
|
||||
)
|
||||
|
||||
var (
|
||||
ErrFileClosed = errors.New("file has already been closed")
|
||||
ErrTimeout = &timeoutError{}
|
||||
)
|
||||
|
||||
type timeoutError struct{}
|
||||
|
||||
func (e *timeoutError) Error() string { return "i/o timeout" }
|
||||
func (e *timeoutError) Timeout() bool { return true }
|
||||
func (e *timeoutError) Temporary() bool { return true }
|
||||
|
||||
type timeoutChan chan struct{}
|
||||
|
||||
var ioInitOnce sync.Once
|
||||
var ioCompletionPort syscall.Handle
|
||||
|
||||
// ioResult contains the result of an asynchronous IO operation
|
||||
type ioResult struct {
|
||||
bytes uint32
|
||||
err error
|
||||
}
|
||||
|
||||
// ioOperation represents an outstanding asynchronous Win32 IO
|
||||
type ioOperation struct {
|
||||
o syscall.Overlapped
|
||||
ch chan ioResult
|
||||
}
|
||||
|
||||
func initIo() {
|
||||
h, err := createIoCompletionPort(syscall.InvalidHandle, 0, 0, 0xffffffff)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
ioCompletionPort = h
|
||||
go ioCompletionProcessor(h)
|
||||
}
|
||||
|
||||
// win32File implements Reader, Writer, and Closer on a Win32 handle without blocking in a syscall.
|
||||
// It takes ownership of this handle and will close it if it is garbage collected.
|
||||
type win32File struct {
|
||||
handle syscall.Handle
|
||||
wg sync.WaitGroup
|
||||
wgLock sync.RWMutex
|
||||
closing atomicBool
|
||||
socket bool
|
||||
readDeadline deadlineHandler
|
||||
writeDeadline deadlineHandler
|
||||
}
|
||||
|
||||
type deadlineHandler struct {
|
||||
setLock sync.Mutex
|
||||
channel timeoutChan
|
||||
channelLock sync.RWMutex
|
||||
timer *time.Timer
|
||||
timedout atomicBool
|
||||
}
|
||||
|
||||
// makeWin32File makes a new win32File from an existing file handle
|
||||
func makeWin32File(h syscall.Handle) (*win32File, error) {
|
||||
f := &win32File{handle: h}
|
||||
ioInitOnce.Do(initIo)
|
||||
_, err := createIoCompletionPort(h, ioCompletionPort, 0, 0xffffffff)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
err = setFileCompletionNotificationModes(h, cFILE_SKIP_COMPLETION_PORT_ON_SUCCESS|cFILE_SKIP_SET_EVENT_ON_HANDLE)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
f.readDeadline.channel = make(timeoutChan)
|
||||
f.writeDeadline.channel = make(timeoutChan)
|
||||
return f, nil
|
||||
}
|
||||
|
||||
func MakeOpenFile(h syscall.Handle) (io.ReadWriteCloser, error) {
|
||||
// If we return the result of makeWin32File directly, it can result in an
|
||||
// interface-wrapped nil, rather than a nil interface value.
|
||||
f, err := makeWin32File(h)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return f, nil
|
||||
}
|
||||
|
||||
// closeHandle closes the resources associated with a Win32 handle
|
||||
func (f *win32File) closeHandle() {
|
||||
f.wgLock.Lock()
|
||||
// Atomically set that we are closing, releasing the resources only once.
|
||||
if !f.closing.swap(true) {
|
||||
f.wgLock.Unlock()
|
||||
// cancel all IO and wait for it to complete
|
||||
cancelIoEx(f.handle, nil)
|
||||
f.wg.Wait()
|
||||
// at this point, no new IO can start
|
||||
syscall.Close(f.handle)
|
||||
f.handle = 0
|
||||
} else {
|
||||
f.wgLock.Unlock()
|
||||
}
|
||||
}
|
||||
|
||||
// Close closes a win32File.
|
||||
func (f *win32File) Close() error {
|
||||
f.closeHandle()
|
||||
return nil
|
||||
}
|
||||
|
||||
// IsClosed checks if the file has been closed
|
||||
func (f *win32File) IsClosed() bool {
|
||||
return f.closing.isSet()
|
||||
}
|
||||
|
||||
// prepareIo prepares for a new IO operation.
|
||||
// The caller must call f.wg.Done() when the IO is finished, prior to Close() returning.
|
||||
func (f *win32File) prepareIo() (*ioOperation, error) {
|
||||
f.wgLock.RLock()
|
||||
if f.closing.isSet() {
|
||||
f.wgLock.RUnlock()
|
||||
return nil, ErrFileClosed
|
||||
}
|
||||
f.wg.Add(1)
|
||||
f.wgLock.RUnlock()
|
||||
c := &ioOperation{}
|
||||
c.ch = make(chan ioResult)
|
||||
return c, nil
|
||||
}
|
||||
|
||||
// ioCompletionProcessor processes completed async IOs forever
|
||||
func ioCompletionProcessor(h syscall.Handle) {
|
||||
for {
|
||||
var bytes uint32
|
||||
var key uintptr
|
||||
var op *ioOperation
|
||||
err := getQueuedCompletionStatus(h, &bytes, &key, &op, syscall.INFINITE)
|
||||
if op == nil {
|
||||
panic(err)
|
||||
}
|
||||
op.ch <- ioResult{bytes, err}
|
||||
}
|
||||
}
|
||||
|
||||
// asyncIo processes the return value from ReadFile or WriteFile, blocking until
|
||||
// the operation has actually completed.
|
||||
func (f *win32File) asyncIo(c *ioOperation, d *deadlineHandler, bytes uint32, err error) (int, error) {
|
||||
if err != syscall.ERROR_IO_PENDING {
|
||||
return int(bytes), err
|
||||
}
|
||||
|
||||
if f.closing.isSet() {
|
||||
cancelIoEx(f.handle, &c.o)
|
||||
}
|
||||
|
||||
var timeout timeoutChan
|
||||
if d != nil {
|
||||
d.channelLock.Lock()
|
||||
timeout = d.channel
|
||||
d.channelLock.Unlock()
|
||||
}
|
||||
|
||||
var r ioResult
|
||||
select {
|
||||
case r = <-c.ch:
|
||||
err = r.err
|
||||
if err == syscall.ERROR_OPERATION_ABORTED {
|
||||
if f.closing.isSet() {
|
||||
err = ErrFileClosed
|
||||
}
|
||||
} else if err != nil && f.socket {
|
||||
// err is from Win32. Query the overlapped structure to get the winsock error.
|
||||
var bytes, flags uint32
|
||||
err = wsaGetOverlappedResult(f.handle, &c.o, &bytes, false, &flags)
|
||||
}
|
||||
case <-timeout:
|
||||
cancelIoEx(f.handle, &c.o)
|
||||
r = <-c.ch
|
||||
err = r.err
|
||||
if err == syscall.ERROR_OPERATION_ABORTED {
|
||||
err = ErrTimeout
|
||||
}
|
||||
}
|
||||
|
||||
// runtime.KeepAlive is needed, as c is passed via native
|
||||
// code to ioCompletionProcessor, c must remain alive
|
||||
// until the channel read is complete.
|
||||
runtime.KeepAlive(c)
|
||||
return int(r.bytes), err
|
||||
}
|
||||
|
||||
// Read reads from a file handle.
|
||||
func (f *win32File) Read(b []byte) (int, error) {
|
||||
c, err := f.prepareIo()
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
defer f.wg.Done()
|
||||
|
||||
if f.readDeadline.timedout.isSet() {
|
||||
return 0, ErrTimeout
|
||||
}
|
||||
|
||||
var bytes uint32
|
||||
err = syscall.ReadFile(f.handle, b, &bytes, &c.o)
|
||||
n, err := f.asyncIo(c, &f.readDeadline, bytes, err)
|
||||
runtime.KeepAlive(b)
|
||||
|
||||
// Handle EOF conditions.
|
||||
if err == nil && n == 0 && len(b) != 0 {
|
||||
return 0, io.EOF
|
||||
} else if err == syscall.ERROR_BROKEN_PIPE {
|
||||
return 0, io.EOF
|
||||
} else {
|
||||
return n, err
|
||||
}
|
||||
}
|
||||
|
||||
// Write writes to a file handle.
|
||||
func (f *win32File) Write(b []byte) (int, error) {
|
||||
c, err := f.prepareIo()
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
defer f.wg.Done()
|
||||
|
||||
if f.writeDeadline.timedout.isSet() {
|
||||
return 0, ErrTimeout
|
||||
}
|
||||
|
||||
var bytes uint32
|
||||
err = syscall.WriteFile(f.handle, b, &bytes, &c.o)
|
||||
n, err := f.asyncIo(c, &f.writeDeadline, bytes, err)
|
||||
runtime.KeepAlive(b)
|
||||
return n, err
|
||||
}
|
||||
|
||||
func (f *win32File) SetReadDeadline(deadline time.Time) error {
|
||||
return f.readDeadline.set(deadline)
|
||||
}
|
||||
|
||||
func (f *win32File) SetWriteDeadline(deadline time.Time) error {
|
||||
return f.writeDeadline.set(deadline)
|
||||
}
|
||||
|
||||
func (f *win32File) Flush() error {
|
||||
return syscall.FlushFileBuffers(f.handle)
|
||||
}
|
||||
|
||||
func (f *win32File) Fd() uintptr {
|
||||
return uintptr(f.handle)
|
||||
}
|
||||
|
||||
func (d *deadlineHandler) set(deadline time.Time) error {
|
||||
d.setLock.Lock()
|
||||
defer d.setLock.Unlock()
|
||||
|
||||
if d.timer != nil {
|
||||
if !d.timer.Stop() {
|
||||
<-d.channel
|
||||
}
|
||||
d.timer = nil
|
||||
}
|
||||
d.timedout.setFalse()
|
||||
|
||||
select {
|
||||
case <-d.channel:
|
||||
d.channelLock.Lock()
|
||||
d.channel = make(chan struct{})
|
||||
d.channelLock.Unlock()
|
||||
default:
|
||||
}
|
||||
|
||||
if deadline.IsZero() {
|
||||
return nil
|
||||
}
|
||||
|
||||
timeoutIO := func() {
|
||||
d.timedout.setTrue()
|
||||
close(d.channel)
|
||||
}
|
||||
|
||||
now := time.Now()
|
||||
duration := deadline.Sub(now)
|
||||
if deadline.After(now) {
|
||||
// Deadline is in the future, set a timer to wait
|
||||
d.timer = time.AfterFunc(duration, timeoutIO)
|
||||
} else {
|
||||
// Deadline is in the past. Cancel all pending IO now.
|
||||
timeoutIO()
|
||||
}
|
||||
return nil
|
||||
}
|
||||
73
vendor/github.com/Microsoft/go-winio/fileinfo.go
generated
vendored
73
vendor/github.com/Microsoft/go-winio/fileinfo.go
generated
vendored
|
|
@ -1,73 +0,0 @@
|
|||
// +build windows
|
||||
|
||||
package winio
|
||||
|
||||
import (
|
||||
"os"
|
||||
"runtime"
|
||||
"unsafe"
|
||||
|
||||
"golang.org/x/sys/windows"
|
||||
)
|
||||
|
||||
// FileBasicInfo contains file access time and file attributes information.
|
||||
type FileBasicInfo struct {
|
||||
CreationTime, LastAccessTime, LastWriteTime, ChangeTime windows.Filetime
|
||||
FileAttributes uint32
|
||||
pad uint32 // padding
|
||||
}
|
||||
|
||||
// GetFileBasicInfo retrieves times and attributes for a file.
|
||||
func GetFileBasicInfo(f *os.File) (*FileBasicInfo, error) {
|
||||
bi := &FileBasicInfo{}
|
||||
if err := windows.GetFileInformationByHandleEx(windows.Handle(f.Fd()), windows.FileBasicInfo, (*byte)(unsafe.Pointer(bi)), uint32(unsafe.Sizeof(*bi))); err != nil {
|
||||
return nil, &os.PathError{Op: "GetFileInformationByHandleEx", Path: f.Name(), Err: err}
|
||||
}
|
||||
runtime.KeepAlive(f)
|
||||
return bi, nil
|
||||
}
|
||||
|
||||
// SetFileBasicInfo sets times and attributes for a file.
|
||||
func SetFileBasicInfo(f *os.File, bi *FileBasicInfo) error {
|
||||
if err := windows.SetFileInformationByHandle(windows.Handle(f.Fd()), windows.FileBasicInfo, (*byte)(unsafe.Pointer(bi)), uint32(unsafe.Sizeof(*bi))); err != nil {
|
||||
return &os.PathError{Op: "SetFileInformationByHandle", Path: f.Name(), Err: err}
|
||||
}
|
||||
runtime.KeepAlive(f)
|
||||
return nil
|
||||
}
|
||||
|
||||
// FileStandardInfo contains extended information for the file.
|
||||
// FILE_STANDARD_INFO in WinBase.h
|
||||
// https://docs.microsoft.com/en-us/windows/win32/api/winbase/ns-winbase-file_standard_info
|
||||
type FileStandardInfo struct {
|
||||
AllocationSize, EndOfFile int64
|
||||
NumberOfLinks uint32
|
||||
DeletePending, Directory bool
|
||||
}
|
||||
|
||||
// GetFileStandardInfo retrieves ended information for the file.
|
||||
func GetFileStandardInfo(f *os.File) (*FileStandardInfo, error) {
|
||||
si := &FileStandardInfo{}
|
||||
if err := windows.GetFileInformationByHandleEx(windows.Handle(f.Fd()), windows.FileStandardInfo, (*byte)(unsafe.Pointer(si)), uint32(unsafe.Sizeof(*si))); err != nil {
|
||||
return nil, &os.PathError{Op: "GetFileInformationByHandleEx", Path: f.Name(), Err: err}
|
||||
}
|
||||
runtime.KeepAlive(f)
|
||||
return si, nil
|
||||
}
|
||||
|
||||
// FileIDInfo contains the volume serial number and file ID for a file. This pair should be
|
||||
// unique on a system.
|
||||
type FileIDInfo struct {
|
||||
VolumeSerialNumber uint64
|
||||
FileID [16]byte
|
||||
}
|
||||
|
||||
// GetFileID retrieves the unique (volume, file ID) pair for a file.
|
||||
func GetFileID(f *os.File) (*FileIDInfo, error) {
|
||||
fileID := &FileIDInfo{}
|
||||
if err := windows.GetFileInformationByHandleEx(windows.Handle(f.Fd()), windows.FileIdInfo, (*byte)(unsafe.Pointer(fileID)), uint32(unsafe.Sizeof(*fileID))); err != nil {
|
||||
return nil, &os.PathError{Op: "GetFileInformationByHandleEx", Path: f.Name(), Err: err}
|
||||
}
|
||||
runtime.KeepAlive(f)
|
||||
return fileID, nil
|
||||
}
|
||||
316
vendor/github.com/Microsoft/go-winio/hvsock.go
generated
vendored
316
vendor/github.com/Microsoft/go-winio/hvsock.go
generated
vendored
|
|
@ -1,316 +0,0 @@
|
|||
//go:build windows
|
||||
// +build windows
|
||||
|
||||
package winio
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"io"
|
||||
"net"
|
||||
"os"
|
||||
"syscall"
|
||||
"time"
|
||||
"unsafe"
|
||||
|
||||
"github.com/Microsoft/go-winio/pkg/guid"
|
||||
)
|
||||
|
||||
//sys bind(s syscall.Handle, name unsafe.Pointer, namelen int32) (err error) [failretval==socketError] = ws2_32.bind
|
||||
|
||||
const (
|
||||
afHvSock = 34 // AF_HYPERV
|
||||
|
||||
socketError = ^uintptr(0)
|
||||
)
|
||||
|
||||
// An HvsockAddr is an address for a AF_HYPERV socket.
|
||||
type HvsockAddr struct {
|
||||
VMID guid.GUID
|
||||
ServiceID guid.GUID
|
||||
}
|
||||
|
||||
type rawHvsockAddr struct {
|
||||
Family uint16
|
||||
_ uint16
|
||||
VMID guid.GUID
|
||||
ServiceID guid.GUID
|
||||
}
|
||||
|
||||
// Network returns the address's network name, "hvsock".
|
||||
func (addr *HvsockAddr) Network() string {
|
||||
return "hvsock"
|
||||
}
|
||||
|
||||
func (addr *HvsockAddr) String() string {
|
||||
return fmt.Sprintf("%s:%s", &addr.VMID, &addr.ServiceID)
|
||||
}
|
||||
|
||||
// VsockServiceID returns an hvsock service ID corresponding to the specified AF_VSOCK port.
|
||||
func VsockServiceID(port uint32) guid.GUID {
|
||||
g, _ := guid.FromString("00000000-facb-11e6-bd58-64006a7986d3")
|
||||
g.Data1 = port
|
||||
return g
|
||||
}
|
||||
|
||||
func (addr *HvsockAddr) raw() rawHvsockAddr {
|
||||
return rawHvsockAddr{
|
||||
Family: afHvSock,
|
||||
VMID: addr.VMID,
|
||||
ServiceID: addr.ServiceID,
|
||||
}
|
||||
}
|
||||
|
||||
func (addr *HvsockAddr) fromRaw(raw *rawHvsockAddr) {
|
||||
addr.VMID = raw.VMID
|
||||
addr.ServiceID = raw.ServiceID
|
||||
}
|
||||
|
||||
// HvsockListener is a socket listener for the AF_HYPERV address family.
|
||||
type HvsockListener struct {
|
||||
sock *win32File
|
||||
addr HvsockAddr
|
||||
}
|
||||
|
||||
// HvsockConn is a connected socket of the AF_HYPERV address family.
|
||||
type HvsockConn struct {
|
||||
sock *win32File
|
||||
local, remote HvsockAddr
|
||||
}
|
||||
|
||||
func newHvSocket() (*win32File, error) {
|
||||
fd, err := syscall.Socket(afHvSock, syscall.SOCK_STREAM, 1)
|
||||
if err != nil {
|
||||
return nil, os.NewSyscallError("socket", err)
|
||||
}
|
||||
f, err := makeWin32File(fd)
|
||||
if err != nil {
|
||||
syscall.Close(fd)
|
||||
return nil, err
|
||||
}
|
||||
f.socket = true
|
||||
return f, nil
|
||||
}
|
||||
|
||||
// ListenHvsock listens for connections on the specified hvsock address.
|
||||
func ListenHvsock(addr *HvsockAddr) (_ *HvsockListener, err error) {
|
||||
l := &HvsockListener{addr: *addr}
|
||||
sock, err := newHvSocket()
|
||||
if err != nil {
|
||||
return nil, l.opErr("listen", err)
|
||||
}
|
||||
sa := addr.raw()
|
||||
err = bind(sock.handle, unsafe.Pointer(&sa), int32(unsafe.Sizeof(sa)))
|
||||
if err != nil {
|
||||
return nil, l.opErr("listen", os.NewSyscallError("socket", err))
|
||||
}
|
||||
err = syscall.Listen(sock.handle, 16)
|
||||
if err != nil {
|
||||
return nil, l.opErr("listen", os.NewSyscallError("listen", err))
|
||||
}
|
||||
return &HvsockListener{sock: sock, addr: *addr}, nil
|
||||
}
|
||||
|
||||
func (l *HvsockListener) opErr(op string, err error) error {
|
||||
return &net.OpError{Op: op, Net: "hvsock", Addr: &l.addr, Err: err}
|
||||
}
|
||||
|
||||
// Addr returns the listener's network address.
|
||||
func (l *HvsockListener) Addr() net.Addr {
|
||||
return &l.addr
|
||||
}
|
||||
|
||||
// Accept waits for the next connection and returns it.
|
||||
func (l *HvsockListener) Accept() (_ net.Conn, err error) {
|
||||
sock, err := newHvSocket()
|
||||
if err != nil {
|
||||
return nil, l.opErr("accept", err)
|
||||
}
|
||||
defer func() {
|
||||
if sock != nil {
|
||||
sock.Close()
|
||||
}
|
||||
}()
|
||||
c, err := l.sock.prepareIo()
|
||||
if err != nil {
|
||||
return nil, l.opErr("accept", err)
|
||||
}
|
||||
defer l.sock.wg.Done()
|
||||
|
||||
// AcceptEx, per documentation, requires an extra 16 bytes per address.
|
||||
const addrlen = uint32(16 + unsafe.Sizeof(rawHvsockAddr{}))
|
||||
var addrbuf [addrlen * 2]byte
|
||||
|
||||
var bytes uint32
|
||||
err = syscall.AcceptEx(l.sock.handle, sock.handle, &addrbuf[0], 0, addrlen, addrlen, &bytes, &c.o)
|
||||
_, err = l.sock.asyncIo(c, nil, bytes, err)
|
||||
if err != nil {
|
||||
return nil, l.opErr("accept", os.NewSyscallError("acceptex", err))
|
||||
}
|
||||
conn := &HvsockConn{
|
||||
sock: sock,
|
||||
}
|
||||
conn.local.fromRaw((*rawHvsockAddr)(unsafe.Pointer(&addrbuf[0])))
|
||||
conn.remote.fromRaw((*rawHvsockAddr)(unsafe.Pointer(&addrbuf[addrlen])))
|
||||
sock = nil
|
||||
return conn, nil
|
||||
}
|
||||
|
||||
// Close closes the listener, causing any pending Accept calls to fail.
|
||||
func (l *HvsockListener) Close() error {
|
||||
return l.sock.Close()
|
||||
}
|
||||
|
||||
/* Need to finish ConnectEx handling
|
||||
func DialHvsock(ctx context.Context, addr *HvsockAddr) (*HvsockConn, error) {
|
||||
sock, err := newHvSocket()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer func() {
|
||||
if sock != nil {
|
||||
sock.Close()
|
||||
}
|
||||
}()
|
||||
c, err := sock.prepareIo()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer sock.wg.Done()
|
||||
var bytes uint32
|
||||
err = windows.ConnectEx(windows.Handle(sock.handle), sa, nil, 0, &bytes, &c.o)
|
||||
_, err = sock.asyncIo(ctx, c, nil, bytes, err)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
conn := &HvsockConn{
|
||||
sock: sock,
|
||||
remote: *addr,
|
||||
}
|
||||
sock = nil
|
||||
return conn, nil
|
||||
}
|
||||
*/
|
||||
|
||||
func (conn *HvsockConn) opErr(op string, err error) error {
|
||||
return &net.OpError{Op: op, Net: "hvsock", Source: &conn.local, Addr: &conn.remote, Err: err}
|
||||
}
|
||||
|
||||
func (conn *HvsockConn) Read(b []byte) (int, error) {
|
||||
c, err := conn.sock.prepareIo()
|
||||
if err != nil {
|
||||
return 0, conn.opErr("read", err)
|
||||
}
|
||||
defer conn.sock.wg.Done()
|
||||
buf := syscall.WSABuf{Buf: &b[0], Len: uint32(len(b))}
|
||||
var flags, bytes uint32
|
||||
err = syscall.WSARecv(conn.sock.handle, &buf, 1, &bytes, &flags, &c.o, nil)
|
||||
n, err := conn.sock.asyncIo(c, &conn.sock.readDeadline, bytes, err)
|
||||
if err != nil {
|
||||
if _, ok := err.(syscall.Errno); ok {
|
||||
err = os.NewSyscallError("wsarecv", err)
|
||||
}
|
||||
return 0, conn.opErr("read", err)
|
||||
} else if n == 0 {
|
||||
err = io.EOF
|
||||
}
|
||||
return n, err
|
||||
}
|
||||
|
||||
func (conn *HvsockConn) Write(b []byte) (int, error) {
|
||||
t := 0
|
||||
for len(b) != 0 {
|
||||
n, err := conn.write(b)
|
||||
if err != nil {
|
||||
return t + n, err
|
||||
}
|
||||
t += n
|
||||
b = b[n:]
|
||||
}
|
||||
return t, nil
|
||||
}
|
||||
|
||||
func (conn *HvsockConn) write(b []byte) (int, error) {
|
||||
c, err := conn.sock.prepareIo()
|
||||
if err != nil {
|
||||
return 0, conn.opErr("write", err)
|
||||
}
|
||||
defer conn.sock.wg.Done()
|
||||
buf := syscall.WSABuf{Buf: &b[0], Len: uint32(len(b))}
|
||||
var bytes uint32
|
||||
err = syscall.WSASend(conn.sock.handle, &buf, 1, &bytes, 0, &c.o, nil)
|
||||
n, err := conn.sock.asyncIo(c, &conn.sock.writeDeadline, bytes, err)
|
||||
if err != nil {
|
||||
if _, ok := err.(syscall.Errno); ok {
|
||||
err = os.NewSyscallError("wsasend", err)
|
||||
}
|
||||
return 0, conn.opErr("write", err)
|
||||
}
|
||||
return n, err
|
||||
}
|
||||
|
||||
// Close closes the socket connection, failing any pending read or write calls.
|
||||
func (conn *HvsockConn) Close() error {
|
||||
return conn.sock.Close()
|
||||
}
|
||||
|
||||
func (conn *HvsockConn) IsClosed() bool {
|
||||
return conn.sock.IsClosed()
|
||||
}
|
||||
|
||||
func (conn *HvsockConn) shutdown(how int) error {
|
||||
if conn.IsClosed() {
|
||||
return ErrFileClosed
|
||||
}
|
||||
|
||||
err := syscall.Shutdown(conn.sock.handle, how)
|
||||
if err != nil {
|
||||
return os.NewSyscallError("shutdown", err)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// CloseRead shuts down the read end of the socket, preventing future read operations.
|
||||
func (conn *HvsockConn) CloseRead() error {
|
||||
err := conn.shutdown(syscall.SHUT_RD)
|
||||
if err != nil {
|
||||
return conn.opErr("close", err)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// CloseWrite shuts down the write end of the socket, preventing future write operations and
|
||||
// notifying the other endpoint that no more data will be written.
|
||||
func (conn *HvsockConn) CloseWrite() error {
|
||||
err := conn.shutdown(syscall.SHUT_WR)
|
||||
if err != nil {
|
||||
return conn.opErr("close", err)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// LocalAddr returns the local address of the connection.
|
||||
func (conn *HvsockConn) LocalAddr() net.Addr {
|
||||
return &conn.local
|
||||
}
|
||||
|
||||
// RemoteAddr returns the remote address of the connection.
|
||||
func (conn *HvsockConn) RemoteAddr() net.Addr {
|
||||
return &conn.remote
|
||||
}
|
||||
|
||||
// SetDeadline implements the net.Conn SetDeadline method.
|
||||
func (conn *HvsockConn) SetDeadline(t time.Time) error {
|
||||
conn.SetReadDeadline(t)
|
||||
conn.SetWriteDeadline(t)
|
||||
return nil
|
||||
}
|
||||
|
||||
// SetReadDeadline implements the net.Conn SetReadDeadline method.
|
||||
func (conn *HvsockConn) SetReadDeadline(t time.Time) error {
|
||||
return conn.sock.SetReadDeadline(t)
|
||||
}
|
||||
|
||||
// SetWriteDeadline implements the net.Conn SetWriteDeadline method.
|
||||
func (conn *HvsockConn) SetWriteDeadline(t time.Time) error {
|
||||
return conn.sock.SetWriteDeadline(t)
|
||||
}
|
||||
517
vendor/github.com/Microsoft/go-winio/pipe.go
generated
vendored
517
vendor/github.com/Microsoft/go-winio/pipe.go
generated
vendored
|
|
@ -1,517 +0,0 @@
|
|||
// +build windows
|
||||
|
||||
package winio
|
||||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"fmt"
|
||||
"io"
|
||||
"net"
|
||||
"os"
|
||||
"runtime"
|
||||
"syscall"
|
||||
"time"
|
||||
"unsafe"
|
||||
)
|
||||
|
||||
//sys connectNamedPipe(pipe syscall.Handle, o *syscall.Overlapped) (err error) = ConnectNamedPipe
|
||||
//sys createNamedPipe(name string, flags uint32, pipeMode uint32, maxInstances uint32, outSize uint32, inSize uint32, defaultTimeout uint32, sa *syscall.SecurityAttributes) (handle syscall.Handle, err error) [failretval==syscall.InvalidHandle] = CreateNamedPipeW
|
||||
//sys createFile(name string, access uint32, mode uint32, sa *syscall.SecurityAttributes, createmode uint32, attrs uint32, templatefile syscall.Handle) (handle syscall.Handle, err error) [failretval==syscall.InvalidHandle] = CreateFileW
|
||||
//sys getNamedPipeInfo(pipe syscall.Handle, flags *uint32, outSize *uint32, inSize *uint32, maxInstances *uint32) (err error) = GetNamedPipeInfo
|
||||
//sys getNamedPipeHandleState(pipe syscall.Handle, state *uint32, curInstances *uint32, maxCollectionCount *uint32, collectDataTimeout *uint32, userName *uint16, maxUserNameSize uint32) (err error) = GetNamedPipeHandleStateW
|
||||
//sys localAlloc(uFlags uint32, length uint32) (ptr uintptr) = LocalAlloc
|
||||
//sys ntCreateNamedPipeFile(pipe *syscall.Handle, access uint32, oa *objectAttributes, iosb *ioStatusBlock, share uint32, disposition uint32, options uint32, typ uint32, readMode uint32, completionMode uint32, maxInstances uint32, inboundQuota uint32, outputQuota uint32, timeout *int64) (status ntstatus) = ntdll.NtCreateNamedPipeFile
|
||||
//sys rtlNtStatusToDosError(status ntstatus) (winerr error) = ntdll.RtlNtStatusToDosErrorNoTeb
|
||||
//sys rtlDosPathNameToNtPathName(name *uint16, ntName *unicodeString, filePart uintptr, reserved uintptr) (status ntstatus) = ntdll.RtlDosPathNameToNtPathName_U
|
||||
//sys rtlDefaultNpAcl(dacl *uintptr) (status ntstatus) = ntdll.RtlDefaultNpAcl
|
||||
|
||||
type ioStatusBlock struct {
|
||||
Status, Information uintptr
|
||||
}
|
||||
|
||||
type objectAttributes struct {
|
||||
Length uintptr
|
||||
RootDirectory uintptr
|
||||
ObjectName *unicodeString
|
||||
Attributes uintptr
|
||||
SecurityDescriptor *securityDescriptor
|
||||
SecurityQoS uintptr
|
||||
}
|
||||
|
||||
type unicodeString struct {
|
||||
Length uint16
|
||||
MaximumLength uint16
|
||||
Buffer uintptr
|
||||
}
|
||||
|
||||
type securityDescriptor struct {
|
||||
Revision byte
|
||||
Sbz1 byte
|
||||
Control uint16
|
||||
Owner uintptr
|
||||
Group uintptr
|
||||
Sacl uintptr
|
||||
Dacl uintptr
|
||||
}
|
||||
|
||||
type ntstatus int32
|
||||
|
||||
func (status ntstatus) Err() error {
|
||||
if status >= 0 {
|
||||
return nil
|
||||
}
|
||||
return rtlNtStatusToDosError(status)
|
||||
}
|
||||
|
||||
const (
|
||||
cERROR_PIPE_BUSY = syscall.Errno(231)
|
||||
cERROR_NO_DATA = syscall.Errno(232)
|
||||
cERROR_PIPE_CONNECTED = syscall.Errno(535)
|
||||
cERROR_SEM_TIMEOUT = syscall.Errno(121)
|
||||
|
||||
cSECURITY_SQOS_PRESENT = 0x100000
|
||||
cSECURITY_ANONYMOUS = 0
|
||||
|
||||
cPIPE_TYPE_MESSAGE = 4
|
||||
|
||||
cPIPE_READMODE_MESSAGE = 2
|
||||
|
||||
cFILE_OPEN = 1
|
||||
cFILE_CREATE = 2
|
||||
|
||||
cFILE_PIPE_MESSAGE_TYPE = 1
|
||||
cFILE_PIPE_REJECT_REMOTE_CLIENTS = 2
|
||||
|
||||
cSE_DACL_PRESENT = 4
|
||||
)
|
||||
|
||||
var (
|
||||
// ErrPipeListenerClosed is returned for pipe operations on listeners that have been closed.
|
||||
// This error should match net.errClosing since docker takes a dependency on its text.
|
||||
ErrPipeListenerClosed = errors.New("use of closed network connection")
|
||||
|
||||
errPipeWriteClosed = errors.New("pipe has been closed for write")
|
||||
)
|
||||
|
||||
type win32Pipe struct {
|
||||
*win32File
|
||||
path string
|
||||
}
|
||||
|
||||
type win32MessageBytePipe struct {
|
||||
win32Pipe
|
||||
writeClosed bool
|
||||
readEOF bool
|
||||
}
|
||||
|
||||
type pipeAddress string
|
||||
|
||||
func (f *win32Pipe) LocalAddr() net.Addr {
|
||||
return pipeAddress(f.path)
|
||||
}
|
||||
|
||||
func (f *win32Pipe) RemoteAddr() net.Addr {
|
||||
return pipeAddress(f.path)
|
||||
}
|
||||
|
||||
func (f *win32Pipe) SetDeadline(t time.Time) error {
|
||||
f.SetReadDeadline(t)
|
||||
f.SetWriteDeadline(t)
|
||||
return nil
|
||||
}
|
||||
|
||||
// CloseWrite closes the write side of a message pipe in byte mode.
|
||||
func (f *win32MessageBytePipe) CloseWrite() error {
|
||||
if f.writeClosed {
|
||||
return errPipeWriteClosed
|
||||
}
|
||||
err := f.win32File.Flush()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
_, err = f.win32File.Write(nil)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
f.writeClosed = true
|
||||
return nil
|
||||
}
|
||||
|
||||
// Write writes bytes to a message pipe in byte mode. Zero-byte writes are ignored, since
|
||||
// they are used to implement CloseWrite().
|
||||
func (f *win32MessageBytePipe) Write(b []byte) (int, error) {
|
||||
if f.writeClosed {
|
||||
return 0, errPipeWriteClosed
|
||||
}
|
||||
if len(b) == 0 {
|
||||
return 0, nil
|
||||
}
|
||||
return f.win32File.Write(b)
|
||||
}
|
||||
|
||||
// Read reads bytes from a message pipe in byte mode. A read of a zero-byte message on a message
|
||||
// mode pipe will return io.EOF, as will all subsequent reads.
|
||||
func (f *win32MessageBytePipe) Read(b []byte) (int, error) {
|
||||
if f.readEOF {
|
||||
return 0, io.EOF
|
||||
}
|
||||
n, err := f.win32File.Read(b)
|
||||
if err == io.EOF {
|
||||
// If this was the result of a zero-byte read, then
|
||||
// it is possible that the read was due to a zero-size
|
||||
// message. Since we are simulating CloseWrite with a
|
||||
// zero-byte message, ensure that all future Read() calls
|
||||
// also return EOF.
|
||||
f.readEOF = true
|
||||
} else if err == syscall.ERROR_MORE_DATA {
|
||||
// ERROR_MORE_DATA indicates that the pipe's read mode is message mode
|
||||
// and the message still has more bytes. Treat this as a success, since
|
||||
// this package presents all named pipes as byte streams.
|
||||
err = nil
|
||||
}
|
||||
return n, err
|
||||
}
|
||||
|
||||
func (s pipeAddress) Network() string {
|
||||
return "pipe"
|
||||
}
|
||||
|
||||
func (s pipeAddress) String() string {
|
||||
return string(s)
|
||||
}
|
||||
|
||||
// tryDialPipe attempts to dial the pipe at `path` until `ctx` cancellation or timeout.
|
||||
func tryDialPipe(ctx context.Context, path *string, access uint32) (syscall.Handle, error) {
|
||||
for {
|
||||
|
||||
select {
|
||||
case <-ctx.Done():
|
||||
return syscall.Handle(0), ctx.Err()
|
||||
default:
|
||||
h, err := createFile(*path, access, 0, nil, syscall.OPEN_EXISTING, syscall.FILE_FLAG_OVERLAPPED|cSECURITY_SQOS_PRESENT|cSECURITY_ANONYMOUS, 0)
|
||||
if err == nil {
|
||||
return h, nil
|
||||
}
|
||||
if err != cERROR_PIPE_BUSY {
|
||||
return h, &os.PathError{Err: err, Op: "open", Path: *path}
|
||||
}
|
||||
// Wait 10 msec and try again. This is a rather simplistic
|
||||
// view, as we always try each 10 milliseconds.
|
||||
time.Sleep(10 * time.Millisecond)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// DialPipe connects to a named pipe by path, timing out if the connection
|
||||
// takes longer than the specified duration. If timeout is nil, then we use
|
||||
// a default timeout of 2 seconds. (We do not use WaitNamedPipe.)
|
||||
func DialPipe(path string, timeout *time.Duration) (net.Conn, error) {
|
||||
var absTimeout time.Time
|
||||
if timeout != nil {
|
||||
absTimeout = time.Now().Add(*timeout)
|
||||
} else {
|
||||
absTimeout = time.Now().Add(2 * time.Second)
|
||||
}
|
||||
ctx, _ := context.WithDeadline(context.Background(), absTimeout)
|
||||
conn, err := DialPipeContext(ctx, path)
|
||||
if err == context.DeadlineExceeded {
|
||||
return nil, ErrTimeout
|
||||
}
|
||||
return conn, err
|
||||
}
|
||||
|
||||
// DialPipeContext attempts to connect to a named pipe by `path` until `ctx`
|
||||
// cancellation or timeout.
|
||||
func DialPipeContext(ctx context.Context, path string) (net.Conn, error) {
|
||||
return DialPipeAccess(ctx, path, syscall.GENERIC_READ|syscall.GENERIC_WRITE)
|
||||
}
|
||||
|
||||
// DialPipeAccess attempts to connect to a named pipe by `path` with `access` until `ctx`
|
||||
// cancellation or timeout.
|
||||
func DialPipeAccess(ctx context.Context, path string, access uint32) (net.Conn, error) {
|
||||
var err error
|
||||
var h syscall.Handle
|
||||
h, err = tryDialPipe(ctx, &path, access)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
var flags uint32
|
||||
err = getNamedPipeInfo(h, &flags, nil, nil, nil)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
f, err := makeWin32File(h)
|
||||
if err != nil {
|
||||
syscall.Close(h)
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// If the pipe is in message mode, return a message byte pipe, which
|
||||
// supports CloseWrite().
|
||||
if flags&cPIPE_TYPE_MESSAGE != 0 {
|
||||
return &win32MessageBytePipe{
|
||||
win32Pipe: win32Pipe{win32File: f, path: path},
|
||||
}, nil
|
||||
}
|
||||
return &win32Pipe{win32File: f, path: path}, nil
|
||||
}
|
||||
|
||||
type acceptResponse struct {
|
||||
f *win32File
|
||||
err error
|
||||
}
|
||||
|
||||
type win32PipeListener struct {
|
||||
firstHandle syscall.Handle
|
||||
path string
|
||||
config PipeConfig
|
||||
acceptCh chan (chan acceptResponse)
|
||||
closeCh chan int
|
||||
doneCh chan int
|
||||
}
|
||||
|
||||
func makeServerPipeHandle(path string, sd []byte, c *PipeConfig, first bool) (syscall.Handle, error) {
|
||||
path16, err := syscall.UTF16FromString(path)
|
||||
if err != nil {
|
||||
return 0, &os.PathError{Op: "open", Path: path, Err: err}
|
||||
}
|
||||
|
||||
var oa objectAttributes
|
||||
oa.Length = unsafe.Sizeof(oa)
|
||||
|
||||
var ntPath unicodeString
|
||||
if err := rtlDosPathNameToNtPathName(&path16[0], &ntPath, 0, 0).Err(); err != nil {
|
||||
return 0, &os.PathError{Op: "open", Path: path, Err: err}
|
||||
}
|
||||
defer localFree(ntPath.Buffer)
|
||||
oa.ObjectName = &ntPath
|
||||
|
||||
// The security descriptor is only needed for the first pipe.
|
||||
if first {
|
||||
if sd != nil {
|
||||
len := uint32(len(sd))
|
||||
sdb := localAlloc(0, len)
|
||||
defer localFree(sdb)
|
||||
copy((*[0xffff]byte)(unsafe.Pointer(sdb))[:], sd)
|
||||
oa.SecurityDescriptor = (*securityDescriptor)(unsafe.Pointer(sdb))
|
||||
} else {
|
||||
// Construct the default named pipe security descriptor.
|
||||
var dacl uintptr
|
||||
if err := rtlDefaultNpAcl(&dacl).Err(); err != nil {
|
||||
return 0, fmt.Errorf("getting default named pipe ACL: %s", err)
|
||||
}
|
||||
defer localFree(dacl)
|
||||
|
||||
sdb := &securityDescriptor{
|
||||
Revision: 1,
|
||||
Control: cSE_DACL_PRESENT,
|
||||
Dacl: dacl,
|
||||
}
|
||||
oa.SecurityDescriptor = sdb
|
||||
}
|
||||
}
|
||||
|
||||
typ := uint32(cFILE_PIPE_REJECT_REMOTE_CLIENTS)
|
||||
if c.MessageMode {
|
||||
typ |= cFILE_PIPE_MESSAGE_TYPE
|
||||
}
|
||||
|
||||
disposition := uint32(cFILE_OPEN)
|
||||
access := uint32(syscall.GENERIC_READ | syscall.GENERIC_WRITE | syscall.SYNCHRONIZE)
|
||||
if first {
|
||||
disposition = cFILE_CREATE
|
||||
// By not asking for read or write access, the named pipe file system
|
||||
// will put this pipe into an initially disconnected state, blocking
|
||||
// client connections until the next call with first == false.
|
||||
access = syscall.SYNCHRONIZE
|
||||
}
|
||||
|
||||
timeout := int64(-50 * 10000) // 50ms
|
||||
|
||||
var (
|
||||
h syscall.Handle
|
||||
iosb ioStatusBlock
|
||||
)
|
||||
err = ntCreateNamedPipeFile(&h, access, &oa, &iosb, syscall.FILE_SHARE_READ|syscall.FILE_SHARE_WRITE, disposition, 0, typ, 0, 0, 0xffffffff, uint32(c.InputBufferSize), uint32(c.OutputBufferSize), &timeout).Err()
|
||||
if err != nil {
|
||||
return 0, &os.PathError{Op: "open", Path: path, Err: err}
|
||||
}
|
||||
|
||||
runtime.KeepAlive(ntPath)
|
||||
return h, nil
|
||||
}
|
||||
|
||||
func (l *win32PipeListener) makeServerPipe() (*win32File, error) {
|
||||
h, err := makeServerPipeHandle(l.path, nil, &l.config, false)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
f, err := makeWin32File(h)
|
||||
if err != nil {
|
||||
syscall.Close(h)
|
||||
return nil, err
|
||||
}
|
||||
return f, nil
|
||||
}
|
||||
|
||||
func (l *win32PipeListener) makeConnectedServerPipe() (*win32File, error) {
|
||||
p, err := l.makeServerPipe()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// Wait for the client to connect.
|
||||
ch := make(chan error)
|
||||
go func(p *win32File) {
|
||||
ch <- connectPipe(p)
|
||||
}(p)
|
||||
|
||||
select {
|
||||
case err = <-ch:
|
||||
if err != nil {
|
||||
p.Close()
|
||||
p = nil
|
||||
}
|
||||
case <-l.closeCh:
|
||||
// Abort the connect request by closing the handle.
|
||||
p.Close()
|
||||
p = nil
|
||||
err = <-ch
|
||||
if err == nil || err == ErrFileClosed {
|
||||
err = ErrPipeListenerClosed
|
||||
}
|
||||
}
|
||||
return p, err
|
||||
}
|
||||
|
||||
func (l *win32PipeListener) listenerRoutine() {
|
||||
closed := false
|
||||
for !closed {
|
||||
select {
|
||||
case <-l.closeCh:
|
||||
closed = true
|
||||
case responseCh := <-l.acceptCh:
|
||||
var (
|
||||
p *win32File
|
||||
err error
|
||||
)
|
||||
for {
|
||||
p, err = l.makeConnectedServerPipe()
|
||||
// If the connection was immediately closed by the client, try
|
||||
// again.
|
||||
if err != cERROR_NO_DATA {
|
||||
break
|
||||
}
|
||||
}
|
||||
responseCh <- acceptResponse{p, err}
|
||||
closed = err == ErrPipeListenerClosed
|
||||
}
|
||||
}
|
||||
syscall.Close(l.firstHandle)
|
||||
l.firstHandle = 0
|
||||
// Notify Close() and Accept() callers that the handle has been closed.
|
||||
close(l.doneCh)
|
||||
}
|
||||
|
||||
// PipeConfig contain configuration for the pipe listener.
|
||||
type PipeConfig struct {
|
||||
// SecurityDescriptor contains a Windows security descriptor in SDDL format.
|
||||
SecurityDescriptor string
|
||||
|
||||
// MessageMode determines whether the pipe is in byte or message mode. In either
|
||||
// case the pipe is read in byte mode by default. The only practical difference in
|
||||
// this implementation is that CloseWrite() is only supported for message mode pipes;
|
||||
// CloseWrite() is implemented as a zero-byte write, but zero-byte writes are only
|
||||
// transferred to the reader (and returned as io.EOF in this implementation)
|
||||
// when the pipe is in message mode.
|
||||
MessageMode bool
|
||||
|
||||
// InputBufferSize specifies the size of the input buffer, in bytes.
|
||||
InputBufferSize int32
|
||||
|
||||
// OutputBufferSize specifies the size of the output buffer, in bytes.
|
||||
OutputBufferSize int32
|
||||
}
|
||||
|
||||
// ListenPipe creates a listener on a Windows named pipe path, e.g. \\.\pipe\mypipe.
|
||||
// The pipe must not already exist.
|
||||
func ListenPipe(path string, c *PipeConfig) (net.Listener, error) {
|
||||
var (
|
||||
sd []byte
|
||||
err error
|
||||
)
|
||||
if c == nil {
|
||||
c = &PipeConfig{}
|
||||
}
|
||||
if c.SecurityDescriptor != "" {
|
||||
sd, err = SddlToSecurityDescriptor(c.SecurityDescriptor)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
h, err := makeServerPipeHandle(path, sd, c, true)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
l := &win32PipeListener{
|
||||
firstHandle: h,
|
||||
path: path,
|
||||
config: *c,
|
||||
acceptCh: make(chan (chan acceptResponse)),
|
||||
closeCh: make(chan int),
|
||||
doneCh: make(chan int),
|
||||
}
|
||||
go l.listenerRoutine()
|
||||
return l, nil
|
||||
}
|
||||
|
||||
func connectPipe(p *win32File) error {
|
||||
c, err := p.prepareIo()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer p.wg.Done()
|
||||
|
||||
err = connectNamedPipe(p.handle, &c.o)
|
||||
_, err = p.asyncIo(c, nil, 0, err)
|
||||
if err != nil && err != cERROR_PIPE_CONNECTED {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (l *win32PipeListener) Accept() (net.Conn, error) {
|
||||
ch := make(chan acceptResponse)
|
||||
select {
|
||||
case l.acceptCh <- ch:
|
||||
response := <-ch
|
||||
err := response.err
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if l.config.MessageMode {
|
||||
return &win32MessageBytePipe{
|
||||
win32Pipe: win32Pipe{win32File: response.f, path: l.path},
|
||||
}, nil
|
||||
}
|
||||
return &win32Pipe{win32File: response.f, path: l.path}, nil
|
||||
case <-l.doneCh:
|
||||
return nil, ErrPipeListenerClosed
|
||||
}
|
||||
}
|
||||
|
||||
func (l *win32PipeListener) Close() error {
|
||||
select {
|
||||
case l.closeCh <- 1:
|
||||
<-l.doneCh
|
||||
case <-l.doneCh:
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (l *win32PipeListener) Addr() net.Addr {
|
||||
return pipeAddress(l.path)
|
||||
}
|
||||
228
vendor/github.com/Microsoft/go-winio/pkg/guid/guid.go
generated
vendored
228
vendor/github.com/Microsoft/go-winio/pkg/guid/guid.go
generated
vendored
|
|
@ -1,228 +0,0 @@
|
|||
// +build windows
|
||||
|
||||
// Package guid provides a GUID type. The backing structure for a GUID is
|
||||
// identical to that used by the golang.org/x/sys/windows GUID type.
|
||||
// There are two main binary encodings used for a GUID, the big-endian encoding,
|
||||
// and the Windows (mixed-endian) encoding. See here for details:
|
||||
// https://en.wikipedia.org/wiki/Universally_unique_identifier#Encoding
|
||||
package guid
|
||||
|
||||
import (
|
||||
"crypto/rand"
|
||||
"crypto/sha1"
|
||||
"encoding"
|
||||
"encoding/binary"
|
||||
"fmt"
|
||||
"strconv"
|
||||
)
|
||||
|
||||
// Variant specifies which GUID variant (or "type") of the GUID. It determines
|
||||
// how the entirety of the rest of the GUID is interpreted.
|
||||
type Variant uint8
|
||||
|
||||
// The variants specified by RFC 4122.
|
||||
const (
|
||||
// VariantUnknown specifies a GUID variant which does not conform to one of
|
||||
// the variant encodings specified in RFC 4122.
|
||||
VariantUnknown Variant = iota
|
||||
VariantNCS
|
||||
VariantRFC4122
|
||||
VariantMicrosoft
|
||||
VariantFuture
|
||||
)
|
||||
|
||||
// Version specifies how the bits in the GUID were generated. For instance, a
|
||||
// version 4 GUID is randomly generated, and a version 5 is generated from the
|
||||
// hash of an input string.
|
||||
type Version uint8
|
||||
|
||||
var _ = (encoding.TextMarshaler)(GUID{})
|
||||
var _ = (encoding.TextUnmarshaler)(&GUID{})
|
||||
|
||||
// NewV4 returns a new version 4 (pseudorandom) GUID, as defined by RFC 4122.
|
||||
func NewV4() (GUID, error) {
|
||||
var b [16]byte
|
||||
if _, err := rand.Read(b[:]); err != nil {
|
||||
return GUID{}, err
|
||||
}
|
||||
|
||||
g := FromArray(b)
|
||||
g.setVersion(4) // Version 4 means randomly generated.
|
||||
g.setVariant(VariantRFC4122)
|
||||
|
||||
return g, nil
|
||||
}
|
||||
|
||||
// NewV5 returns a new version 5 (generated from a string via SHA-1 hashing)
|
||||
// GUID, as defined by RFC 4122. The RFC is unclear on the encoding of the name,
|
||||
// and the sample code treats it as a series of bytes, so we do the same here.
|
||||
//
|
||||
// Some implementations, such as those found on Windows, treat the name as a
|
||||
// big-endian UTF16 stream of bytes. If that is desired, the string can be
|
||||
// encoded as such before being passed to this function.
|
||||
func NewV5(namespace GUID, name []byte) (GUID, error) {
|
||||
b := sha1.New()
|
||||
namespaceBytes := namespace.ToArray()
|
||||
b.Write(namespaceBytes[:])
|
||||
b.Write(name)
|
||||
|
||||
a := [16]byte{}
|
||||
copy(a[:], b.Sum(nil))
|
||||
|
||||
g := FromArray(a)
|
||||
g.setVersion(5) // Version 5 means generated from a string.
|
||||
g.setVariant(VariantRFC4122)
|
||||
|
||||
return g, nil
|
||||
}
|
||||
|
||||
func fromArray(b [16]byte, order binary.ByteOrder) GUID {
|
||||
var g GUID
|
||||
g.Data1 = order.Uint32(b[0:4])
|
||||
g.Data2 = order.Uint16(b[4:6])
|
||||
g.Data3 = order.Uint16(b[6:8])
|
||||
copy(g.Data4[:], b[8:16])
|
||||
return g
|
||||
}
|
||||
|
||||
func (g GUID) toArray(order binary.ByteOrder) [16]byte {
|
||||
b := [16]byte{}
|
||||
order.PutUint32(b[0:4], g.Data1)
|
||||
order.PutUint16(b[4:6], g.Data2)
|
||||
order.PutUint16(b[6:8], g.Data3)
|
||||
copy(b[8:16], g.Data4[:])
|
||||
return b
|
||||
}
|
||||
|
||||
// FromArray constructs a GUID from a big-endian encoding array of 16 bytes.
|
||||
func FromArray(b [16]byte) GUID {
|
||||
return fromArray(b, binary.BigEndian)
|
||||
}
|
||||
|
||||
// ToArray returns an array of 16 bytes representing the GUID in big-endian
|
||||
// encoding.
|
||||
func (g GUID) ToArray() [16]byte {
|
||||
return g.toArray(binary.BigEndian)
|
||||
}
|
||||
|
||||
// FromWindowsArray constructs a GUID from a Windows encoding array of bytes.
|
||||
func FromWindowsArray(b [16]byte) GUID {
|
||||
return fromArray(b, binary.LittleEndian)
|
||||
}
|
||||
|
||||
// ToWindowsArray returns an array of 16 bytes representing the GUID in Windows
|
||||
// encoding.
|
||||
func (g GUID) ToWindowsArray() [16]byte {
|
||||
return g.toArray(binary.LittleEndian)
|
||||
}
|
||||
|
||||
func (g GUID) String() string {
|
||||
return fmt.Sprintf(
|
||||
"%08x-%04x-%04x-%04x-%012x",
|
||||
g.Data1,
|
||||
g.Data2,
|
||||
g.Data3,
|
||||
g.Data4[:2],
|
||||
g.Data4[2:])
|
||||
}
|
||||
|
||||
// FromString parses a string containing a GUID and returns the GUID. The only
|
||||
// format currently supported is the `xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx`
|
||||
// format.
|
||||
func FromString(s string) (GUID, error) {
|
||||
if len(s) != 36 {
|
||||
return GUID{}, fmt.Errorf("invalid GUID %q", s)
|
||||
}
|
||||
if s[8] != '-' || s[13] != '-' || s[18] != '-' || s[23] != '-' {
|
||||
return GUID{}, fmt.Errorf("invalid GUID %q", s)
|
||||
}
|
||||
|
||||
var g GUID
|
||||
|
||||
data1, err := strconv.ParseUint(s[0:8], 16, 32)
|
||||
if err != nil {
|
||||
return GUID{}, fmt.Errorf("invalid GUID %q", s)
|
||||
}
|
||||
g.Data1 = uint32(data1)
|
||||
|
||||
data2, err := strconv.ParseUint(s[9:13], 16, 16)
|
||||
if err != nil {
|
||||
return GUID{}, fmt.Errorf("invalid GUID %q", s)
|
||||
}
|
||||
g.Data2 = uint16(data2)
|
||||
|
||||
data3, err := strconv.ParseUint(s[14:18], 16, 16)
|
||||
if err != nil {
|
||||
return GUID{}, fmt.Errorf("invalid GUID %q", s)
|
||||
}
|
||||
g.Data3 = uint16(data3)
|
||||
|
||||
for i, x := range []int{19, 21, 24, 26, 28, 30, 32, 34} {
|
||||
v, err := strconv.ParseUint(s[x:x+2], 16, 8)
|
||||
if err != nil {
|
||||
return GUID{}, fmt.Errorf("invalid GUID %q", s)
|
||||
}
|
||||
g.Data4[i] = uint8(v)
|
||||
}
|
||||
|
||||
return g, nil
|
||||
}
|
||||
|
||||
func (g *GUID) setVariant(v Variant) {
|
||||
d := g.Data4[0]
|
||||
switch v {
|
||||
case VariantNCS:
|
||||
d = (d & 0x7f)
|
||||
case VariantRFC4122:
|
||||
d = (d & 0x3f) | 0x80
|
||||
case VariantMicrosoft:
|
||||
d = (d & 0x1f) | 0xc0
|
||||
case VariantFuture:
|
||||
d = (d & 0x0f) | 0xe0
|
||||
case VariantUnknown:
|
||||
fallthrough
|
||||
default:
|
||||
panic(fmt.Sprintf("invalid variant: %d", v))
|
||||
}
|
||||
g.Data4[0] = d
|
||||
}
|
||||
|
||||
// Variant returns the GUID variant, as defined in RFC 4122.
|
||||
func (g GUID) Variant() Variant {
|
||||
b := g.Data4[0]
|
||||
if b&0x80 == 0 {
|
||||
return VariantNCS
|
||||
} else if b&0xc0 == 0x80 {
|
||||
return VariantRFC4122
|
||||
} else if b&0xe0 == 0xc0 {
|
||||
return VariantMicrosoft
|
||||
} else if b&0xe0 == 0xe0 {
|
||||
return VariantFuture
|
||||
}
|
||||
return VariantUnknown
|
||||
}
|
||||
|
||||
func (g *GUID) setVersion(v Version) {
|
||||
g.Data3 = (g.Data3 & 0x0fff) | (uint16(v) << 12)
|
||||
}
|
||||
|
||||
// Version returns the GUID version, as defined in RFC 4122.
|
||||
func (g GUID) Version() Version {
|
||||
return Version((g.Data3 & 0xF000) >> 12)
|
||||
}
|
||||
|
||||
// MarshalText returns the textual representation of the GUID.
|
||||
func (g GUID) MarshalText() ([]byte, error) {
|
||||
return []byte(g.String()), nil
|
||||
}
|
||||
|
||||
// UnmarshalText takes the textual representation of a GUID, and unmarhals it
|
||||
// into this GUID.
|
||||
func (g *GUID) UnmarshalText(text []byte) error {
|
||||
g2, err := FromString(string(text))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
*g = g2
|
||||
return nil
|
||||
}
|
||||
15
vendor/github.com/Microsoft/go-winio/pkg/guid/guid_nonwindows.go
generated
vendored
15
vendor/github.com/Microsoft/go-winio/pkg/guid/guid_nonwindows.go
generated
vendored
|
|
@ -1,15 +0,0 @@
|
|||
// +build !windows
|
||||
|
||||
package guid
|
||||
|
||||
// GUID represents a GUID/UUID. It has the same structure as
|
||||
// golang.org/x/sys/windows.GUID so that it can be used with functions expecting
|
||||
// that type. It is defined as its own type as that is only available to builds
|
||||
// targeted at `windows`. The representation matches that used by native Windows
|
||||
// code.
|
||||
type GUID struct {
|
||||
Data1 uint32
|
||||
Data2 uint16
|
||||
Data3 uint16
|
||||
Data4 [8]byte
|
||||
}
|
||||
10
vendor/github.com/Microsoft/go-winio/pkg/guid/guid_windows.go
generated
vendored
10
vendor/github.com/Microsoft/go-winio/pkg/guid/guid_windows.go
generated
vendored
|
|
@ -1,10 +0,0 @@
|
|||
package guid
|
||||
|
||||
import "golang.org/x/sys/windows"
|
||||
|
||||
// GUID represents a GUID/UUID. It has the same structure as
|
||||
// golang.org/x/sys/windows.GUID so that it can be used with functions expecting
|
||||
// that type. It is defined as its own type so that stringification and
|
||||
// marshaling can be supported. The representation matches that used by native
|
||||
// Windows code.
|
||||
type GUID windows.GUID
|
||||
203
vendor/github.com/Microsoft/go-winio/privilege.go
generated
vendored
203
vendor/github.com/Microsoft/go-winio/privilege.go
generated
vendored
|
|
@ -1,203 +0,0 @@
|
|||
// +build windows
|
||||
|
||||
package winio
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"encoding/binary"
|
||||
"fmt"
|
||||
"runtime"
|
||||
"sync"
|
||||
"syscall"
|
||||
"unicode/utf16"
|
||||
|
||||
"golang.org/x/sys/windows"
|
||||
)
|
||||
|
||||
//sys adjustTokenPrivileges(token windows.Token, releaseAll bool, input *byte, outputSize uint32, output *byte, requiredSize *uint32) (success bool, err error) [true] = advapi32.AdjustTokenPrivileges
|
||||
//sys impersonateSelf(level uint32) (err error) = advapi32.ImpersonateSelf
|
||||
//sys revertToSelf() (err error) = advapi32.RevertToSelf
|
||||
//sys openThreadToken(thread syscall.Handle, accessMask uint32, openAsSelf bool, token *windows.Token) (err error) = advapi32.OpenThreadToken
|
||||
//sys getCurrentThread() (h syscall.Handle) = GetCurrentThread
|
||||
//sys lookupPrivilegeValue(systemName string, name string, luid *uint64) (err error) = advapi32.LookupPrivilegeValueW
|
||||
//sys lookupPrivilegeName(systemName string, luid *uint64, buffer *uint16, size *uint32) (err error) = advapi32.LookupPrivilegeNameW
|
||||
//sys lookupPrivilegeDisplayName(systemName string, name *uint16, buffer *uint16, size *uint32, languageId *uint32) (err error) = advapi32.LookupPrivilegeDisplayNameW
|
||||
|
||||
const (
|
||||
SE_PRIVILEGE_ENABLED = 2
|
||||
|
||||
ERROR_NOT_ALL_ASSIGNED syscall.Errno = 1300
|
||||
|
||||
SeBackupPrivilege = "SeBackupPrivilege"
|
||||
SeRestorePrivilege = "SeRestorePrivilege"
|
||||
SeSecurityPrivilege = "SeSecurityPrivilege"
|
||||
)
|
||||
|
||||
const (
|
||||
securityAnonymous = iota
|
||||
securityIdentification
|
||||
securityImpersonation
|
||||
securityDelegation
|
||||
)
|
||||
|
||||
var (
|
||||
privNames = make(map[string]uint64)
|
||||
privNameMutex sync.Mutex
|
||||
)
|
||||
|
||||
// PrivilegeError represents an error enabling privileges.
|
||||
type PrivilegeError struct {
|
||||
privileges []uint64
|
||||
}
|
||||
|
||||
func (e *PrivilegeError) Error() string {
|
||||
s := ""
|
||||
if len(e.privileges) > 1 {
|
||||
s = "Could not enable privileges "
|
||||
} else {
|
||||
s = "Could not enable privilege "
|
||||
}
|
||||
for i, p := range e.privileges {
|
||||
if i != 0 {
|
||||
s += ", "
|
||||
}
|
||||
s += `"`
|
||||
s += getPrivilegeName(p)
|
||||
s += `"`
|
||||
}
|
||||
return s
|
||||
}
|
||||
|
||||
// RunWithPrivilege enables a single privilege for a function call.
|
||||
func RunWithPrivilege(name string, fn func() error) error {
|
||||
return RunWithPrivileges([]string{name}, fn)
|
||||
}
|
||||
|
||||
// RunWithPrivileges enables privileges for a function call.
|
||||
func RunWithPrivileges(names []string, fn func() error) error {
|
||||
privileges, err := mapPrivileges(names)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
runtime.LockOSThread()
|
||||
defer runtime.UnlockOSThread()
|
||||
token, err := newThreadToken()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer releaseThreadToken(token)
|
||||
err = adjustPrivileges(token, privileges, SE_PRIVILEGE_ENABLED)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return fn()
|
||||
}
|
||||
|
||||
func mapPrivileges(names []string) ([]uint64, error) {
|
||||
var privileges []uint64
|
||||
privNameMutex.Lock()
|
||||
defer privNameMutex.Unlock()
|
||||
for _, name := range names {
|
||||
p, ok := privNames[name]
|
||||
if !ok {
|
||||
err := lookupPrivilegeValue("", name, &p)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
privNames[name] = p
|
||||
}
|
||||
privileges = append(privileges, p)
|
||||
}
|
||||
return privileges, nil
|
||||
}
|
||||
|
||||
// EnableProcessPrivileges enables privileges globally for the process.
|
||||
func EnableProcessPrivileges(names []string) error {
|
||||
return enableDisableProcessPrivilege(names, SE_PRIVILEGE_ENABLED)
|
||||
}
|
||||
|
||||
// DisableProcessPrivileges disables privileges globally for the process.
|
||||
func DisableProcessPrivileges(names []string) error {
|
||||
return enableDisableProcessPrivilege(names, 0)
|
||||
}
|
||||
|
||||
func enableDisableProcessPrivilege(names []string, action uint32) error {
|
||||
privileges, err := mapPrivileges(names)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
p, _ := windows.GetCurrentProcess()
|
||||
var token windows.Token
|
||||
err = windows.OpenProcessToken(p, windows.TOKEN_ADJUST_PRIVILEGES|windows.TOKEN_QUERY, &token)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
defer token.Close()
|
||||
return adjustPrivileges(token, privileges, action)
|
||||
}
|
||||
|
||||
func adjustPrivileges(token windows.Token, privileges []uint64, action uint32) error {
|
||||
var b bytes.Buffer
|
||||
binary.Write(&b, binary.LittleEndian, uint32(len(privileges)))
|
||||
for _, p := range privileges {
|
||||
binary.Write(&b, binary.LittleEndian, p)
|
||||
binary.Write(&b, binary.LittleEndian, action)
|
||||
}
|
||||
prevState := make([]byte, b.Len())
|
||||
reqSize := uint32(0)
|
||||
success, err := adjustTokenPrivileges(token, false, &b.Bytes()[0], uint32(len(prevState)), &prevState[0], &reqSize)
|
||||
if !success {
|
||||
return err
|
||||
}
|
||||
if err == ERROR_NOT_ALL_ASSIGNED {
|
||||
return &PrivilegeError{privileges}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func getPrivilegeName(luid uint64) string {
|
||||
var nameBuffer [256]uint16
|
||||
bufSize := uint32(len(nameBuffer))
|
||||
err := lookupPrivilegeName("", &luid, &nameBuffer[0], &bufSize)
|
||||
if err != nil {
|
||||
return fmt.Sprintf("<unknown privilege %d>", luid)
|
||||
}
|
||||
|
||||
var displayNameBuffer [256]uint16
|
||||
displayBufSize := uint32(len(displayNameBuffer))
|
||||
var langID uint32
|
||||
err = lookupPrivilegeDisplayName("", &nameBuffer[0], &displayNameBuffer[0], &displayBufSize, &langID)
|
||||
if err != nil {
|
||||
return fmt.Sprintf("<unknown privilege %s>", string(utf16.Decode(nameBuffer[:bufSize])))
|
||||
}
|
||||
|
||||
return string(utf16.Decode(displayNameBuffer[:displayBufSize]))
|
||||
}
|
||||
|
||||
func newThreadToken() (windows.Token, error) {
|
||||
err := impersonateSelf(securityImpersonation)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
|
||||
var token windows.Token
|
||||
err = openThreadToken(getCurrentThread(), syscall.TOKEN_ADJUST_PRIVILEGES|syscall.TOKEN_QUERY, false, &token)
|
||||
if err != nil {
|
||||
rerr := revertToSelf()
|
||||
if rerr != nil {
|
||||
panic(rerr)
|
||||
}
|
||||
return 0, err
|
||||
}
|
||||
return token, nil
|
||||
}
|
||||
|
||||
func releaseThreadToken(h windows.Token) {
|
||||
err := revertToSelf()
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
h.Close()
|
||||
}
|
||||
128
vendor/github.com/Microsoft/go-winio/reparse.go
generated
vendored
128
vendor/github.com/Microsoft/go-winio/reparse.go
generated
vendored
|
|
@ -1,128 +0,0 @@
|
|||
package winio
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"encoding/binary"
|
||||
"fmt"
|
||||
"strings"
|
||||
"unicode/utf16"
|
||||
"unsafe"
|
||||
)
|
||||
|
||||
const (
|
||||
reparseTagMountPoint = 0xA0000003
|
||||
reparseTagSymlink = 0xA000000C
|
||||
)
|
||||
|
||||
type reparseDataBuffer struct {
|
||||
ReparseTag uint32
|
||||
ReparseDataLength uint16
|
||||
Reserved uint16
|
||||
SubstituteNameOffset uint16
|
||||
SubstituteNameLength uint16
|
||||
PrintNameOffset uint16
|
||||
PrintNameLength uint16
|
||||
}
|
||||
|
||||
// ReparsePoint describes a Win32 symlink or mount point.
|
||||
type ReparsePoint struct {
|
||||
Target string
|
||||
IsMountPoint bool
|
||||
}
|
||||
|
||||
// UnsupportedReparsePointError is returned when trying to decode a non-symlink or
|
||||
// mount point reparse point.
|
||||
type UnsupportedReparsePointError struct {
|
||||
Tag uint32
|
||||
}
|
||||
|
||||
func (e *UnsupportedReparsePointError) Error() string {
|
||||
return fmt.Sprintf("unsupported reparse point %x", e.Tag)
|
||||
}
|
||||
|
||||
// DecodeReparsePoint decodes a Win32 REPARSE_DATA_BUFFER structure containing either a symlink
|
||||
// or a mount point.
|
||||
func DecodeReparsePoint(b []byte) (*ReparsePoint, error) {
|
||||
tag := binary.LittleEndian.Uint32(b[0:4])
|
||||
return DecodeReparsePointData(tag, b[8:])
|
||||
}
|
||||
|
||||
func DecodeReparsePointData(tag uint32, b []byte) (*ReparsePoint, error) {
|
||||
isMountPoint := false
|
||||
switch tag {
|
||||
case reparseTagMountPoint:
|
||||
isMountPoint = true
|
||||
case reparseTagSymlink:
|
||||
default:
|
||||
return nil, &UnsupportedReparsePointError{tag}
|
||||
}
|
||||
nameOffset := 8 + binary.LittleEndian.Uint16(b[4:6])
|
||||
if !isMountPoint {
|
||||
nameOffset += 4
|
||||
}
|
||||
nameLength := binary.LittleEndian.Uint16(b[6:8])
|
||||
name := make([]uint16, nameLength/2)
|
||||
err := binary.Read(bytes.NewReader(b[nameOffset:nameOffset+nameLength]), binary.LittleEndian, &name)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &ReparsePoint{string(utf16.Decode(name)), isMountPoint}, nil
|
||||
}
|
||||
|
||||
func isDriveLetter(c byte) bool {
|
||||
return (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z')
|
||||
}
|
||||
|
||||
// EncodeReparsePoint encodes a Win32 REPARSE_DATA_BUFFER structure describing a symlink or
|
||||
// mount point.
|
||||
func EncodeReparsePoint(rp *ReparsePoint) []byte {
|
||||
// Generate an NT path and determine if this is a relative path.
|
||||
var ntTarget string
|
||||
relative := false
|
||||
if strings.HasPrefix(rp.Target, `\\?\`) {
|
||||
ntTarget = `\??\` + rp.Target[4:]
|
||||
} else if strings.HasPrefix(rp.Target, `\\`) {
|
||||
ntTarget = `\??\UNC\` + rp.Target[2:]
|
||||
} else if len(rp.Target) >= 2 && isDriveLetter(rp.Target[0]) && rp.Target[1] == ':' {
|
||||
ntTarget = `\??\` + rp.Target
|
||||
} else {
|
||||
ntTarget = rp.Target
|
||||
relative = true
|
||||
}
|
||||
|
||||
// The paths must be NUL-terminated even though they are counted strings.
|
||||
target16 := utf16.Encode([]rune(rp.Target + "\x00"))
|
||||
ntTarget16 := utf16.Encode([]rune(ntTarget + "\x00"))
|
||||
|
||||
size := int(unsafe.Sizeof(reparseDataBuffer{})) - 8
|
||||
size += len(ntTarget16)*2 + len(target16)*2
|
||||
|
||||
tag := uint32(reparseTagMountPoint)
|
||||
if !rp.IsMountPoint {
|
||||
tag = reparseTagSymlink
|
||||
size += 4 // Add room for symlink flags
|
||||
}
|
||||
|
||||
data := reparseDataBuffer{
|
||||
ReparseTag: tag,
|
||||
ReparseDataLength: uint16(size),
|
||||
SubstituteNameOffset: 0,
|
||||
SubstituteNameLength: uint16((len(ntTarget16) - 1) * 2),
|
||||
PrintNameOffset: uint16(len(ntTarget16) * 2),
|
||||
PrintNameLength: uint16((len(target16) - 1) * 2),
|
||||
}
|
||||
|
||||
var b bytes.Buffer
|
||||
binary.Write(&b, binary.LittleEndian, &data)
|
||||
if !rp.IsMountPoint {
|
||||
flags := uint32(0)
|
||||
if relative {
|
||||
flags |= 1
|
||||
}
|
||||
binary.Write(&b, binary.LittleEndian, flags)
|
||||
}
|
||||
|
||||
binary.Write(&b, binary.LittleEndian, ntTarget16)
|
||||
binary.Write(&b, binary.LittleEndian, target16)
|
||||
return b.Bytes()
|
||||
}
|
||||
98
vendor/github.com/Microsoft/go-winio/sd.go
generated
vendored
98
vendor/github.com/Microsoft/go-winio/sd.go
generated
vendored
|
|
@ -1,98 +0,0 @@
|
|||
// +build windows
|
||||
|
||||
package winio
|
||||
|
||||
import (
|
||||
"syscall"
|
||||
"unsafe"
|
||||
)
|
||||
|
||||
//sys lookupAccountName(systemName *uint16, accountName string, sid *byte, sidSize *uint32, refDomain *uint16, refDomainSize *uint32, sidNameUse *uint32) (err error) = advapi32.LookupAccountNameW
|
||||
//sys convertSidToStringSid(sid *byte, str **uint16) (err error) = advapi32.ConvertSidToStringSidW
|
||||
//sys convertStringSecurityDescriptorToSecurityDescriptor(str string, revision uint32, sd *uintptr, size *uint32) (err error) = advapi32.ConvertStringSecurityDescriptorToSecurityDescriptorW
|
||||
//sys convertSecurityDescriptorToStringSecurityDescriptor(sd *byte, revision uint32, secInfo uint32, sddl **uint16, sddlSize *uint32) (err error) = advapi32.ConvertSecurityDescriptorToStringSecurityDescriptorW
|
||||
//sys localFree(mem uintptr) = LocalFree
|
||||
//sys getSecurityDescriptorLength(sd uintptr) (len uint32) = advapi32.GetSecurityDescriptorLength
|
||||
|
||||
const (
|
||||
cERROR_NONE_MAPPED = syscall.Errno(1332)
|
||||
)
|
||||
|
||||
type AccountLookupError struct {
|
||||
Name string
|
||||
Err error
|
||||
}
|
||||
|
||||
func (e *AccountLookupError) Error() string {
|
||||
if e.Name == "" {
|
||||
return "lookup account: empty account name specified"
|
||||
}
|
||||
var s string
|
||||
switch e.Err {
|
||||
case cERROR_NONE_MAPPED:
|
||||
s = "not found"
|
||||
default:
|
||||
s = e.Err.Error()
|
||||
}
|
||||
return "lookup account " + e.Name + ": " + s
|
||||
}
|
||||
|
||||
type SddlConversionError struct {
|
||||
Sddl string
|
||||
Err error
|
||||
}
|
||||
|
||||
func (e *SddlConversionError) Error() string {
|
||||
return "convert " + e.Sddl + ": " + e.Err.Error()
|
||||
}
|
||||
|
||||
// LookupSidByName looks up the SID of an account by name
|
||||
func LookupSidByName(name string) (sid string, err error) {
|
||||
if name == "" {
|
||||
return "", &AccountLookupError{name, cERROR_NONE_MAPPED}
|
||||
}
|
||||
|
||||
var sidSize, sidNameUse, refDomainSize uint32
|
||||
err = lookupAccountName(nil, name, nil, &sidSize, nil, &refDomainSize, &sidNameUse)
|
||||
if err != nil && err != syscall.ERROR_INSUFFICIENT_BUFFER {
|
||||
return "", &AccountLookupError{name, err}
|
||||
}
|
||||
sidBuffer := make([]byte, sidSize)
|
||||
refDomainBuffer := make([]uint16, refDomainSize)
|
||||
err = lookupAccountName(nil, name, &sidBuffer[0], &sidSize, &refDomainBuffer[0], &refDomainSize, &sidNameUse)
|
||||
if err != nil {
|
||||
return "", &AccountLookupError{name, err}
|
||||
}
|
||||
var strBuffer *uint16
|
||||
err = convertSidToStringSid(&sidBuffer[0], &strBuffer)
|
||||
if err != nil {
|
||||
return "", &AccountLookupError{name, err}
|
||||
}
|
||||
sid = syscall.UTF16ToString((*[0xffff]uint16)(unsafe.Pointer(strBuffer))[:])
|
||||
localFree(uintptr(unsafe.Pointer(strBuffer)))
|
||||
return sid, nil
|
||||
}
|
||||
|
||||
func SddlToSecurityDescriptor(sddl string) ([]byte, error) {
|
||||
var sdBuffer uintptr
|
||||
err := convertStringSecurityDescriptorToSecurityDescriptor(sddl, 1, &sdBuffer, nil)
|
||||
if err != nil {
|
||||
return nil, &SddlConversionError{sddl, err}
|
||||
}
|
||||
defer localFree(sdBuffer)
|
||||
sd := make([]byte, getSecurityDescriptorLength(sdBuffer))
|
||||
copy(sd, (*[0xffff]byte)(unsafe.Pointer(sdBuffer))[:len(sd)])
|
||||
return sd, nil
|
||||
}
|
||||
|
||||
func SecurityDescriptorToSddl(sd []byte) (string, error) {
|
||||
var sddl *uint16
|
||||
// The returned string length seems to including an aribtrary number of terminating NULs.
|
||||
// Don't use it.
|
||||
err := convertSecurityDescriptorToStringSecurityDescriptor(&sd[0], 1, 0xff, &sddl, nil)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
defer localFree(uintptr(unsafe.Pointer(sddl)))
|
||||
return syscall.UTF16ToString((*[0xffff]uint16)(unsafe.Pointer(sddl))[:]), nil
|
||||
}
|
||||
3
vendor/github.com/Microsoft/go-winio/syscall.go
generated
vendored
3
vendor/github.com/Microsoft/go-winio/syscall.go
generated
vendored
|
|
@ -1,3 +0,0 @@
|
|||
package winio
|
||||
|
||||
//go:generate go run golang.org/x/sys/windows/mkwinsyscall -output zsyscall_windows.go file.go pipe.go sd.go fileinfo.go privilege.go backup.go hvsock.go
|
||||
427
vendor/github.com/Microsoft/go-winio/zsyscall_windows.go
generated
vendored
427
vendor/github.com/Microsoft/go-winio/zsyscall_windows.go
generated
vendored
|
|
@ -1,427 +0,0 @@
|
|||
// Code generated by 'go generate'; DO NOT EDIT.
|
||||
|
||||
package winio
|
||||
|
||||
import (
|
||||
"syscall"
|
||||
"unsafe"
|
||||
|
||||
"golang.org/x/sys/windows"
|
||||
)
|
||||
|
||||
var _ unsafe.Pointer
|
||||
|
||||
// Do the interface allocations only once for common
|
||||
// Errno values.
|
||||
const (
|
||||
errnoERROR_IO_PENDING = 997
|
||||
)
|
||||
|
||||
var (
|
||||
errERROR_IO_PENDING error = syscall.Errno(errnoERROR_IO_PENDING)
|
||||
errERROR_EINVAL error = syscall.EINVAL
|
||||
)
|
||||
|
||||
// errnoErr returns common boxed Errno values, to prevent
|
||||
// allocations at runtime.
|
||||
func errnoErr(e syscall.Errno) error {
|
||||
switch e {
|
||||
case 0:
|
||||
return errERROR_EINVAL
|
||||
case errnoERROR_IO_PENDING:
|
||||
return errERROR_IO_PENDING
|
||||
}
|
||||
// TODO: add more here, after collecting data on the common
|
||||
// error values see on Windows. (perhaps when running
|
||||
// all.bat?)
|
||||
return e
|
||||
}
|
||||
|
||||
var (
|
||||
modadvapi32 = windows.NewLazySystemDLL("advapi32.dll")
|
||||
modkernel32 = windows.NewLazySystemDLL("kernel32.dll")
|
||||
modntdll = windows.NewLazySystemDLL("ntdll.dll")
|
||||
modws2_32 = windows.NewLazySystemDLL("ws2_32.dll")
|
||||
|
||||
procAdjustTokenPrivileges = modadvapi32.NewProc("AdjustTokenPrivileges")
|
||||
procConvertSecurityDescriptorToStringSecurityDescriptorW = modadvapi32.NewProc("ConvertSecurityDescriptorToStringSecurityDescriptorW")
|
||||
procConvertSidToStringSidW = modadvapi32.NewProc("ConvertSidToStringSidW")
|
||||
procConvertStringSecurityDescriptorToSecurityDescriptorW = modadvapi32.NewProc("ConvertStringSecurityDescriptorToSecurityDescriptorW")
|
||||
procGetSecurityDescriptorLength = modadvapi32.NewProc("GetSecurityDescriptorLength")
|
||||
procImpersonateSelf = modadvapi32.NewProc("ImpersonateSelf")
|
||||
procLookupAccountNameW = modadvapi32.NewProc("LookupAccountNameW")
|
||||
procLookupPrivilegeDisplayNameW = modadvapi32.NewProc("LookupPrivilegeDisplayNameW")
|
||||
procLookupPrivilegeNameW = modadvapi32.NewProc("LookupPrivilegeNameW")
|
||||
procLookupPrivilegeValueW = modadvapi32.NewProc("LookupPrivilegeValueW")
|
||||
procOpenThreadToken = modadvapi32.NewProc("OpenThreadToken")
|
||||
procRevertToSelf = modadvapi32.NewProc("RevertToSelf")
|
||||
procBackupRead = modkernel32.NewProc("BackupRead")
|
||||
procBackupWrite = modkernel32.NewProc("BackupWrite")
|
||||
procCancelIoEx = modkernel32.NewProc("CancelIoEx")
|
||||
procConnectNamedPipe = modkernel32.NewProc("ConnectNamedPipe")
|
||||
procCreateFileW = modkernel32.NewProc("CreateFileW")
|
||||
procCreateIoCompletionPort = modkernel32.NewProc("CreateIoCompletionPort")
|
||||
procCreateNamedPipeW = modkernel32.NewProc("CreateNamedPipeW")
|
||||
procGetCurrentThread = modkernel32.NewProc("GetCurrentThread")
|
||||
procGetNamedPipeHandleStateW = modkernel32.NewProc("GetNamedPipeHandleStateW")
|
||||
procGetNamedPipeInfo = modkernel32.NewProc("GetNamedPipeInfo")
|
||||
procGetQueuedCompletionStatus = modkernel32.NewProc("GetQueuedCompletionStatus")
|
||||
procLocalAlloc = modkernel32.NewProc("LocalAlloc")
|
||||
procLocalFree = modkernel32.NewProc("LocalFree")
|
||||
procSetFileCompletionNotificationModes = modkernel32.NewProc("SetFileCompletionNotificationModes")
|
||||
procNtCreateNamedPipeFile = modntdll.NewProc("NtCreateNamedPipeFile")
|
||||
procRtlDefaultNpAcl = modntdll.NewProc("RtlDefaultNpAcl")
|
||||
procRtlDosPathNameToNtPathName_U = modntdll.NewProc("RtlDosPathNameToNtPathName_U")
|
||||
procRtlNtStatusToDosErrorNoTeb = modntdll.NewProc("RtlNtStatusToDosErrorNoTeb")
|
||||
procWSAGetOverlappedResult = modws2_32.NewProc("WSAGetOverlappedResult")
|
||||
procbind = modws2_32.NewProc("bind")
|
||||
)
|
||||
|
||||
func adjustTokenPrivileges(token windows.Token, releaseAll bool, input *byte, outputSize uint32, output *byte, requiredSize *uint32) (success bool, err error) {
|
||||
var _p0 uint32
|
||||
if releaseAll {
|
||||
_p0 = 1
|
||||
}
|
||||
r0, _, e1 := syscall.Syscall6(procAdjustTokenPrivileges.Addr(), 6, uintptr(token), uintptr(_p0), uintptr(unsafe.Pointer(input)), uintptr(outputSize), uintptr(unsafe.Pointer(output)), uintptr(unsafe.Pointer(requiredSize)))
|
||||
success = r0 != 0
|
||||
if true {
|
||||
err = errnoErr(e1)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func convertSecurityDescriptorToStringSecurityDescriptor(sd *byte, revision uint32, secInfo uint32, sddl **uint16, sddlSize *uint32) (err error) {
|
||||
r1, _, e1 := syscall.Syscall6(procConvertSecurityDescriptorToStringSecurityDescriptorW.Addr(), 5, uintptr(unsafe.Pointer(sd)), uintptr(revision), uintptr(secInfo), uintptr(unsafe.Pointer(sddl)), uintptr(unsafe.Pointer(sddlSize)), 0)
|
||||
if r1 == 0 {
|
||||
err = errnoErr(e1)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func convertSidToStringSid(sid *byte, str **uint16) (err error) {
|
||||
r1, _, e1 := syscall.Syscall(procConvertSidToStringSidW.Addr(), 2, uintptr(unsafe.Pointer(sid)), uintptr(unsafe.Pointer(str)), 0)
|
||||
if r1 == 0 {
|
||||
err = errnoErr(e1)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func convertStringSecurityDescriptorToSecurityDescriptor(str string, revision uint32, sd *uintptr, size *uint32) (err error) {
|
||||
var _p0 *uint16
|
||||
_p0, err = syscall.UTF16PtrFromString(str)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
return _convertStringSecurityDescriptorToSecurityDescriptor(_p0, revision, sd, size)
|
||||
}
|
||||
|
||||
func _convertStringSecurityDescriptorToSecurityDescriptor(str *uint16, revision uint32, sd *uintptr, size *uint32) (err error) {
|
||||
r1, _, e1 := syscall.Syscall6(procConvertStringSecurityDescriptorToSecurityDescriptorW.Addr(), 4, uintptr(unsafe.Pointer(str)), uintptr(revision), uintptr(unsafe.Pointer(sd)), uintptr(unsafe.Pointer(size)), 0, 0)
|
||||
if r1 == 0 {
|
||||
err = errnoErr(e1)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func getSecurityDescriptorLength(sd uintptr) (len uint32) {
|
||||
r0, _, _ := syscall.Syscall(procGetSecurityDescriptorLength.Addr(), 1, uintptr(sd), 0, 0)
|
||||
len = uint32(r0)
|
||||
return
|
||||
}
|
||||
|
||||
func impersonateSelf(level uint32) (err error) {
|
||||
r1, _, e1 := syscall.Syscall(procImpersonateSelf.Addr(), 1, uintptr(level), 0, 0)
|
||||
if r1 == 0 {
|
||||
err = errnoErr(e1)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func lookupAccountName(systemName *uint16, accountName string, sid *byte, sidSize *uint32, refDomain *uint16, refDomainSize *uint32, sidNameUse *uint32) (err error) {
|
||||
var _p0 *uint16
|
||||
_p0, err = syscall.UTF16PtrFromString(accountName)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
return _lookupAccountName(systemName, _p0, sid, sidSize, refDomain, refDomainSize, sidNameUse)
|
||||
}
|
||||
|
||||
func _lookupAccountName(systemName *uint16, accountName *uint16, sid *byte, sidSize *uint32, refDomain *uint16, refDomainSize *uint32, sidNameUse *uint32) (err error) {
|
||||
r1, _, e1 := syscall.Syscall9(procLookupAccountNameW.Addr(), 7, uintptr(unsafe.Pointer(systemName)), uintptr(unsafe.Pointer(accountName)), uintptr(unsafe.Pointer(sid)), uintptr(unsafe.Pointer(sidSize)), uintptr(unsafe.Pointer(refDomain)), uintptr(unsafe.Pointer(refDomainSize)), uintptr(unsafe.Pointer(sidNameUse)), 0, 0)
|
||||
if r1 == 0 {
|
||||
err = errnoErr(e1)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func lookupPrivilegeDisplayName(systemName string, name *uint16, buffer *uint16, size *uint32, languageId *uint32) (err error) {
|
||||
var _p0 *uint16
|
||||
_p0, err = syscall.UTF16PtrFromString(systemName)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
return _lookupPrivilegeDisplayName(_p0, name, buffer, size, languageId)
|
||||
}
|
||||
|
||||
func _lookupPrivilegeDisplayName(systemName *uint16, name *uint16, buffer *uint16, size *uint32, languageId *uint32) (err error) {
|
||||
r1, _, e1 := syscall.Syscall6(procLookupPrivilegeDisplayNameW.Addr(), 5, uintptr(unsafe.Pointer(systemName)), uintptr(unsafe.Pointer(name)), uintptr(unsafe.Pointer(buffer)), uintptr(unsafe.Pointer(size)), uintptr(unsafe.Pointer(languageId)), 0)
|
||||
if r1 == 0 {
|
||||
err = errnoErr(e1)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func lookupPrivilegeName(systemName string, luid *uint64, buffer *uint16, size *uint32) (err error) {
|
||||
var _p0 *uint16
|
||||
_p0, err = syscall.UTF16PtrFromString(systemName)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
return _lookupPrivilegeName(_p0, luid, buffer, size)
|
||||
}
|
||||
|
||||
func _lookupPrivilegeName(systemName *uint16, luid *uint64, buffer *uint16, size *uint32) (err error) {
|
||||
r1, _, e1 := syscall.Syscall6(procLookupPrivilegeNameW.Addr(), 4, uintptr(unsafe.Pointer(systemName)), uintptr(unsafe.Pointer(luid)), uintptr(unsafe.Pointer(buffer)), uintptr(unsafe.Pointer(size)), 0, 0)
|
||||
if r1 == 0 {
|
||||
err = errnoErr(e1)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func lookupPrivilegeValue(systemName string, name string, luid *uint64) (err error) {
|
||||
var _p0 *uint16
|
||||
_p0, err = syscall.UTF16PtrFromString(systemName)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
var _p1 *uint16
|
||||
_p1, err = syscall.UTF16PtrFromString(name)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
return _lookupPrivilegeValue(_p0, _p1, luid)
|
||||
}
|
||||
|
||||
func _lookupPrivilegeValue(systemName *uint16, name *uint16, luid *uint64) (err error) {
|
||||
r1, _, e1 := syscall.Syscall(procLookupPrivilegeValueW.Addr(), 3, uintptr(unsafe.Pointer(systemName)), uintptr(unsafe.Pointer(name)), uintptr(unsafe.Pointer(luid)))
|
||||
if r1 == 0 {
|
||||
err = errnoErr(e1)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func openThreadToken(thread syscall.Handle, accessMask uint32, openAsSelf bool, token *windows.Token) (err error) {
|
||||
var _p0 uint32
|
||||
if openAsSelf {
|
||||
_p0 = 1
|
||||
}
|
||||
r1, _, e1 := syscall.Syscall6(procOpenThreadToken.Addr(), 4, uintptr(thread), uintptr(accessMask), uintptr(_p0), uintptr(unsafe.Pointer(token)), 0, 0)
|
||||
if r1 == 0 {
|
||||
err = errnoErr(e1)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func revertToSelf() (err error) {
|
||||
r1, _, e1 := syscall.Syscall(procRevertToSelf.Addr(), 0, 0, 0, 0)
|
||||
if r1 == 0 {
|
||||
err = errnoErr(e1)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func backupRead(h syscall.Handle, b []byte, bytesRead *uint32, abort bool, processSecurity bool, context *uintptr) (err error) {
|
||||
var _p0 *byte
|
||||
if len(b) > 0 {
|
||||
_p0 = &b[0]
|
||||
}
|
||||
var _p1 uint32
|
||||
if abort {
|
||||
_p1 = 1
|
||||
}
|
||||
var _p2 uint32
|
||||
if processSecurity {
|
||||
_p2 = 1
|
||||
}
|
||||
r1, _, e1 := syscall.Syscall9(procBackupRead.Addr(), 7, uintptr(h), uintptr(unsafe.Pointer(_p0)), uintptr(len(b)), uintptr(unsafe.Pointer(bytesRead)), uintptr(_p1), uintptr(_p2), uintptr(unsafe.Pointer(context)), 0, 0)
|
||||
if r1 == 0 {
|
||||
err = errnoErr(e1)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func backupWrite(h syscall.Handle, b []byte, bytesWritten *uint32, abort bool, processSecurity bool, context *uintptr) (err error) {
|
||||
var _p0 *byte
|
||||
if len(b) > 0 {
|
||||
_p0 = &b[0]
|
||||
}
|
||||
var _p1 uint32
|
||||
if abort {
|
||||
_p1 = 1
|
||||
}
|
||||
var _p2 uint32
|
||||
if processSecurity {
|
||||
_p2 = 1
|
||||
}
|
||||
r1, _, e1 := syscall.Syscall9(procBackupWrite.Addr(), 7, uintptr(h), uintptr(unsafe.Pointer(_p0)), uintptr(len(b)), uintptr(unsafe.Pointer(bytesWritten)), uintptr(_p1), uintptr(_p2), uintptr(unsafe.Pointer(context)), 0, 0)
|
||||
if r1 == 0 {
|
||||
err = errnoErr(e1)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func cancelIoEx(file syscall.Handle, o *syscall.Overlapped) (err error) {
|
||||
r1, _, e1 := syscall.Syscall(procCancelIoEx.Addr(), 2, uintptr(file), uintptr(unsafe.Pointer(o)), 0)
|
||||
if r1 == 0 {
|
||||
err = errnoErr(e1)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func connectNamedPipe(pipe syscall.Handle, o *syscall.Overlapped) (err error) {
|
||||
r1, _, e1 := syscall.Syscall(procConnectNamedPipe.Addr(), 2, uintptr(pipe), uintptr(unsafe.Pointer(o)), 0)
|
||||
if r1 == 0 {
|
||||
err = errnoErr(e1)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func createFile(name string, access uint32, mode uint32, sa *syscall.SecurityAttributes, createmode uint32, attrs uint32, templatefile syscall.Handle) (handle syscall.Handle, err error) {
|
||||
var _p0 *uint16
|
||||
_p0, err = syscall.UTF16PtrFromString(name)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
return _createFile(_p0, access, mode, sa, createmode, attrs, templatefile)
|
||||
}
|
||||
|
||||
func _createFile(name *uint16, access uint32, mode uint32, sa *syscall.SecurityAttributes, createmode uint32, attrs uint32, templatefile syscall.Handle) (handle syscall.Handle, err error) {
|
||||
r0, _, e1 := syscall.Syscall9(procCreateFileW.Addr(), 7, uintptr(unsafe.Pointer(name)), uintptr(access), uintptr(mode), uintptr(unsafe.Pointer(sa)), uintptr(createmode), uintptr(attrs), uintptr(templatefile), 0, 0)
|
||||
handle = syscall.Handle(r0)
|
||||
if handle == syscall.InvalidHandle {
|
||||
err = errnoErr(e1)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func createIoCompletionPort(file syscall.Handle, port syscall.Handle, key uintptr, threadCount uint32) (newport syscall.Handle, err error) {
|
||||
r0, _, e1 := syscall.Syscall6(procCreateIoCompletionPort.Addr(), 4, uintptr(file), uintptr(port), uintptr(key), uintptr(threadCount), 0, 0)
|
||||
newport = syscall.Handle(r0)
|
||||
if newport == 0 {
|
||||
err = errnoErr(e1)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func createNamedPipe(name string, flags uint32, pipeMode uint32, maxInstances uint32, outSize uint32, inSize uint32, defaultTimeout uint32, sa *syscall.SecurityAttributes) (handle syscall.Handle, err error) {
|
||||
var _p0 *uint16
|
||||
_p0, err = syscall.UTF16PtrFromString(name)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
return _createNamedPipe(_p0, flags, pipeMode, maxInstances, outSize, inSize, defaultTimeout, sa)
|
||||
}
|
||||
|
||||
func _createNamedPipe(name *uint16, flags uint32, pipeMode uint32, maxInstances uint32, outSize uint32, inSize uint32, defaultTimeout uint32, sa *syscall.SecurityAttributes) (handle syscall.Handle, err error) {
|
||||
r0, _, e1 := syscall.Syscall9(procCreateNamedPipeW.Addr(), 8, uintptr(unsafe.Pointer(name)), uintptr(flags), uintptr(pipeMode), uintptr(maxInstances), uintptr(outSize), uintptr(inSize), uintptr(defaultTimeout), uintptr(unsafe.Pointer(sa)), 0)
|
||||
handle = syscall.Handle(r0)
|
||||
if handle == syscall.InvalidHandle {
|
||||
err = errnoErr(e1)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func getCurrentThread() (h syscall.Handle) {
|
||||
r0, _, _ := syscall.Syscall(procGetCurrentThread.Addr(), 0, 0, 0, 0)
|
||||
h = syscall.Handle(r0)
|
||||
return
|
||||
}
|
||||
|
||||
func getNamedPipeHandleState(pipe syscall.Handle, state *uint32, curInstances *uint32, maxCollectionCount *uint32, collectDataTimeout *uint32, userName *uint16, maxUserNameSize uint32) (err error) {
|
||||
r1, _, e1 := syscall.Syscall9(procGetNamedPipeHandleStateW.Addr(), 7, uintptr(pipe), uintptr(unsafe.Pointer(state)), uintptr(unsafe.Pointer(curInstances)), uintptr(unsafe.Pointer(maxCollectionCount)), uintptr(unsafe.Pointer(collectDataTimeout)), uintptr(unsafe.Pointer(userName)), uintptr(maxUserNameSize), 0, 0)
|
||||
if r1 == 0 {
|
||||
err = errnoErr(e1)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func getNamedPipeInfo(pipe syscall.Handle, flags *uint32, outSize *uint32, inSize *uint32, maxInstances *uint32) (err error) {
|
||||
r1, _, e1 := syscall.Syscall6(procGetNamedPipeInfo.Addr(), 5, uintptr(pipe), uintptr(unsafe.Pointer(flags)), uintptr(unsafe.Pointer(outSize)), uintptr(unsafe.Pointer(inSize)), uintptr(unsafe.Pointer(maxInstances)), 0)
|
||||
if r1 == 0 {
|
||||
err = errnoErr(e1)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func getQueuedCompletionStatus(port syscall.Handle, bytes *uint32, key *uintptr, o **ioOperation, timeout uint32) (err error) {
|
||||
r1, _, e1 := syscall.Syscall6(procGetQueuedCompletionStatus.Addr(), 5, uintptr(port), uintptr(unsafe.Pointer(bytes)), uintptr(unsafe.Pointer(key)), uintptr(unsafe.Pointer(o)), uintptr(timeout), 0)
|
||||
if r1 == 0 {
|
||||
err = errnoErr(e1)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func localAlloc(uFlags uint32, length uint32) (ptr uintptr) {
|
||||
r0, _, _ := syscall.Syscall(procLocalAlloc.Addr(), 2, uintptr(uFlags), uintptr(length), 0)
|
||||
ptr = uintptr(r0)
|
||||
return
|
||||
}
|
||||
|
||||
func localFree(mem uintptr) {
|
||||
syscall.Syscall(procLocalFree.Addr(), 1, uintptr(mem), 0, 0)
|
||||
return
|
||||
}
|
||||
|
||||
func setFileCompletionNotificationModes(h syscall.Handle, flags uint8) (err error) {
|
||||
r1, _, e1 := syscall.Syscall(procSetFileCompletionNotificationModes.Addr(), 2, uintptr(h), uintptr(flags), 0)
|
||||
if r1 == 0 {
|
||||
err = errnoErr(e1)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func ntCreateNamedPipeFile(pipe *syscall.Handle, access uint32, oa *objectAttributes, iosb *ioStatusBlock, share uint32, disposition uint32, options uint32, typ uint32, readMode uint32, completionMode uint32, maxInstances uint32, inboundQuota uint32, outputQuota uint32, timeout *int64) (status ntstatus) {
|
||||
r0, _, _ := syscall.Syscall15(procNtCreateNamedPipeFile.Addr(), 14, uintptr(unsafe.Pointer(pipe)), uintptr(access), uintptr(unsafe.Pointer(oa)), uintptr(unsafe.Pointer(iosb)), uintptr(share), uintptr(disposition), uintptr(options), uintptr(typ), uintptr(readMode), uintptr(completionMode), uintptr(maxInstances), uintptr(inboundQuota), uintptr(outputQuota), uintptr(unsafe.Pointer(timeout)), 0)
|
||||
status = ntstatus(r0)
|
||||
return
|
||||
}
|
||||
|
||||
func rtlDefaultNpAcl(dacl *uintptr) (status ntstatus) {
|
||||
r0, _, _ := syscall.Syscall(procRtlDefaultNpAcl.Addr(), 1, uintptr(unsafe.Pointer(dacl)), 0, 0)
|
||||
status = ntstatus(r0)
|
||||
return
|
||||
}
|
||||
|
||||
func rtlDosPathNameToNtPathName(name *uint16, ntName *unicodeString, filePart uintptr, reserved uintptr) (status ntstatus) {
|
||||
r0, _, _ := syscall.Syscall6(procRtlDosPathNameToNtPathName_U.Addr(), 4, uintptr(unsafe.Pointer(name)), uintptr(unsafe.Pointer(ntName)), uintptr(filePart), uintptr(reserved), 0, 0)
|
||||
status = ntstatus(r0)
|
||||
return
|
||||
}
|
||||
|
||||
func rtlNtStatusToDosError(status ntstatus) (winerr error) {
|
||||
r0, _, _ := syscall.Syscall(procRtlNtStatusToDosErrorNoTeb.Addr(), 1, uintptr(status), 0, 0)
|
||||
if r0 != 0 {
|
||||
winerr = syscall.Errno(r0)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func wsaGetOverlappedResult(h syscall.Handle, o *syscall.Overlapped, bytes *uint32, wait bool, flags *uint32) (err error) {
|
||||
var _p0 uint32
|
||||
if wait {
|
||||
_p0 = 1
|
||||
}
|
||||
r1, _, e1 := syscall.Syscall6(procWSAGetOverlappedResult.Addr(), 5, uintptr(h), uintptr(unsafe.Pointer(o)), uintptr(unsafe.Pointer(bytes)), uintptr(_p0), uintptr(unsafe.Pointer(flags)), 0)
|
||||
if r1 == 0 {
|
||||
err = errnoErr(e1)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func bind(s syscall.Handle, name unsafe.Pointer, namelen int32) (err error) {
|
||||
r1, _, e1 := syscall.Syscall(procbind.Addr(), 3, uintptr(s), uintptr(name), uintptr(namelen))
|
||||
if r1 == socketError {
|
||||
err = errnoErr(e1)
|
||||
}
|
||||
return
|
||||
}
|
||||
15
vendor/github.com/asaskevich/govalidator/.gitignore
generated
vendored
Normal file
15
vendor/github.com/asaskevich/govalidator/.gitignore
generated
vendored
Normal file
|
|
@ -0,0 +1,15 @@
|
|||
bin/
|
||||
.idea/
|
||||
# Binaries for programs and plugins
|
||||
*.exe
|
||||
*.exe~
|
||||
*.dll
|
||||
*.so
|
||||
*.dylib
|
||||
|
||||
# Test binary, built with `go test -c`
|
||||
*.test
|
||||
|
||||
# Output of the go coverage tool, specifically when used with LiteIDE
|
||||
*.out
|
||||
|
||||
12
vendor/github.com/asaskevich/govalidator/.travis.yml
generated
vendored
Normal file
12
vendor/github.com/asaskevich/govalidator/.travis.yml
generated
vendored
Normal file
|
|
@ -0,0 +1,12 @@
|
|||
language: go
|
||||
dist: xenial
|
||||
go:
|
||||
- '1.10'
|
||||
- '1.11'
|
||||
- '1.12'
|
||||
- '1.13'
|
||||
- 'tip'
|
||||
|
||||
script:
|
||||
- go test -coverpkg=./... -coverprofile=coverage.info -timeout=5s
|
||||
- bash <(curl -s https://codecov.io/bash)
|
||||
43
vendor/github.com/asaskevich/govalidator/CODE_OF_CONDUCT.md
generated
vendored
Normal file
43
vendor/github.com/asaskevich/govalidator/CODE_OF_CONDUCT.md
generated
vendored
Normal file
|
|
@ -0,0 +1,43 @@
|
|||
# Contributor Code of Conduct
|
||||
|
||||
This project adheres to [The Code Manifesto](http://codemanifesto.com)
|
||||
as its guidelines for contributor interactions.
|
||||
|
||||
## The Code Manifesto
|
||||
|
||||
We want to work in an ecosystem that empowers developers to reach their
|
||||
potential — one that encourages growth and effective collaboration. A space
|
||||
that is safe for all.
|
||||
|
||||
A space such as this benefits everyone that participates in it. It encourages
|
||||
new developers to enter our field. It is through discussion and collaboration
|
||||
that we grow, and through growth that we improve.
|
||||
|
||||
In the effort to create such a place, we hold to these values:
|
||||
|
||||
1. **Discrimination limits us.** This includes discrimination on the basis of
|
||||
race, gender, sexual orientation, gender identity, age, nationality,
|
||||
technology and any other arbitrary exclusion of a group of people.
|
||||
2. **Boundaries honor us.** Your comfort levels are not everyone’s comfort
|
||||
levels. Remember that, and if brought to your attention, heed it.
|
||||
3. **We are our biggest assets.** None of us were born masters of our trade.
|
||||
Each of us has been helped along the way. Return that favor, when and where
|
||||
you can.
|
||||
4. **We are resources for the future.** As an extension of #3, share what you
|
||||
know. Make yourself a resource to help those that come after you.
|
||||
5. **Respect defines us.** Treat others as you wish to be treated. Make your
|
||||
discussions, criticisms and debates from a position of respectfulness. Ask
|
||||
yourself, is it true? Is it necessary? Is it constructive? Anything less is
|
||||
unacceptable.
|
||||
6. **Reactions require grace.** Angry responses are valid, but abusive language
|
||||
and vindictive actions are toxic. When something happens that offends you,
|
||||
handle it assertively, but be respectful. Escalate reasonably, and try to
|
||||
allow the offender an opportunity to explain themselves, and possibly
|
||||
correct the issue.
|
||||
7. **Opinions are just that: opinions.** Each and every one of us, due to our
|
||||
background and upbringing, have varying opinions. That is perfectly
|
||||
acceptable. Remember this: if you respect your own opinions, you should
|
||||
respect the opinions of others.
|
||||
8. **To err is human.** You might not intend it, but mistakes do happen and
|
||||
contribute to build experience. Tolerate honest mistakes, and don't
|
||||
hesitate to apologize if you make one yourself.
|
||||
63
vendor/github.com/asaskevich/govalidator/CONTRIBUTING.md
generated
vendored
Normal file
63
vendor/github.com/asaskevich/govalidator/CONTRIBUTING.md
generated
vendored
Normal file
|
|
@ -0,0 +1,63 @@
|
|||
#### Support
|
||||
If you do have a contribution to the package, feel free to create a Pull Request or an Issue.
|
||||
|
||||
#### What to contribute
|
||||
If you don't know what to do, there are some features and functions that need to be done
|
||||
|
||||
- [ ] Refactor code
|
||||
- [ ] Edit docs and [README](https://github.com/asaskevich/govalidator/README.md): spellcheck, grammar and typo check
|
||||
- [ ] Create actual list of contributors and projects that currently using this package
|
||||
- [ ] Resolve [issues and bugs](https://github.com/asaskevich/govalidator/issues)
|
||||
- [ ] Update actual [list of functions](https://github.com/asaskevich/govalidator#list-of-functions)
|
||||
- [ ] Update [list of validators](https://github.com/asaskevich/govalidator#validatestruct-2) that available for `ValidateStruct` and add new
|
||||
- [ ] Implement new validators: `IsFQDN`, `IsIMEI`, `IsPostalCode`, `IsISIN`, `IsISRC` etc
|
||||
- [x] Implement [validation by maps](https://github.com/asaskevich/govalidator/issues/224)
|
||||
- [ ] Implement fuzzing testing
|
||||
- [ ] Implement some struct/map/array utilities
|
||||
- [ ] Implement map/array validation
|
||||
- [ ] Implement benchmarking
|
||||
- [ ] Implement batch of examples
|
||||
- [ ] Look at forks for new features and fixes
|
||||
|
||||
#### Advice
|
||||
Feel free to create what you want, but keep in mind when you implement new features:
|
||||
- Code must be clear and readable, names of variables/constants clearly describes what they are doing
|
||||
- Public functions must be documented and described in source file and added to README.md to the list of available functions
|
||||
- There are must be unit-tests for any new functions and improvements
|
||||
|
||||
## Financial contributions
|
||||
|
||||
We also welcome financial contributions in full transparency on our [open collective](https://opencollective.com/govalidator).
|
||||
Anyone can file an expense. If the expense makes sense for the development of the community, it will be "merged" in the ledger of our open collective by the core contributors and the person who filed the expense will be reimbursed.
|
||||
|
||||
|
||||
## Credits
|
||||
|
||||
|
||||
### Contributors
|
||||
|
||||
Thank you to all the people who have already contributed to govalidator!
|
||||
<a href="https://github.com/asaskevich/govalidator/graphs/contributors"><img src="https://opencollective.com/govalidator/contributors.svg?width=890" /></a>
|
||||
|
||||
|
||||
### Backers
|
||||
|
||||
Thank you to all our backers! [[Become a backer](https://opencollective.com/govalidator#backer)]
|
||||
|
||||
<a href="https://opencollective.com/govalidator#backers" target="_blank"><img src="https://opencollective.com/govalidator/backers.svg?width=890"></a>
|
||||
|
||||
|
||||
### Sponsors
|
||||
|
||||
Thank you to all our sponsors! (please ask your company to also support this open source project by [becoming a sponsor](https://opencollective.com/govalidator#sponsor))
|
||||
|
||||
<a href="https://opencollective.com/govalidator/sponsor/0/website" target="_blank"><img src="https://opencollective.com/govalidator/sponsor/0/avatar.svg"></a>
|
||||
<a href="https://opencollective.com/govalidator/sponsor/1/website" target="_blank"><img src="https://opencollective.com/govalidator/sponsor/1/avatar.svg"></a>
|
||||
<a href="https://opencollective.com/govalidator/sponsor/2/website" target="_blank"><img src="https://opencollective.com/govalidator/sponsor/2/avatar.svg"></a>
|
||||
<a href="https://opencollective.com/govalidator/sponsor/3/website" target="_blank"><img src="https://opencollective.com/govalidator/sponsor/3/avatar.svg"></a>
|
||||
<a href="https://opencollective.com/govalidator/sponsor/4/website" target="_blank"><img src="https://opencollective.com/govalidator/sponsor/4/avatar.svg"></a>
|
||||
<a href="https://opencollective.com/govalidator/sponsor/5/website" target="_blank"><img src="https://opencollective.com/govalidator/sponsor/5/avatar.svg"></a>
|
||||
<a href="https://opencollective.com/govalidator/sponsor/6/website" target="_blank"><img src="https://opencollective.com/govalidator/sponsor/6/avatar.svg"></a>
|
||||
<a href="https://opencollective.com/govalidator/sponsor/7/website" target="_blank"><img src="https://opencollective.com/govalidator/sponsor/7/avatar.svg"></a>
|
||||
<a href="https://opencollective.com/govalidator/sponsor/8/website" target="_blank"><img src="https://opencollective.com/govalidator/sponsor/8/avatar.svg"></a>
|
||||
<a href="https://opencollective.com/govalidator/sponsor/9/website" target="_blank"><img src="https://opencollective.com/govalidator/sponsor/9/avatar.svg"></a>
|
||||
|
|
@ -1,6 +1,6 @@
|
|||
The MIT License (MIT)
|
||||
|
||||
Copyright (c) 2015 Microsoft
|
||||
Copyright (c) 2014-2020 Alex Saskevich
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
|
|
@ -18,5 +18,4 @@ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
|
||||
SOFTWARE.
|
||||
622
vendor/github.com/asaskevich/govalidator/README.md
generated
vendored
Normal file
622
vendor/github.com/asaskevich/govalidator/README.md
generated
vendored
Normal file
|
|
@ -0,0 +1,622 @@
|
|||
govalidator
|
||||
===========
|
||||
[](https://gitter.im/asaskevich/govalidator?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge) [](https://godoc.org/github.com/asaskevich/govalidator)
|
||||
[](https://travis-ci.org/asaskevich/govalidator)
|
||||
[](https://codecov.io/gh/asaskevich/govalidator) [](https://goreportcard.com/report/github.com/asaskevich/govalidator) [](http://go-search.org/view?id=github.com%2Fasaskevich%2Fgovalidator) [](#backers) [](#sponsors) [](https://app.fossa.io/projects/git%2Bgithub.com%2Fasaskevich%2Fgovalidator?ref=badge_shield)
|
||||
|
||||
A package of validators and sanitizers for strings, structs and collections. Based on [validator.js](https://github.com/chriso/validator.js).
|
||||
|
||||
#### Installation
|
||||
Make sure that Go is installed on your computer.
|
||||
Type the following command in your terminal:
|
||||
|
||||
go get github.com/asaskevich/govalidator
|
||||
|
||||
or you can get specified release of the package with `gopkg.in`:
|
||||
|
||||
go get gopkg.in/asaskevich/govalidator.v10
|
||||
|
||||
After it the package is ready to use.
|
||||
|
||||
|
||||
#### Import package in your project
|
||||
Add following line in your `*.go` file:
|
||||
```go
|
||||
import "github.com/asaskevich/govalidator"
|
||||
```
|
||||
If you are unhappy to use long `govalidator`, you can do something like this:
|
||||
```go
|
||||
import (
|
||||
valid "github.com/asaskevich/govalidator"
|
||||
)
|
||||
```
|
||||
|
||||
#### Activate behavior to require all fields have a validation tag by default
|
||||
`SetFieldsRequiredByDefault` causes validation to fail when struct fields do not include validations or are not explicitly marked as exempt (using `valid:"-"` or `valid:"email,optional"`). A good place to activate this is a package init function or the main() function.
|
||||
|
||||
`SetNilPtrAllowedByRequired` causes validation to pass when struct fields marked by `required` are set to nil. This is disabled by default for consistency, but some packages that need to be able to determine between `nil` and `zero value` state can use this. If disabled, both `nil` and `zero` values cause validation errors.
|
||||
|
||||
```go
|
||||
import "github.com/asaskevich/govalidator"
|
||||
|
||||
func init() {
|
||||
govalidator.SetFieldsRequiredByDefault(true)
|
||||
}
|
||||
```
|
||||
|
||||
Here's some code to explain it:
|
||||
```go
|
||||
// this struct definition will fail govalidator.ValidateStruct() (and the field values do not matter):
|
||||
type exampleStruct struct {
|
||||
Name string ``
|
||||
Email string `valid:"email"`
|
||||
}
|
||||
|
||||
// this, however, will only fail when Email is empty or an invalid email address:
|
||||
type exampleStruct2 struct {
|
||||
Name string `valid:"-"`
|
||||
Email string `valid:"email"`
|
||||
}
|
||||
|
||||
// lastly, this will only fail when Email is an invalid email address but not when it's empty:
|
||||
type exampleStruct2 struct {
|
||||
Name string `valid:"-"`
|
||||
Email string `valid:"email,optional"`
|
||||
}
|
||||
```
|
||||
|
||||
#### Recent breaking changes (see [#123](https://github.com/asaskevich/govalidator/pull/123))
|
||||
##### Custom validator function signature
|
||||
A context was added as the second parameter, for structs this is the object being validated – this makes dependent validation possible.
|
||||
```go
|
||||
import "github.com/asaskevich/govalidator"
|
||||
|
||||
// old signature
|
||||
func(i interface{}) bool
|
||||
|
||||
// new signature
|
||||
func(i interface{}, o interface{}) bool
|
||||
```
|
||||
|
||||
##### Adding a custom validator
|
||||
This was changed to prevent data races when accessing custom validators.
|
||||
```go
|
||||
import "github.com/asaskevich/govalidator"
|
||||
|
||||
// before
|
||||
govalidator.CustomTypeTagMap["customByteArrayValidator"] = func(i interface{}, o interface{}) bool {
|
||||
// ...
|
||||
}
|
||||
|
||||
// after
|
||||
govalidator.CustomTypeTagMap.Set("customByteArrayValidator", func(i interface{}, o interface{}) bool {
|
||||
// ...
|
||||
})
|
||||
```
|
||||
|
||||
#### List of functions:
|
||||
```go
|
||||
func Abs(value float64) float64
|
||||
func BlackList(str, chars string) string
|
||||
func ByteLength(str string, params ...string) bool
|
||||
func CamelCaseToUnderscore(str string) string
|
||||
func Contains(str, substring string) bool
|
||||
func Count(array []interface{}, iterator ConditionIterator) int
|
||||
func Each(array []interface{}, iterator Iterator)
|
||||
func ErrorByField(e error, field string) string
|
||||
func ErrorsByField(e error) map[string]string
|
||||
func Filter(array []interface{}, iterator ConditionIterator) []interface{}
|
||||
func Find(array []interface{}, iterator ConditionIterator) interface{}
|
||||
func GetLine(s string, index int) (string, error)
|
||||
func GetLines(s string) []string
|
||||
func HasLowerCase(str string) bool
|
||||
func HasUpperCase(str string) bool
|
||||
func HasWhitespace(str string) bool
|
||||
func HasWhitespaceOnly(str string) bool
|
||||
func InRange(value interface{}, left interface{}, right interface{}) bool
|
||||
func InRangeFloat32(value, left, right float32) bool
|
||||
func InRangeFloat64(value, left, right float64) bool
|
||||
func InRangeInt(value, left, right interface{}) bool
|
||||
func IsASCII(str string) bool
|
||||
func IsAlpha(str string) bool
|
||||
func IsAlphanumeric(str string) bool
|
||||
func IsBase64(str string) bool
|
||||
func IsByteLength(str string, min, max int) bool
|
||||
func IsCIDR(str string) bool
|
||||
func IsCRC32(str string) bool
|
||||
func IsCRC32b(str string) bool
|
||||
func IsCreditCard(str string) bool
|
||||
func IsDNSName(str string) bool
|
||||
func IsDataURI(str string) bool
|
||||
func IsDialString(str string) bool
|
||||
func IsDivisibleBy(str, num string) bool
|
||||
func IsEmail(str string) bool
|
||||
func IsExistingEmail(email string) bool
|
||||
func IsFilePath(str string) (bool, int)
|
||||
func IsFloat(str string) bool
|
||||
func IsFullWidth(str string) bool
|
||||
func IsHalfWidth(str string) bool
|
||||
func IsHash(str string, algorithm string) bool
|
||||
func IsHexadecimal(str string) bool
|
||||
func IsHexcolor(str string) bool
|
||||
func IsHost(str string) bool
|
||||
func IsIP(str string) bool
|
||||
func IsIPv4(str string) bool
|
||||
func IsIPv6(str string) bool
|
||||
func IsISBN(str string, version int) bool
|
||||
func IsISBN10(str string) bool
|
||||
func IsISBN13(str string) bool
|
||||
func IsISO3166Alpha2(str string) bool
|
||||
func IsISO3166Alpha3(str string) bool
|
||||
func IsISO4217(str string) bool
|
||||
func IsISO693Alpha2(str string) bool
|
||||
func IsISO693Alpha3b(str string) bool
|
||||
func IsIn(str string, params ...string) bool
|
||||
func IsInRaw(str string, params ...string) bool
|
||||
func IsInt(str string) bool
|
||||
func IsJSON(str string) bool
|
||||
func IsLatitude(str string) bool
|
||||
func IsLongitude(str string) bool
|
||||
func IsLowerCase(str string) bool
|
||||
func IsMAC(str string) bool
|
||||
func IsMD4(str string) bool
|
||||
func IsMD5(str string) bool
|
||||
func IsMagnetURI(str string) bool
|
||||
func IsMongoID(str string) bool
|
||||
func IsMultibyte(str string) bool
|
||||
func IsNatural(value float64) bool
|
||||
func IsNegative(value float64) bool
|
||||
func IsNonNegative(value float64) bool
|
||||
func IsNonPositive(value float64) bool
|
||||
func IsNotNull(str string) bool
|
||||
func IsNull(str string) bool
|
||||
func IsNumeric(str string) bool
|
||||
func IsPort(str string) bool
|
||||
func IsPositive(value float64) bool
|
||||
func IsPrintableASCII(str string) bool
|
||||
func IsRFC3339(str string) bool
|
||||
func IsRFC3339WithoutZone(str string) bool
|
||||
func IsRGBcolor(str string) bool
|
||||
func IsRegex(str string) bool
|
||||
func IsRequestURI(rawurl string) bool
|
||||
func IsRequestURL(rawurl string) bool
|
||||
func IsRipeMD128(str string) bool
|
||||
func IsRipeMD160(str string) bool
|
||||
func IsRsaPub(str string, params ...string) bool
|
||||
func IsRsaPublicKey(str string, keylen int) bool
|
||||
func IsSHA1(str string) bool
|
||||
func IsSHA256(str string) bool
|
||||
func IsSHA384(str string) bool
|
||||
func IsSHA512(str string) bool
|
||||
func IsSSN(str string) bool
|
||||
func IsSemver(str string) bool
|
||||
func IsTiger128(str string) bool
|
||||
func IsTiger160(str string) bool
|
||||
func IsTiger192(str string) bool
|
||||
func IsTime(str string, format string) bool
|
||||
func IsType(v interface{}, params ...string) bool
|
||||
func IsURL(str string) bool
|
||||
func IsUTFDigit(str string) bool
|
||||
func IsUTFLetter(str string) bool
|
||||
func IsUTFLetterNumeric(str string) bool
|
||||
func IsUTFNumeric(str string) bool
|
||||
func IsUUID(str string) bool
|
||||
func IsUUIDv3(str string) bool
|
||||
func IsUUIDv4(str string) bool
|
||||
func IsUUIDv5(str string) bool
|
||||
func IsULID(str string) bool
|
||||
func IsUnixTime(str string) bool
|
||||
func IsUpperCase(str string) bool
|
||||
func IsVariableWidth(str string) bool
|
||||
func IsWhole(value float64) bool
|
||||
func LeftTrim(str, chars string) string
|
||||
func Map(array []interface{}, iterator ResultIterator) []interface{}
|
||||
func Matches(str, pattern string) bool
|
||||
func MaxStringLength(str string, params ...string) bool
|
||||
func MinStringLength(str string, params ...string) bool
|
||||
func NormalizeEmail(str string) (string, error)
|
||||
func PadBoth(str string, padStr string, padLen int) string
|
||||
func PadLeft(str string, padStr string, padLen int) string
|
||||
func PadRight(str string, padStr string, padLen int) string
|
||||
func PrependPathToErrors(err error, path string) error
|
||||
func Range(str string, params ...string) bool
|
||||
func RemoveTags(s string) string
|
||||
func ReplacePattern(str, pattern, replace string) string
|
||||
func Reverse(s string) string
|
||||
func RightTrim(str, chars string) string
|
||||
func RuneLength(str string, params ...string) bool
|
||||
func SafeFileName(str string) string
|
||||
func SetFieldsRequiredByDefault(value bool)
|
||||
func SetNilPtrAllowedByRequired(value bool)
|
||||
func Sign(value float64) float64
|
||||
func StringLength(str string, params ...string) bool
|
||||
func StringMatches(s string, params ...string) bool
|
||||
func StripLow(str string, keepNewLines bool) string
|
||||
func ToBoolean(str string) (bool, error)
|
||||
func ToFloat(str string) (float64, error)
|
||||
func ToInt(value interface{}) (res int64, err error)
|
||||
func ToJSON(obj interface{}) (string, error)
|
||||
func ToString(obj interface{}) string
|
||||
func Trim(str, chars string) string
|
||||
func Truncate(str string, length int, ending string) string
|
||||
func TruncatingErrorf(str string, args ...interface{}) error
|
||||
func UnderscoreToCamelCase(s string) string
|
||||
func ValidateMap(inputMap map[string]interface{}, validationMap map[string]interface{}) (bool, error)
|
||||
func ValidateStruct(s interface{}) (bool, error)
|
||||
func WhiteList(str, chars string) string
|
||||
type ConditionIterator
|
||||
type CustomTypeValidator
|
||||
type Error
|
||||
func (e Error) Error() string
|
||||
type Errors
|
||||
func (es Errors) Error() string
|
||||
func (es Errors) Errors() []error
|
||||
type ISO3166Entry
|
||||
type ISO693Entry
|
||||
type InterfaceParamValidator
|
||||
type Iterator
|
||||
type ParamValidator
|
||||
type ResultIterator
|
||||
type UnsupportedTypeError
|
||||
func (e *UnsupportedTypeError) Error() string
|
||||
type Validator
|
||||
```
|
||||
|
||||
#### Examples
|
||||
###### IsURL
|
||||
```go
|
||||
println(govalidator.IsURL(`http://user@pass:domain.com/path/page`))
|
||||
```
|
||||
###### IsType
|
||||
```go
|
||||
println(govalidator.IsType("Bob", "string"))
|
||||
println(govalidator.IsType(1, "int"))
|
||||
i := 1
|
||||
println(govalidator.IsType(&i, "*int"))
|
||||
```
|
||||
|
||||
IsType can be used through the tag `type` which is essential for map validation:
|
||||
```go
|
||||
type User struct {
|
||||
Name string `valid:"type(string)"`
|
||||
Age int `valid:"type(int)"`
|
||||
Meta interface{} `valid:"type(string)"`
|
||||
}
|
||||
result, err := govalidator.ValidateStruct(User{"Bob", 20, "meta"})
|
||||
if err != nil {
|
||||
println("error: " + err.Error())
|
||||
}
|
||||
println(result)
|
||||
```
|
||||
###### ToString
|
||||
```go
|
||||
type User struct {
|
||||
FirstName string
|
||||
LastName string
|
||||
}
|
||||
|
||||
str := govalidator.ToString(&User{"John", "Juan"})
|
||||
println(str)
|
||||
```
|
||||
###### Each, Map, Filter, Count for slices
|
||||
Each iterates over the slice/array and calls Iterator for every item
|
||||
```go
|
||||
data := []interface{}{1, 2, 3, 4, 5}
|
||||
var fn govalidator.Iterator = func(value interface{}, index int) {
|
||||
println(value.(int))
|
||||
}
|
||||
govalidator.Each(data, fn)
|
||||
```
|
||||
```go
|
||||
data := []interface{}{1, 2, 3, 4, 5}
|
||||
var fn govalidator.ResultIterator = func(value interface{}, index int) interface{} {
|
||||
return value.(int) * 3
|
||||
}
|
||||
_ = govalidator.Map(data, fn) // result = []interface{}{1, 6, 9, 12, 15}
|
||||
```
|
||||
```go
|
||||
data := []interface{}{1, 2, 3, 4, 5, 6, 7, 8, 9, 10}
|
||||
var fn govalidator.ConditionIterator = func(value interface{}, index int) bool {
|
||||
return value.(int)%2 == 0
|
||||
}
|
||||
_ = govalidator.Filter(data, fn) // result = []interface{}{2, 4, 6, 8, 10}
|
||||
_ = govalidator.Count(data, fn) // result = 5
|
||||
```
|
||||
###### ValidateStruct [#2](https://github.com/asaskevich/govalidator/pull/2)
|
||||
If you want to validate structs, you can use tag `valid` for any field in your structure. All validators used with this field in one tag are separated by comma. If you want to skip validation, place `-` in your tag. If you need a validator that is not on the list below, you can add it like this:
|
||||
```go
|
||||
govalidator.TagMap["duck"] = govalidator.Validator(func(str string) bool {
|
||||
return str == "duck"
|
||||
})
|
||||
```
|
||||
For completely custom validators (interface-based), see below.
|
||||
|
||||
Here is a list of available validators for struct fields (validator - used function):
|
||||
```go
|
||||
"email": IsEmail,
|
||||
"url": IsURL,
|
||||
"dialstring": IsDialString,
|
||||
"requrl": IsRequestURL,
|
||||
"requri": IsRequestURI,
|
||||
"alpha": IsAlpha,
|
||||
"utfletter": IsUTFLetter,
|
||||
"alphanum": IsAlphanumeric,
|
||||
"utfletternum": IsUTFLetterNumeric,
|
||||
"numeric": IsNumeric,
|
||||
"utfnumeric": IsUTFNumeric,
|
||||
"utfdigit": IsUTFDigit,
|
||||
"hexadecimal": IsHexadecimal,
|
||||
"hexcolor": IsHexcolor,
|
||||
"rgbcolor": IsRGBcolor,
|
||||
"lowercase": IsLowerCase,
|
||||
"uppercase": IsUpperCase,
|
||||
"int": IsInt,
|
||||
"float": IsFloat,
|
||||
"null": IsNull,
|
||||
"uuid": IsUUID,
|
||||
"uuidv3": IsUUIDv3,
|
||||
"uuidv4": IsUUIDv4,
|
||||
"uuidv5": IsUUIDv5,
|
||||
"creditcard": IsCreditCard,
|
||||
"isbn10": IsISBN10,
|
||||
"isbn13": IsISBN13,
|
||||
"json": IsJSON,
|
||||
"multibyte": IsMultibyte,
|
||||
"ascii": IsASCII,
|
||||
"printableascii": IsPrintableASCII,
|
||||
"fullwidth": IsFullWidth,
|
||||
"halfwidth": IsHalfWidth,
|
||||
"variablewidth": IsVariableWidth,
|
||||
"base64": IsBase64,
|
||||
"datauri": IsDataURI,
|
||||
"ip": IsIP,
|
||||
"port": IsPort,
|
||||
"ipv4": IsIPv4,
|
||||
"ipv6": IsIPv6,
|
||||
"dns": IsDNSName,
|
||||
"host": IsHost,
|
||||
"mac": IsMAC,
|
||||
"latitude": IsLatitude,
|
||||
"longitude": IsLongitude,
|
||||
"ssn": IsSSN,
|
||||
"semver": IsSemver,
|
||||
"rfc3339": IsRFC3339,
|
||||
"rfc3339WithoutZone": IsRFC3339WithoutZone,
|
||||
"ISO3166Alpha2": IsISO3166Alpha2,
|
||||
"ISO3166Alpha3": IsISO3166Alpha3,
|
||||
"ulid": IsULID,
|
||||
```
|
||||
Validators with parameters
|
||||
|
||||
```go
|
||||
"range(min|max)": Range,
|
||||
"length(min|max)": ByteLength,
|
||||
"runelength(min|max)": RuneLength,
|
||||
"stringlength(min|max)": StringLength,
|
||||
"matches(pattern)": StringMatches,
|
||||
"in(string1|string2|...|stringN)": IsIn,
|
||||
"rsapub(keylength)" : IsRsaPub,
|
||||
"minstringlength(int): MinStringLength,
|
||||
"maxstringlength(int): MaxStringLength,
|
||||
```
|
||||
Validators with parameters for any type
|
||||
|
||||
```go
|
||||
"type(type)": IsType,
|
||||
```
|
||||
|
||||
And here is small example of usage:
|
||||
```go
|
||||
type Post struct {
|
||||
Title string `valid:"alphanum,required"`
|
||||
Message string `valid:"duck,ascii"`
|
||||
Message2 string `valid:"animal(dog)"`
|
||||
AuthorIP string `valid:"ipv4"`
|
||||
Date string `valid:"-"`
|
||||
}
|
||||
post := &Post{
|
||||
Title: "My Example Post",
|
||||
Message: "duck",
|
||||
Message2: "dog",
|
||||
AuthorIP: "123.234.54.3",
|
||||
}
|
||||
|
||||
// Add your own struct validation tags
|
||||
govalidator.TagMap["duck"] = govalidator.Validator(func(str string) bool {
|
||||
return str == "duck"
|
||||
})
|
||||
|
||||
// Add your own struct validation tags with parameter
|
||||
govalidator.ParamTagMap["animal"] = govalidator.ParamValidator(func(str string, params ...string) bool {
|
||||
species := params[0]
|
||||
return str == species
|
||||
})
|
||||
govalidator.ParamTagRegexMap["animal"] = regexp.MustCompile("^animal\\((\\w+)\\)$")
|
||||
|
||||
result, err := govalidator.ValidateStruct(post)
|
||||
if err != nil {
|
||||
println("error: " + err.Error())
|
||||
}
|
||||
println(result)
|
||||
```
|
||||
###### ValidateMap [#2](https://github.com/asaskevich/govalidator/pull/338)
|
||||
If you want to validate maps, you can use the map to be validated and a validation map that contain the same tags used in ValidateStruct, both maps have to be in the form `map[string]interface{}`
|
||||
|
||||
So here is small example of usage:
|
||||
```go
|
||||
var mapTemplate = map[string]interface{}{
|
||||
"name":"required,alpha",
|
||||
"family":"required,alpha",
|
||||
"email":"required,email",
|
||||
"cell-phone":"numeric",
|
||||
"address":map[string]interface{}{
|
||||
"line1":"required,alphanum",
|
||||
"line2":"alphanum",
|
||||
"postal-code":"numeric",
|
||||
},
|
||||
}
|
||||
|
||||
var inputMap = map[string]interface{}{
|
||||
"name":"Bob",
|
||||
"family":"Smith",
|
||||
"email":"foo@bar.baz",
|
||||
"address":map[string]interface{}{
|
||||
"line1":"",
|
||||
"line2":"",
|
||||
"postal-code":"",
|
||||
},
|
||||
}
|
||||
|
||||
result, err := govalidator.ValidateMap(inputMap, mapTemplate)
|
||||
if err != nil {
|
||||
println("error: " + err.Error())
|
||||
}
|
||||
println(result)
|
||||
```
|
||||
|
||||
###### WhiteList
|
||||
```go
|
||||
// Remove all characters from string ignoring characters between "a" and "z"
|
||||
println(govalidator.WhiteList("a3a43a5a4a3a2a23a4a5a4a3a4", "a-z") == "aaaaaaaaaaaa")
|
||||
```
|
||||
|
||||
###### Custom validation functions
|
||||
Custom validation using your own domain specific validators is also available - here's an example of how to use it:
|
||||
```go
|
||||
import "github.com/asaskevich/govalidator"
|
||||
|
||||
type CustomByteArray [6]byte // custom types are supported and can be validated
|
||||
|
||||
type StructWithCustomByteArray struct {
|
||||
ID CustomByteArray `valid:"customByteArrayValidator,customMinLengthValidator"` // multiple custom validators are possible as well and will be evaluated in sequence
|
||||
Email string `valid:"email"`
|
||||
CustomMinLength int `valid:"-"`
|
||||
}
|
||||
|
||||
govalidator.CustomTypeTagMap.Set("customByteArrayValidator", func(i interface{}, context interface{}) bool {
|
||||
switch v := context.(type) { // you can type switch on the context interface being validated
|
||||
case StructWithCustomByteArray:
|
||||
// you can check and validate against some other field in the context,
|
||||
// return early or not validate against the context at all – your choice
|
||||
case SomeOtherType:
|
||||
// ...
|
||||
default:
|
||||
// expecting some other type? Throw/panic here or continue
|
||||
}
|
||||
|
||||
switch v := i.(type) { // type switch on the struct field being validated
|
||||
case CustomByteArray:
|
||||
for _, e := range v { // this validator checks that the byte array is not empty, i.e. not all zeroes
|
||||
if e != 0 {
|
||||
return true
|
||||
}
|
||||
}
|
||||
}
|
||||
return false
|
||||
})
|
||||
govalidator.CustomTypeTagMap.Set("customMinLengthValidator", func(i interface{}, context interface{}) bool {
|
||||
switch v := context.(type) { // this validates a field against the value in another field, i.e. dependent validation
|
||||
case StructWithCustomByteArray:
|
||||
return len(v.ID) >= v.CustomMinLength
|
||||
}
|
||||
return false
|
||||
})
|
||||
```
|
||||
|
||||
###### Loop over Error()
|
||||
By default .Error() returns all errors in a single String. To access each error you can do this:
|
||||
```go
|
||||
if err != nil {
|
||||
errs := err.(govalidator.Errors).Errors()
|
||||
for _, e := range errs {
|
||||
fmt.Println(e.Error())
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
###### Custom error messages
|
||||
Custom error messages are supported via annotations by adding the `~` separator - here's an example of how to use it:
|
||||
```go
|
||||
type Ticket struct {
|
||||
Id int64 `json:"id"`
|
||||
FirstName string `json:"firstname" valid:"required~First name is blank"`
|
||||
}
|
||||
```
|
||||
|
||||
#### Notes
|
||||
Documentation is available here: [godoc.org](https://godoc.org/github.com/asaskevich/govalidator).
|
||||
Full information about code coverage is also available here: [govalidator on gocover.io](http://gocover.io/github.com/asaskevich/govalidator).
|
||||
|
||||
#### Support
|
||||
If you do have a contribution to the package, feel free to create a Pull Request or an Issue.
|
||||
|
||||
#### What to contribute
|
||||
If you don't know what to do, there are some features and functions that need to be done
|
||||
|
||||
- [ ] Refactor code
|
||||
- [ ] Edit docs and [README](https://github.com/asaskevich/govalidator/README.md): spellcheck, grammar and typo check
|
||||
- [ ] Create actual list of contributors and projects that currently using this package
|
||||
- [ ] Resolve [issues and bugs](https://github.com/asaskevich/govalidator/issues)
|
||||
- [ ] Update actual [list of functions](https://github.com/asaskevich/govalidator#list-of-functions)
|
||||
- [ ] Update [list of validators](https://github.com/asaskevich/govalidator#validatestruct-2) that available for `ValidateStruct` and add new
|
||||
- [ ] Implement new validators: `IsFQDN`, `IsIMEI`, `IsPostalCode`, `IsISIN`, `IsISRC` etc
|
||||
- [x] Implement [validation by maps](https://github.com/asaskevich/govalidator/issues/224)
|
||||
- [ ] Implement fuzzing testing
|
||||
- [ ] Implement some struct/map/array utilities
|
||||
- [ ] Implement map/array validation
|
||||
- [ ] Implement benchmarking
|
||||
- [ ] Implement batch of examples
|
||||
- [ ] Look at forks for new features and fixes
|
||||
|
||||
#### Advice
|
||||
Feel free to create what you want, but keep in mind when you implement new features:
|
||||
- Code must be clear and readable, names of variables/constants clearly describes what they are doing
|
||||
- Public functions must be documented and described in source file and added to README.md to the list of available functions
|
||||
- There are must be unit-tests for any new functions and improvements
|
||||
|
||||
## Credits
|
||||
### Contributors
|
||||
|
||||
This project exists thanks to all the people who contribute. [[Contribute](CONTRIBUTING.md)].
|
||||
|
||||
#### Special thanks to [contributors](https://github.com/asaskevich/govalidator/graphs/contributors)
|
||||
* [Daniel Lohse](https://github.com/annismckenzie)
|
||||
* [Attila Oláh](https://github.com/attilaolah)
|
||||
* [Daniel Korner](https://github.com/Dadie)
|
||||
* [Steven Wilkin](https://github.com/stevenwilkin)
|
||||
* [Deiwin Sarjas](https://github.com/deiwin)
|
||||
* [Noah Shibley](https://github.com/slugmobile)
|
||||
* [Nathan Davies](https://github.com/nathj07)
|
||||
* [Matt Sanford](https://github.com/mzsanford)
|
||||
* [Simon ccl1115](https://github.com/ccl1115)
|
||||
|
||||
<a href="https://github.com/asaskevich/govalidator/graphs/contributors"><img src="https://opencollective.com/govalidator/contributors.svg?width=890" /></a>
|
||||
|
||||
|
||||
### Backers
|
||||
|
||||
Thank you to all our backers! 🙏 [[Become a backer](https://opencollective.com/govalidator#backer)]
|
||||
|
||||
<a href="https://opencollective.com/govalidator#backers" target="_blank"><img src="https://opencollective.com/govalidator/backers.svg?width=890"></a>
|
||||
|
||||
|
||||
### Sponsors
|
||||
|
||||
Support this project by becoming a sponsor. Your logo will show up here with a link to your website. [[Become a sponsor](https://opencollective.com/govalidator#sponsor)]
|
||||
|
||||
<a href="https://opencollective.com/govalidator/sponsor/0/website" target="_blank"><img src="https://opencollective.com/govalidator/sponsor/0/avatar.svg"></a>
|
||||
<a href="https://opencollective.com/govalidator/sponsor/1/website" target="_blank"><img src="https://opencollective.com/govalidator/sponsor/1/avatar.svg"></a>
|
||||
<a href="https://opencollective.com/govalidator/sponsor/2/website" target="_blank"><img src="https://opencollective.com/govalidator/sponsor/2/avatar.svg"></a>
|
||||
<a href="https://opencollective.com/govalidator/sponsor/3/website" target="_blank"><img src="https://opencollective.com/govalidator/sponsor/3/avatar.svg"></a>
|
||||
<a href="https://opencollective.com/govalidator/sponsor/4/website" target="_blank"><img src="https://opencollective.com/govalidator/sponsor/4/avatar.svg"></a>
|
||||
<a href="https://opencollective.com/govalidator/sponsor/5/website" target="_blank"><img src="https://opencollective.com/govalidator/sponsor/5/avatar.svg"></a>
|
||||
<a href="https://opencollective.com/govalidator/sponsor/6/website" target="_blank"><img src="https://opencollective.com/govalidator/sponsor/6/avatar.svg"></a>
|
||||
<a href="https://opencollective.com/govalidator/sponsor/7/website" target="_blank"><img src="https://opencollective.com/govalidator/sponsor/7/avatar.svg"></a>
|
||||
<a href="https://opencollective.com/govalidator/sponsor/8/website" target="_blank"><img src="https://opencollective.com/govalidator/sponsor/8/avatar.svg"></a>
|
||||
<a href="https://opencollective.com/govalidator/sponsor/9/website" target="_blank"><img src="https://opencollective.com/govalidator/sponsor/9/avatar.svg"></a>
|
||||
|
||||
|
||||
|
||||
|
||||
## License
|
||||
[](https://app.fossa.io/projects/git%2Bgithub.com%2Fasaskevich%2Fgovalidator?ref=badge_large)
|
||||
87
vendor/github.com/asaskevich/govalidator/arrays.go
generated
vendored
Normal file
87
vendor/github.com/asaskevich/govalidator/arrays.go
generated
vendored
Normal file
|
|
@ -0,0 +1,87 @@
|
|||
package govalidator
|
||||
|
||||
// Iterator is the function that accepts element of slice/array and its index
|
||||
type Iterator func(interface{}, int)
|
||||
|
||||
// ResultIterator is the function that accepts element of slice/array and its index and returns any result
|
||||
type ResultIterator func(interface{}, int) interface{}
|
||||
|
||||
// ConditionIterator is the function that accepts element of slice/array and its index and returns boolean
|
||||
type ConditionIterator func(interface{}, int) bool
|
||||
|
||||
// ReduceIterator is the function that accepts two element of slice/array and returns result of merging those values
|
||||
type ReduceIterator func(interface{}, interface{}) interface{}
|
||||
|
||||
// Some validates that any item of array corresponds to ConditionIterator. Returns boolean.
|
||||
func Some(array []interface{}, iterator ConditionIterator) bool {
|
||||
res := false
|
||||
for index, data := range array {
|
||||
res = res || iterator(data, index)
|
||||
}
|
||||
return res
|
||||
}
|
||||
|
||||
// Every validates that every item of array corresponds to ConditionIterator. Returns boolean.
|
||||
func Every(array []interface{}, iterator ConditionIterator) bool {
|
||||
res := true
|
||||
for index, data := range array {
|
||||
res = res && iterator(data, index)
|
||||
}
|
||||
return res
|
||||
}
|
||||
|
||||
// Reduce boils down a list of values into a single value by ReduceIterator
|
||||
func Reduce(array []interface{}, iterator ReduceIterator, initialValue interface{}) interface{} {
|
||||
for _, data := range array {
|
||||
initialValue = iterator(initialValue, data)
|
||||
}
|
||||
return initialValue
|
||||
}
|
||||
|
||||
// Each iterates over the slice and apply Iterator to every item
|
||||
func Each(array []interface{}, iterator Iterator) {
|
||||
for index, data := range array {
|
||||
iterator(data, index)
|
||||
}
|
||||
}
|
||||
|
||||
// Map iterates over the slice and apply ResultIterator to every item. Returns new slice as a result.
|
||||
func Map(array []interface{}, iterator ResultIterator) []interface{} {
|
||||
var result = make([]interface{}, len(array))
|
||||
for index, data := range array {
|
||||
result[index] = iterator(data, index)
|
||||
}
|
||||
return result
|
||||
}
|
||||
|
||||
// Find iterates over the slice and apply ConditionIterator to every item. Returns first item that meet ConditionIterator or nil otherwise.
|
||||
func Find(array []interface{}, iterator ConditionIterator) interface{} {
|
||||
for index, data := range array {
|
||||
if iterator(data, index) {
|
||||
return data
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// Filter iterates over the slice and apply ConditionIterator to every item. Returns new slice.
|
||||
func Filter(array []interface{}, iterator ConditionIterator) []interface{} {
|
||||
var result = make([]interface{}, 0)
|
||||
for index, data := range array {
|
||||
if iterator(data, index) {
|
||||
result = append(result, data)
|
||||
}
|
||||
}
|
||||
return result
|
||||
}
|
||||
|
||||
// Count iterates over the slice and apply ConditionIterator to every item. Returns count of items that meets ConditionIterator.
|
||||
func Count(array []interface{}, iterator ConditionIterator) int {
|
||||
count := 0
|
||||
for index, data := range array {
|
||||
if iterator(data, index) {
|
||||
count = count + 1
|
||||
}
|
||||
}
|
||||
return count
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Add a link
Reference in a new issue