# GetBucketLocation

GetBucketLocation returns the region a bucket lives in. Each STRG endpoint serves exactly one
region and answers for the buckets in it, so a successful answer is always the endpoint's own
region: `us-east-1` comes back as an empty `LocationConstraint`, just as Amazon S3 answers it, and
`eu-central-1` by name. [HeadBucket](https://docs.strg.com/s3-api/HeadBucket) carries the same region in its
`x-amz-bucket-region` header, which makes it a handy alternative.

**Info: Good to know on STRG**

- A bucket in another region answers `404 NoSuchBucket` rather than a redirect, so the operation
  confirms a bucket's region from that region's own endpoint -
  [Finding a bucket's region](https://docs.strg.com/s3-api/GetBucketLocation#finding-a-buckets-region) shows how that works.
- The answer is always a STRG region (`us-east-1` or `eu-central-1`), so legacy values such
  as `EU` never need handling.
- `x-amz-expected-bucket-owner` is welcome and has nothing to check: a key only ever reaches
  buckets of its own account.

## When you'd use it

- **Tools written for Amazon S3.** Many clients and SDK helpers ask for a bucket's location
  before they start working with it, and they get an answer in the shape they expect.
- **Confirming configuration.** A deploy script or an agent about to write to a bucket can check
  that the endpoint and region it was configured with really are the bucket's, before it uploads
  anything.
- **Finding where a bucket lives.** A script handed only a bucket name can ask each regional
  endpoint in turn; the one that answers is the bucket's region.

## Request

```http
GET /?location HTTP/1.1
Host: my-bucket.s3.eu-central-1.strg.com
Authorization: AWS4-HMAC-SHA256 Credential=...
x-amz-date: 20260926T120000Z
x-amz-content-sha256: e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855
```

The path-style form is `GET /my-bucket?location` on `s3.eu-central-1.strg.com` -
[Addressing](https://docs.strg.com/s3-api/overview#addressing) explains both.

### Permissions

The access key needs **Read bucket settings** (`buckets:read-config`), which every access key
holds, whether it covers all buckets or only some. A key limited to certain buckets reads the
location of those buckets, and any other bucket answers `403 AccessDenied`.
[Access keys](https://docs.strg.com/access-keys#always-included) has the details.

### URI parameters

| Name | Type | Required | Description |
| --- | --- | --- | --- |
| `Bucket` | String | Yes | The bucket whose region is returned. |
| `location` | Flag | Yes | Selects this operation. Sent with no value. |

Any other query parameter answers `501 NotImplemented`, so a client knows straight away.

### Request headers

| Name | Type | Required | Description |
| --- | --- | --- | --- |
| `x-amz-expected-bucket-owner` | String | No | Welcome, with nothing to check: an access key only ever reaches its own account's buckets. |

### Request body

None.

## Response

A successful request answers `200 OK` with an XML body.

### Response headers

| Name | Description |
| --- | --- |
| `Content-Type` | `application/xml` |
| `x-amz-request-id` | The request ID, handy for a support request. |

### Response body

| Element | Type | Description |
| --- | --- | --- |
| `LocationConstraint` | String | The bucket's region. Empty for `us-east-1`; `eu-central-1` otherwise. |

A bucket in `eu-central-1`:

```xml
<?xml version="1.0" encoding="UTF-8"?>
<LocationConstraint xmlns="http://s3.amazonaws.com/doc/2006-03-01/">eu-central-1</LocationConstraint>
```

A bucket in `us-east-1`:

```xml
<?xml version="1.0" encoding="UTF-8"?>
<LocationConstraint xmlns="http://s3.amazonaws.com/doc/2006-03-01/"/>
```

The AWS SDKs and the AWS CLI report the empty element as `null` or leave it out, and either way it
means `us-east-1`.

## Errors

These are the errors this request can return, and the situation behind each one.

| Code | HTTP status | When |
| --- | --- | --- |
| `NoSuchBucket` | 404 | The bucket does not exist, belongs to another account, or is in a region other than the endpoint's - including when the account has nothing stored in this endpoint's region yet. |
| `AccessDenied` | 403 | The access key is limited to other buckets, the account is not active, or the request is unsigned. |
| `InvalidAccessKeyId` | 403 | The access key does not exist, has expired or been revoked - or it was created moments ago and is not usable yet in this endpoint's region, in which case the same request works shortly afterwards. |
| `SignatureDoesNotMatch` | 403 | The request signature does not match. |
| `RequestTimeTooSkewed` | 403 | The request time is more than 15 minutes from the server's. |
| `AuthorizationHeaderMalformed` | 400 | The signature's credential scope names a region other than the endpoint's. |
| `NotImplemented` | 501 | The request carries a query parameter this operation does not take. |
| `SlowDown` | 503 | Too many requests. The `Retry-After` header says when a retry is welcome; the AWS SDKs retry on their own. |
| `ServiceUnavailable` | 503 | A temporary failure; the same request can be retried. |
| `InternalError` | 500 | An unexpected failure while confirming the bucket; the same request can be retried. |

## Finding a bucket's region

Every endpoint answers for its own region, so finding a bucket's region is a matter of asking
each regional endpoint in turn: the one that answers `200` is the bucket's region, and every other
answers `404 NoSuchBucket`. STRG has two regions, `us-east-1` and `eu-central-1`, so this takes
at most two requests. Each request is signed for the region of the endpoint it goes to - a
signature for another region answers `AuthorizationHeaderMalformed`.

A region where the account has never stored anything answers `NoSuchBucket` as well, which is
the truth: the bucket is not there.

## Differences from Amazon S3

| Aspect | Amazon S3 | STRG |
| --- | --- | --- |
| Bucket in another region | Answered from any region | `404 NoSuchBucket`; the bucket's own regional endpoint answers with its region |
| Values | Any AWS region, plus legacy values such as `EU` | `us-east-1` (empty) or `eu-central-1` |
| `x-amz-expected-bucket-owner` | Checked against the bucket owner | Welcome, with nothing to check - a key only reaches its own account's buckets |

## Examples

**AWS CLI**

```bash
aws s3api get-bucket-location \
  --bucket my-bucket \
  --endpoint-url https://s3.eu-central-1.strg.com \
  --region eu-central-1
```

```json
{
    "LocationConstraint": "eu-central-1"
}
```

For a bucket in `us-east-1`, `LocationConstraint` is `null`.

**Python (boto3)**

```python
import boto3

s3 = boto3.client(
    "s3",
    endpoint_url="https://s3.eu-central-1.strg.com",
    region_name="eu-central-1",
)

response = s3.get_bucket_location(Bucket="my-bucket")
print(response.get("LocationConstraint") or "us-east-1")
```

**JavaScript (AWS SDK v3)**

```javascript
import { GetBucketLocationCommand, S3Client } from "@aws-sdk/client-s3";

const client = new S3Client({
  endpoint: "https://s3.eu-central-1.strg.com",
  region: "eu-central-1",
});

const response = await client.send(new GetBucketLocationCommand({ Bucket: "my-bucket" }));
console.log(response.LocationConstraint || "us-east-1");
```

Finding which region a bucket is in, by asking each regional endpoint:

**AWS CLI**

```bash
for region in us-east-1 eu-central-1; do
  if aws s3api get-bucket-location \
      --bucket my-bucket \
      --endpoint-url "https://s3.${region}.strg.com" \
      --region "${region}" > /dev/null 2>&1; then
    echo "my-bucket is in ${region}"
  fi
done
```

**Python (boto3)**

```python
import boto3
from botocore.exceptions import ClientError

for region in ["us-east-1", "eu-central-1"]:
    s3 = boto3.client(
        "s3",
        endpoint_url=f"https://s3.{region}.strg.com",
        region_name=region,
    )
    try:
        s3.get_bucket_location(Bucket="my-bucket")
    except ClientError as error:
        if error.response["Error"]["Code"] == "NoSuchBucket":
            continue
        raise
    print(f"my-bucket is in {region}")
    break
```

**JavaScript (AWS SDK v3)**

```javascript
import { GetBucketLocationCommand, S3Client } from "@aws-sdk/client-s3";

for (const region of ["us-east-1", "eu-central-1"]) {
  const client = new S3Client({ endpoint: `https://s3.${region}.strg.com`, region });
  try {
    await client.send(new GetBucketLocationCommand({ Bucket: "my-bucket" }));
  } catch (error) {
    if (error.name === "NoSuchBucket") continue;
    throw error;
  }
  console.log(`my-bucket is in ${region}`);
  break;
}
```

## Related

- [HeadBucket](https://docs.strg.com/s3-api/HeadBucket) - the same region, in the `x-amz-bucket-region` header
- [ListBuckets](https://docs.strg.com/s3-api/ListBuckets)
- [S3 API overview](https://docs.strg.com/s3-api/overview#regions-and-endpoints) - regions and their endpoints
- [Access keys](https://docs.strg.com/access-keys)
