func()

in oss/encryption_client.go [134:237]


func (e *EncryptionClient) getObjectSecurely(ctx context.Context, request *GetObjectRequest, optFns ...func(*Options)) (*GetObjectResult, error) {
	if request == nil {
		return nil, NewErrParamNull("request")
	}

	var (
		err          error
		httpRange    *HTTPRange
		discardCount int64 = 0
		adjustOffset int64 = 0
		closeBody    bool  = true
	)

	if request.Range != nil {
		httpRange, err = ParseRange(*request.Range)
		if err != nil {
			return nil, err
		}
		offset := httpRange.Offset
		count := httpRange.Count
		adjustOffset = adjustRangeStart(offset, int64(e.alignLen))
		discardCount = httpRange.Offset - adjustOffset

		if discardCount != 0 {
			if count > 0 {
				count += discardCount
			}
			httpRange.Offset = adjustOffset
			httpRange.Count = count
		}
	}

	eRequest := request
	if httpRange != nil && discardCount > 0 {
		_request := *request
		eRequest = &_request
		eRequest.Range = httpRange.FormatHTTPRange()
		eRequest.RangeBehavior = Ptr("standard")
	}

	result, err := e.client.GetObject(ctx, eRequest, optFns...)

	if err != nil {
		return nil, err
	}

	defer func() {
		if closeBody && result.Body != nil {
			result.Body.Close()
		}
	}()

	if hasEncryptedHeader(result.Headers) {
		envelope, err := getEnvelopeFromHeader(result.Headers)
		if err != nil {
			return nil, err
		}
		if !isValidContentAlg(envelope.CEKAlg) {
			return nil, fmt.Errorf("not supported content algorithm %s,object:%s", envelope.CEKAlg, ToString(request.Key))
		}
		if !envelope.IsValid() {
			return nil, fmt.Errorf("getEnvelopeFromHeader error,object:%s", ToString(request.Key))
		}

		// use ContentCipherBuilder to decrpt object by default
		cc, err := e.getContentCipherBuilder(envelope).ContentCipherEnv(envelope)
		if err != nil {
			return nil, fmt.Errorf("%s,object:%s", err.Error(), ToString(request.Key))
		}

		if adjustOffset > 0 {
			cipherData := cc.GetCipherData().Clone()
			cipherData.SeekIV(uint64(adjustOffset))
			cc, _ = cc.Clone(cipherData)
		}

		result.Body, err = cc.DecryptContent(result.Body)
	}

	if discardCount > 0 && err == nil {
		//rewrite ContentRange & ContentRange
		if result.ContentRange != nil {
			if from, to, total, cerr := ParseContentRange(*result.ContentRange); cerr == nil {
				from += discardCount
				value := fmt.Sprintf("bytes %v-%v/%v", from, to, total)
				result.ContentRange = Ptr(value)
				result.Headers.Set(HTTPHeaderContentRange, value)
			}
		} else {
			result.Headers.Set(HTTPHeaderContentRange, fmt.Sprintf("bytes %v-/*", discardCount))
		}
		if result.ContentLength > 0 {
			result.ContentLength -= discardCount
			result.Headers.Set(HTTPHeaderContentLength, fmt.Sprint(result.ContentLength))
		}
		result.Body = &DiscardReadCloser{
			RC:      result.Body,
			Discard: int(discardCount),
		}
	}

	closeBody = false
	return result, err
}