---
name: azion-use-a-bucket-as-an-application-origin
description: >-
  Serve the objects of an Object Storage bucket through an application, with a storage connector and a Rules Engine rule that sends requests to it.
---

# Use a bucket as an application origin

You can serve the objects of an [Object Storage](/en/documentation/platform/object-storage/) bucket through an [application](/en/documentation/platform/applications/) by pairing a [connector](/en/documentation/platform/connectors/) to the bucket with a [Rules Engine](/en/documentation/platform/applications/rules-engine/) rule. A request to the domain of the [workload](/en/documentation/platform/workloads/) that serves the application then returns the object stored under the matching key. To connect an application to an HTTP server instead, refer to [Connect an application to an origin](/en/documentation/guides/application-development/getting-started/work-with-origins/).

An account that [has not migrated to API v4](/en/documentation/guides/application-security/access-and-compliance/verify-account-migration/) builds the same path through the legacy Origins of the application. For more information, refer to [Origins](/en/documentation/platform/connectors/origins/).

---

Choose the interface you work in. The prerequisites and the procedures change with your choice.

## Prerequisites

- A bucket whose `workloads_access` is `read_only` or `read_write`. A `restricted` bucket cannot back an application. To create a bucket, refer to [Object Storage quickstart](/en/documentation/platform/object-storage/quickstart/).
- An application served by a workload. To create both, refer to [Applications quickstart](/en/documentation/platform/applications/quickstart/).
- A personal token, sent in the `Authorization` header as `Token [TOKEN VALUE]`, because this page uploads the objects with the API. To create a token, refer to [Manage a personal token](/en/documentation/guides/platform/account-and-billing/personal-tokens/).
- `curl`, or another HTTP client.

**Console**

- Access to Azion Console. To sign in, refer to [Access Azion Console](/en/documentation/guides/platform/account-and-billing/how-to-access-azion-console/).

**API**

- The ID of the application. Azion Console shows it in the address of the application's page, after `/applications/edit/`.

> **Caution**
>
> An application that serves a `read_write` bucket lets any request that reaches it modify the bucket, for example by overwriting an object. Serve static content from a `read_only` bucket, and [put a function in front of the bucket](/en/documentation/guides/application-development/data/auth-layer-object-storage-functions/) when a path has to accept writes. For more information, refer to [Object Storage best practices](/en/documentation/platform/object-storage/best-practices/).

---

## Upload the objects to serve

The connector serves what the bucket already holds, so the objects go in first. The example on this page serves a page of two objects, both stored under the `src` prefix of a bucket named `app-origin`:

```text
src/index.html
src/styles/style.css
```

In a local `src` directory, create `index.html`. The page links its stylesheet by a relative path:

```html
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
    <link rel="stylesheet" href="styles/style.css">
</head>
<body>
    <h1>Hello world!</h1>
    <p>I am an object from a bucket.</p>
</body>
</html>
```

In a `styles` directory inside `src`, create `style.css`, the file the page links to:

```css
body {
  background-color: black;
}

h1,
p {
  color: white;
}
```

To upload the HTML file with the API, send a `POST` request with the object key in the path. `Content-Type` sets the type the object is stored and served with:

```bash
curl --request POST \
  --url https://api.azion.com/v4/workspace/storage/buckets/app-origin/objects/src/index.html \
  --header 'Accept: application/json' \
  --header 'Authorization: Token [TOKEN VALUE]' \
  --header 'Content-Type: text/html' \
  --data-binary '@./src/index.html'
```

The API answers `201` with the key the object is stored under:

```json
{
  "state": "executed",
  "data": {
    "object_key": "src/index.html"
  }
}
```

To upload the stylesheet, send the same request with its own key and type:

```bash
curl --request POST \
  --url https://api.azion.com/v4/workspace/storage/buckets/app-origin/objects/src/styles/style.css \
  --header 'Accept: application/json' \
  --header 'Authorization: Token [TOKEN VALUE]' \
  --header 'Content-Type: text/css' \
  --data-binary '@./src/styles/style.css'
```

The response carries the key of the second object:

```json
{
  "state": "executed",
  "data": {
    "object_key": "src/styles/style.css"
  }
}
```

The bucket holds the two objects. The `src/` segment of each key is part of the key, not a folder, and the platform creates it with the object. Without a `Content-Type` header, the platform detects the type of the object. Azion Console and the Azion CLI upload objects too. For more information, refer to [Object Storage quickstart](/en/documentation/platform/object-storage/quickstart/).

---

## Create a connector to the bucket

A connector to a bucket names the bucket an application reads from and the prefix inside it. The prefix sets where the application's paths start. With the prefix `/src`, the object stored under `src/index.html` answers at `/index.html`, and `src/styles/style.css` answers at `/styles/style.css`. The prefix is optional in the API and required in Azion Console.

