For use cases involving sharing large datasets or delivering production data to customers and partners, you can have the requester cover the costs of data access. To do this, enable Pay-by-requester for the bucket. When this feature is enabled, the requester pays for all data access fees, including traffic and request fees. The bucket owner pays only for storage and other fixed fees.
How it works
Pay-by-requester shifts the billing for specific operations from the bucket owner to the requester. When you enable pay-by-requester, OSS disables anonymous access, and all requests must be authenticated. Object Storage Service (OSS) processes requests based on the following logic:
If the request includes the
x-oss-request-payer: requester
header: OSS authenticates the requester, and the requester pays the request and traffic fees.If the request does not include the
x-oss-request-payer: requester
header:If the requester is the bucket owner, the request succeeds, and the bucket owner pays the fees.
If the requester is not the bucket owner, OSS rejects the request.
Configure pay-by-requester
Step 1: Enable pay-by-requester
Console
Log on to the OSS console.
In the left-side navigation pane, click Buckets. On the Buckets page, find and click the desired bucket.
In the navigation pane on the left, choose .
On the Pay-by-requester page, turn on the Pay-by-requester switch.
In the dialog box that appears, click OK.
OSS SDKs
The following code provides examples of how to enable pay-by-requester using common SDKs. For more information about how to use other SDKs to enable this feature, see Introduction to SDKs.
import com.aliyun.oss.ClientBuilderConfiguration; import com.aliyun.oss.OSS; import com.aliyun.oss.common.auth.*; import com.aliyun.oss.OSSClientBuilder; import com.aliyun.oss.OSSException; import com.aliyun.oss.common.comm.SignVersion; import com.aliyun.oss.model.*; public class Demo { public static void main(String[] args) throws Exception{ // In this example, the endpoint of the China (Hangzhou) region is used. Specify your actual endpoint. String endpoint = "https://oss-cn-hangzhou.aliyuncs.com"; // Obtain access credentials from environment variables. Before you run the sample code, make sure that the OSS_ACCESS_KEY_ID and OSS_ACCESS_KEY_SECRET environment variables are configured. EnvironmentVariableCredentialsProvider credentialsProvider = CredentialsProviderFactory.newEnvironmentVariableCredentialsProvider(); // Specify the name of the bucket. Example: examplebucket. String bucketName = "examplebucket"; // Specify the region in which the bucket is located. For example, if the bucket is located in the China (Hangzhou) region, set the region to cn-hangzhou. String region = "cn-hangzhou"; // Create an OSS Client instance. // Call the shutdown method to release associated resources when the OSS Client is no longer in use. ClientBuilderConfiguration clientBuilderConfiguration = new ClientBuilderConfiguration(); clientBuilderConfiguration.setSignatureVersion(SignVersion.V4); OSS ossClient = OSSClientBuilder.create() .endpoint(endpoint) .credentialsProvider(credentialsProvider) .clientConfiguration(clientBuilderConfiguration) .region(region) .build(); try { // Enable pay-by-requester for the bucket. Payer payer = Payer.Requester; ossClient.setBucketRequestPayment(bucketName, payer); } catch (OSSException oe) { System.out.println("Caught an OSSException, which means your request made it to OSS, " + "but was rejected with an error response for some reason."); System.out.println("Error Message:" + oe.getErrorMessage()); System.out.println("Error Code:" + oe.getErrorCode()); System.out.println("Request ID:" + oe.getRequestId()); System.out.println("Host ID:" + oe.getHostId()); } catch (Throwable ce) { System.out.println("Caught an ClientException, which means the client encountered " + "a serious internal problem while trying to communicate with OSS, " + "such as not being able to access the network."); System.out.println("Error Message:" + ce.getMessage()); } finally { // Shut down the OSSClient instance. if (ossClient != null) { ossClient.shutdown(); } } } }
const OSS = require('ali-oss') const client = new OSS({ // Specify the region in which the bucket is located. For example, if the bucket is located in the China (Hangzhou) region, set the region to oss-cn-hangzhou. region: 'yourregion', // Obtain access credentials from environment variables. Before you run the sample code, make sure that you have configured environment variables OSS_ACCESS_KEY_ID and OSS_ACCESS_KEY_SECRET. accessKeyId: process.env.OSS_ACCESS_KEY_ID, accessKeySecret: process.env.OSS_ACCESS_KEY_SECRET, authorizationV4: true, // Specify the name of your bucket. bucket: 'yourBucketName', }); async function setBucketRequestPayment(bucket, Payer) { try { // Specify the name of the bucket for which you want to enable pay-by-requester. // Set Payer to Requester or BucketOwner. // If Payer is set to Requester, pay-by-requester is enabled for the bucket. The requester is charged the traffic and request fees that are generated when the requester reads data in the bucket. // If Payer is set to BucketOwner, pay-by-requester is disabled for the bucket. This is the default configuration for the bucket. In this case, the bucket owner is charged the generated request fees. const result = await client.putBucketRequestPayment(bucket, Payer); console.log(result); } catch (e) { console.log(e); } } setBucketRequestPayment('bucketName', 'Requester')
using Aliyun.OSS; using Aliyun.OSS.Common; // Specify the endpoint of the region in which the bucket is located. For example, if the bucket is located in the China (Hangzhou) region, set the endpoint to https://oss-cn-hangzhou.aliyuncs.com. var endpoint = "yourEndpoint"; // Obtain access credentials from environment variables. Before you run the sample code, make sure that the OSS_ACCESS_KEY_ID and OSS_ACCESS_KEY_SECRET environment variables are configured. var accessKeyId = Environment.GetEnvironmentVariable("OSS_ACCESS_KEY_ID"); var accessKeySecret = Environment.GetEnvironmentVariable("OSS_ACCESS_KEY_SECRET"); // Specify the name of the bucket. var bucketName = "examplebucket"; // Specify the region in which the bucket is located. For example, if the bucket is located in the China (Hangzhou) region, set the region to cn-hangzhou. const string region = "cn-hangzhou"; // Create a ClientConfiguration instance and modify parameters as required. var conf = new ClientConfiguration(); // Use the signature algorithm V4. conf.SignatureVersion = SignatureVersion.V4; // Create an OSSClient instance. var client = new OssClient(endpoint, accessKeyId, accessKeySecret, conf); c.SetRegion(region); try { // Enable pay-by-requester for the bucket. var request = new SetBucketRequestPaymentRequest(bucketName, RequestPayer.Requester); client.SetBucketRequestPayment(request); Console.WriteLine("Set bucket:{0} RequestPayment succeeded ", bucketName); } catch (OssException ex) { Console.WriteLine("Failed with error code: {0}; Error info: {1}. \nRequestID:{2}\tHostID:{3}", ex.ErrorCode, ex.Message, ex.RequestId, ex.HostId); } catch (Exception ex) { Console.WriteLine("Failed with error info: {0}", ex.Message); }
#include <alibabacloud/oss/OssClient.h> using namespace AlibabaCloud::OSS; int main(void) { /* Initialize information about the account that is used to access OSS. */ /* Specify the endpoint of the region in which the bucket is located. For example, if the bucket is located in the China (Hangzhou) region, set the endpoint to https://oss-cn-hangzhou.aliyuncs.com. */ std::string Endpoint = "yourEndpoint"; /* Specify the region in which the bucket is located. For example, if the bucket is located in the China (Hangzhou) region, set the region to cn-hangzhou. */ std::string Region = "yourRegion"; /* Specify the name of the bucket. Example: examplebucket. */ std::string BucketName = "examplebucket"; /* Initialize resources such as network resources. */ InitializeSdk(); ClientConfiguration conf; conf.signatureVersion = SignatureVersionType::V4; /* Obtain access credentials from environment variables. Before you run the sample code, make sure that the OSS_ACCESS_KEY_ID and OSS_ACCESS_KEY_SECRET environment variables are configured. */ auto credentialsProvider = std::make_shared<EnvironmentVariableCredentialsProvider>(); OssClient client(Endpoint, credentialsProvider, conf); client.SetRegion(Region); /* Enable pay-by-requester for the bucket. */ SetBucketRequestPaymentRequest request(BucketName); request.setRequestPayer(RequestPayer::Requester); auto outcome = client.SetBucketRequestPayment(request); if (!outcome.isSuccess()) { /* Handle exceptions. */ std::cout << "SetBucketRequestPayment fail" << ",code:" << outcome.error().Code() << ",message:" << outcome.error().Message() << ",requestId:" << outcome.error().RequestId() << std::endl; return -1; } /* Release resources such as network resources. */ ShutdownSdk(); return 0; }
package main import ( "context" "flag" "log" "github.com/aliyun/alibabacloud-oss-go-sdk-v2/oss" "github.com/aliyun/alibabacloud-oss-go-sdk-v2/oss/credentials" ) // Specify the global variables. var ( region string // The region in which the bucket is located. bucketName string // The name of the bucket. ) // Specify the init function used to initialize command line parameters. func init() { flag.StringVar(®ion, "region", "", "The region in which the bucket is located.") flag.StringVar(&bucketName, "bucket", "", "The name of the bucket.") } func main() { // Parse command line parameters. flag.Parse() // Check whether the bucket name is empty. if len(bucketName) == 0 { flag.PrintDefaults() log.Fatalf("invalid parameters, bucket name required") } // Check whether the region is empty. if len(region) == 0 { flag.PrintDefaults() log.Fatalf("invalid parameters, region required") } // Load the default configurations and specify the credential provider and region. cfg := oss.LoadDefaultConfig(). WithCredentialsProvider(credentials.NewEnvironmentVariableCredentialsProvider()). WithRegion(region) // Create an OSS client. client := oss.NewClient(cfg) // Create a request to specify the payer of the request. putRequest := &oss.PutBucketRequestPaymentRequest{ Bucket: oss.Ptr(bucketName), // The name of the bucket. PaymentConfiguration: &oss.RequestPaymentConfiguration{ Payer: oss.Requester, // Set the payer of the request to the requester. }, } // Send the request to specify the payer of the request. putResult, err := client.PutBucketRequestPayment(context.TODO(), putRequest) if err != nil { log.Fatalf("failed to put bucket request payment %v", err) } // Display the result of the request. log.Printf("put bucket request payment result:%#v\n", putResult) }
<?php require_once __DIR__ . '/../vendor/autoload.php'; // Automaticically load objects and dependency libraries. use AlibabaCloud\Oss\V2 as Oss; // Specify command line parameters. $optsdesc = [ "region" => ['help' => The region in which the bucket is located.', 'required' => True], // (Required) Specify the region in which the bucket is located. Example: oss-cn-hangzhou. "endpoint" => ['help' => The domain names that other services can use to access OSS.', 'required' => False], // (Optional) Specify the endpoint that can be used by other services to access OSS. "bucket" => ['help' => The name of the bucket, 'required' => True], // (Required) Specify the name of the bucket. ]; $longopts = \array_map(function ($key) { return "$key:"; // Add a colon (:) to the end of each parameter to indicate that a value is required. }, array_keys($optsdesc)); // Parse command line parameters. $options = getopt("", $longopts); // Check whether the required parameters are configured. foreach ($optsdesc as $key => $value) { if ($value['required'] === True && empty($options[$key])) { $help = $value['help']; echo "Error: the following arguments are required: --$key, $help"; // Specifies that the required parameters are not configured. exit(1); } } // Obtain the values of the command line parameters. $region = $options["region"]; // The region in which the bucket is located. $bucket = $options["bucket"]; // The name of the bucket. // Use environment variables to load the credential information (AccessKey ID and AccessKey secret). $credentialsProvider = new Oss\Credentials\EnvironmentVariableCredentialsProvider(); // Use the default configurations of the SDK. $cfg=Oss\Config::loadDefault(); // Load the default configurations of the SDK. $cfg->setCredentialsProvider($credentialsProvider); // Specify the credential provider. $cfg->setRegion($region); // Specify the region. if (isset($options["endpoint"])) { $cfg->setEndpoint($options["endpoint"]); // Specify the endpoint if an endpoint is provided. } // Create an OSSClient instance. $client = new Oss\Client($cfg); // Create a request to specify the payer of the request. $request = new Oss\Models\PutBucketRequestPaymentRequest( $bucket, new Oss\Models\RequestPaymentConfiguration('Requester') ); // Use the putBucketRequestPayment method to specify the payer of the request. $result = $client->putBucketRequestPayment($request); // Display the returned result. printf( 'status code:' . $result-> statusCode. PHP_EOL . // The HTTP response status code. 'request id:' . $result->requestId // The unique identifier of the request. );
ossutil
You can use the ossutil command line interface to enable pay-by-requester. For more information about how to install ossutil, see Install ossutil.
The following example shows how to enable pay-by-requester for a bucket named examplebucket
.
ossutil api put-bucket-request-payment --bucket examplebucket --request-payment-configuration "{\"Payer\":\"Requester\"}"
For more information, see put-bucket-request-payment.
API
If your business requires a high level of customization, you can directly call RESTful APIs. To directly call an API, you must include the signature calculation in your code. For more information, see PutBucketRequestPayment.
Step 2: Grant access permissions to the requester
Use a Bucket Policy or RAM policy to grant requesters specific access to your data. To ensure the requester is billed, they must use their own Alibaba Cloud account credentials to make requests. Do not share your account's AccessKey pairs with requesters. If a requester uses credentials from the bucket owner's account (including RAM user credentials), the bucket owner will be billed for the request.
When a requester assumes a RAM role from the bucket owner's account to access a bucket for which pay-by-requester is enabled, the requester's account is charged for any incurred fees.
Access a bucket as a requester by including the x-oss-request-payer
header
To access a bucket for which pay-by-requester is enabled, you must include the x-oss-request-payer
header in your request.
For POST, GET, and HEAD requests, include
x-oss-request-payer:requester
in the request header. For more information, see (Recommended) Include a V4 signature.For presigned URLs, include
x-oss-request-payer=requester
as a query parameter. For more information, see (Recommended) Include a V4 signature.
Apply in production
Presigned URL pitfalls:
Incorrect approach: The bucket owner generates a presigned URL using their own credentials. When anyone uses this URL, the request is authenticated as the bucket owner, and therefore the bucket owner is billed, even if the
x-oss-request-payer
parameter is included.Correct approach: The requester must generate the presigned URL using their own identity credentials (an AccessKey pair or an STS temporary credential).
Compatibility risks: This feature is incompatible with static website hosting. Enabling pay-by-requester disables anonymous access, which static website hosting requires. This will cause the hosted website to fail.
Billing
Before you enable pay-by-requester for a bucket, the bucket owner pays all fees. After you enable pay-by-requester, the billable items for the bucket owner change. The following table outlines the billable items for the bucket owner and the requester.
Fee | Billable item | Payer |
Standard (LRS) capacity | Bucket owner | |
Standard (ZRS) capacity | Bucket owner | |
Infrequent Access (LRS) capacity | Bucket owner | |
Infrequent Access (ZRS) capacity | Bucket owner | |
Archive (LRS) capacity | Bucket owner | |
Archive (ZRS) capacity | Bucket owner | |
Cold Archive (LRS) capacity | Bucket owner | |
Deep Cold Archive (LRS) capacity | Bucket owner | |
Infrequent Access (LRS) capacity for objects stored for less than the minimum duration | Bucket owner | |
Archive (LRS) capacity for objects stored for less than the minimum duration | Bucket owner | |
Archive (ZRS) capacity for objects stored for less than the minimum duration | Bucket owner | |
Cold Archive capacity for objects stored for less than the minimum duration | Bucket owner | |
Deep Cold Archive capacity for objects stored for less than the minimum duration | Bucket owner | |
Outbound traffic over the internet | Requester | |
Inbound traffic over the internet | Free | |
Outbound traffic over the internal network | Free | |
Inbound traffic over the internal network | Free | |
Origin traffic | Requester | |
Cross-Region Replication (CRR) traffic | Bucket owner | |
PUT requests | Requester | |
GET requests | Requester | |
Retrieval requests | Bucket owner | |
Select scanned data volume | Bucket owner | |
Infrequent Access data retrieval | Requester | |
Archive data retrieval | Requester | |
Real-time access of Archive objects | Bucket owner | |
Cold Archive data retrieval | Bucket owner | |
Deep Cold Archive data retrieval | Bucket owner | |
Object tagging | Bucket owner | |
Transfer acceleration AccM2MIn | Bucket owner | |
Transfer acceleration AccM2MOut | Bucket owner | |
Transfer acceleration AccM2OIn | Bucket owner | |
Transfer acceleration AccM2OOut | Bucket owner | |
Transfer acceleration AccO2MIn | Bucket owner | |
Transfer acceleration AccO2MOut | Bucket owner | |
Transfer acceleration AccO2OIn | Bucket owner | |
Transfer acceleration AccO2OOut | Bucket owner | |
Temporary storage capacity (LRS) | Bucket owner | |
Reserved OSS DDoS protection instances | Bucket owner | |
Remaining duration of OSS DDoS protection instances released within the minimum usage duration | Bucket owner | |
Traffic protected by OSS DDoS protection instances | Bucket owner | |
API requests protected by OSS DDoS protection | Bucket owner | |
Metadata management | Free during public preview | |
Bucket query | Free during public preview |
①If the requester does not include the x-oss-request-payer
header in a GET, HEAD, or POST request, the bucket owner pays the fees for the PUT and GET requests.