diff --git a/storagev2/uptoken/uploadtoken.go b/storagev2/uptoken/uploadtoken.go index b3c32685..a4c66df9 100644 --- a/storagev2/uptoken/uploadtoken.go +++ b/storagev2/uptoken/uploadtoken.go @@ -36,15 +36,21 @@ type ( signer struct { putPolicy PutPolicy credentialsProvider credentials.CredentialsProvider - onceCredentials sync.Once - upToken string + mu sync.Mutex credentials *credentials.Credentials + credentialsInited bool + upToken string + upTokenInited bool } parser struct { - upToken string - putPolicy PutPolicy - accessKey string - splits []string + upToken string + mu sync.Mutex + putPolicy PutPolicy + putPolicyInited bool + accessKey string + accessKeyInited bool + splits []string + splitsInited bool } ) @@ -60,8 +66,7 @@ func (signer *signer) GetPutPolicy(context.Context) (PutPolicy, error) { } func (signer *signer) GetAccessKey(ctx context.Context) (string, error) { - var err error - credentials, err := signer.onceGetCredentials(ctx) + credentials, err := signer.getCredentials(ctx) if err != nil { return "", err } @@ -69,84 +74,154 @@ func (signer *signer) GetAccessKey(ctx context.Context) (string, error) { } func (signer *signer) GetUpToken(ctx context.Context) (string, error) { - return signer.onceGetUpToken(ctx) -} - -func (signer *signer) onceGetCredentials(ctx context.Context) (*credentials.Credentials, error) { - var err error - signer.onceCredentials.Do(func() { - if signer.credentialsProvider != nil { - signer.credentials, err = signer.credentialsProvider.Get(ctx) - } else if defaultCreds := credentials.Default(); defaultCreds != nil { - signer.credentials = defaultCreds - } - }) - return signer.credentials, err -} - -func (signer *signer) onceGetUpToken(ctx context.Context) (string, error) { - var err error - if signer.upToken != "" { + signer.mu.Lock() + if signer.upTokenInited { + defer signer.mu.Unlock() return signer.upToken, nil } - credentials, err := signer.onceGetCredentials(ctx) + signer.mu.Unlock() + + credentials, err := signer.getCredentials(ctx) if err != nil { - return "", nil + return "", err } + putPolicyJson, err := json.Marshal(signer.putPolicy) if err != nil { - return "", nil + return "", err + } + + upToken := credentials.SignWithData(putPolicyJson) + + signer.mu.Lock() + defer signer.mu.Unlock() + if !signer.upTokenInited { + signer.upToken = upToken + signer.upTokenInited = true } - signer.upToken = credentials.SignWithData(putPolicyJson) return signer.upToken, nil } +func (signer *signer) getCredentials(ctx context.Context) (*credentials.Credentials, error) { + signer.mu.Lock() + if signer.credentialsInited { + defer signer.mu.Unlock() + return signer.credentials, nil + } + signer.mu.Unlock() + + var creds *credentials.Credentials + var err error + if signer.credentialsProvider != nil { + creds, err = signer.credentialsProvider.Get(ctx) + if err != nil { + return nil, err + } + } else if defaultCreds := credentials.Default(); defaultCreds != nil { + creds = defaultCreds + } + + signer.mu.Lock() + defer signer.mu.Unlock() + if !signer.credentialsInited { + signer.credentials = creds + signer.credentialsInited = true + } + return signer.credentials, nil +} + // NewParser 创建上传凭证签发器 func NewParser(upToken string) Provider { return &parser{upToken: upToken} } func (parser *parser) GetPutPolicy(context.Context) (PutPolicy, error) { - if parser.putPolicy != nil { + parser.mu.Lock() + if parser.putPolicyInited { + defer parser.mu.Unlock() return parser.putPolicy, nil } - splits, ok := parser.onceGetSplits() - if !ok { - return nil, ErrInvalidUpToken + parser.mu.Unlock() + + splits, err := parser.getSplits() + if err != nil { + return PutPolicy{}, err } + putPolicyJson, err := base64.URLEncoding.DecodeString(splits[2]) if err != nil { - return nil, ErrInvalidUpToken + return PutPolicy{}, ErrInvalidUpToken + } + + var putPolicy PutPolicy + if err := json.Unmarshal(putPolicyJson, &putPolicy); err != nil { + return PutPolicy{}, err } - err = json.Unmarshal(putPolicyJson, &parser.putPolicy) - return parser.putPolicy, err + + parser.mu.Lock() + defer parser.mu.Unlock() + if !parser.putPolicyInited { + parser.putPolicy = putPolicy + parser.putPolicyInited = true + } + return parser.putPolicy, nil } func (parser *parser) GetAccessKey(context.Context) (string, error) { - if parser.accessKey != "" { + parser.mu.Lock() + if parser.accessKeyInited { + defer parser.mu.Unlock() return parser.accessKey, nil } - splits, ok := parser.onceGetSplits() - if !ok { - return "", ErrInvalidUpToken + parser.mu.Unlock() + + splits, err := parser.getSplits() + if err != nil { + return "", err + } + + accessKey := splits[0] + + parser.mu.Lock() + defer parser.mu.Unlock() + if !parser.accessKeyInited { + parser.accessKey = accessKey + parser.accessKeyInited = true } - parser.accessKey = splits[0] return parser.accessKey, nil } -func (parser *parser) onceGetSplits() ([]string, bool) { - if len(parser.splits) > 0 { - return parser.splits, true +func (parser *parser) getSplits() ([]string, error) { + parser.mu.Lock() + if parser.splitsInited { + defer parser.mu.Unlock() + if parser.splits == nil { + return nil, ErrInvalidUpToken + } + return parser.splits, nil } + parser.mu.Unlock() + splits := strings.Split(parser.upToken, ":") if len(splits) == 5 && splits[0] == "" { splits = splits[2:] } if len(splits) != 3 { - return nil, false + parser.mu.Lock() + defer parser.mu.Unlock() + if !parser.splitsInited { + parser.splitsInited = true + } + return nil, ErrInvalidUpToken + } + + parser.mu.Lock() + defer parser.mu.Unlock() + if !parser.splitsInited { + parser.splits = splits + parser.splitsInited = true } - parser.splits = splits - return parser.splits, true + return parser.splits, nil } func (parser *parser) GetUpToken(context.Context) (string, error) {