In Azion Console, you set up connectors in the Connectors menu, not in a tab of the application. For each field of the Console form and of the request body, refer to [Connector settings](/en/documentation/platform/connectors/settings/#storage).

**Console**

To create the connector in Azion Console:

1. **Open the Connectors page**

   Access [Azion Console](https://console.azion.com/) > **Connectors**.

2. **Start a new connector**

3. **Name the connector**

   In the **General** section, enter `app-origin-connector` in **Name**.

4. **Select the Object Storage type**

   In the **Connector Type** section, select *Object Storage*.

5. **Select the bucket**

   Select `app-origin` as the bucket the connector reads from.

6. **Set the prefix**

   Enter `/src` in **Prefix**, the prefix the objects were uploaded under.

7. **Select Create**

Azion Console shows `Connector successfully created`.

**API**

In the API, the connector's `type` is `storage`, and its `attributes` carry `bucket`, the name of the bucket, and `prefix`. For the example on this page, `bucket` is `app-origin` and `prefix` is `/src`.

Create the connector with a `POST` request to `/v4/workspace/connectors`. Then copy the ID of the connector, which the API returns in `data.id`: the rule that sends requests to the bucket names the connector by this ID.

---

## Send requests to the bucket

A connector receives no request until a rule sets it. The rule in this section runs in the Request Phase of the application. Its criterion matches every path, with the `${uri}` variable, the `starts_with` operator, and `/` as the argument, so the whole application reads from the bucket. Its behavior sets the connector.

The `${uri}` variable works on every application. A criterion on `${request_uri}` needs [Application Accelerator](/en/documentation/platform/applications/application-accelerator/quickstart/) on the application. For every variable and operator, refer to [Rules Engine for Applications](/en/documentation/platform/applications/rules-engine/#criteria).

**Console**

To create the rule in Azion Console:

1. **Open the application**

   Access [Azion Console](https://console.azion.com/) > **Applications**, then select your application.

2. **Select the Rules Engine tab**

3. **Start a rule**

   Select **+ Rule**.

4. **Name the rule**

   In the **General** section, enter a **Name**, such as `serve-the-bucket`.

5. **Select the phase**

   In the **Phase** section, select *Request Phase*. A rule keeps the phase it is created in.

6. **Set the criterion**

   In the **Criteria** section, set the variable to `${uri}`, the operator to `starts_with`, and the argument to `/`.

7. **Set the connector**

   In the **Behaviors** section, select *Set Connector*, then select the connector to the bucket in **Connector**.

8. **Save the rule**

   Select **Save**.

The rule appears in the **Rules Engine** tab of the application, under **Request**.

**API**

To create the rule with the API, send a `POST` request to the `request_rules` endpoint of the application. Replace `<application-id>` with the ID of your application, and `<connector-id>` with the ID of the connector to the bucket:

```bash
curl --request POST \
  --url https://api.azion.com/v4/workspace/applications/<application-id>/request_rules \
  --header 'Accept: application/json' \
  --header 'Authorization: Token [TOKEN VALUE]' \
  --header 'Content-Type: application/json' \
  --data '{
  "name": "serve-the-bucket",
  "active": true,
  "criteria": [
    [
      {
        "variable": "${uri}",
        "conditional": "if",
        "operator": "starts_with",
        "argument": "/"
      }
    ]
  ],
  "behaviors": [
    {
      "type": "set_connector",
      "attributes": {
        "value": <connector-id>
      }
    }
  ]
}'
```

The API answers `202` and returns the rule:

```json
{
  "state": "pending",
  "data": {
    "id": <rule-id>,
    "name": "serve-the-bucket",
    "active": true,
    "criteria": [
      [
        {
          "conditional": "if",
          "variable": "${uri}",
          "operator": "starts_with",
          "argument": "/"
        }
      ]
    ],
    "behaviors": [
      {
        "type": "set_connector",
        "attributes": {
          "value": <connector-id>
        }
      }
    ],
    "description": "",
    "order": 0,
    "last_editor": "user@example.com",
    "last_modified": "2026-01-01T12:00:26.750242Z",
    "created_at": "2026-01-01T12:00:26.750262Z"
  }
}
```

The rule is the first of the application's Request Phase, at `order` `0`.

For the behavior and its attributes, refer to [Set Connector](/en/documentation/platform/applications/rules-engine/#set-connector).

---

## Confirm that the application serves the bucket

The rule takes some time to propagate. Until then, the domain of the workload does not answer with the objects.

To confirm the delivery path, request the page through the domain of your workload, with that domain in place of `<your-workload-domain>`:

```bash
curl https://<your-workload-domain>/index.html
```

The response body is the object stored under `src/index.html`, which the `/src` prefix serves at `/index.html`. It carries the heading `Hello world!` and the paragraph `I am an object from a bucket.` A workload's domain ends in `.map.azionedge.net`, and the API returns it in `workload_domain` when it creates the workload.

Go to the same address in a browser. The browser renders the page with the stylesheet applied, which it loads from `/styles/style.css` under the same prefix.

If the domain does not return the object yet, the rule has not propagated. Send the request again, and look for another cause only after that. For more information, refer to [Troubleshoot Applications](/en/documentation/platform/applications/troubleshooting/).

---

## Next steps

- [Cache settings](/en/documentation/platform/applications/cache/cache-settings.md): Set how long the objects the application serves stay cached.
- [Connectors](/en/documentation/platform/connectors.md): Every field of a connector to a bucket, and the other connector types.
- [How Object Storage works](/en/documentation/platform/object-storage/how-it-works.md): What the access level changes, and the path a request takes to an object.
- [Buckets and objects](/en/documentation/platform/object-storage/buckets-and-objects.md): Bucket names, access levels, object keys, and prefixes.
