> ## Documentation Index
> Fetch the complete documentation index at: https://docs.gcore.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Request and response properties

> FastEdge CDN request and response properties can be read or modified with get_property and set_property host functions.

FastEdge CDN applications read and modify request and response data through the `get_property` and `set_property` host functions. The table below lists all properties accessible through this API. HTTP headers are read and written through dedicated header methods (`get_http_request_header`, `set_http_response_header`, etc.) and are not included here.

## Available properties

| Property path | Type | Access | Available in | Description |
| - | - | - | - | - |
| `request.url` | String | Read-write | `on_http_request_headers` | Original URL path before modifications |
| `request.host` | String | Read-write | `on_http_request_headers` | Host header value |
| `request.path` | String | Read-write | `on_http_request_headers` | Request URL path |
| `request.scheme` | String | Read-only | `on_http_request_headers` | Protocol scheme (`http` or `https`) |
| `request.method` | String | Read-only | `on_http_request_headers` | HTTP method |
| `request.extension` | String | Read-only | `on_http_request_headers` | File extension from the request path |
| `request.query` | String | Read-write | `on_http_request_headers` | Query string |
| `request.country` | String | Read-only | `on_http_request_headers` | Two-letter country code, derived from client IP |
| `request.city` | String | Read-only | `on_http_request_headers` | City name, derived from client IP |
| `request.asn` | String | Read-only | `on_http_request_headers` | ASN of the network associated with the client IP |
| `request.geo.lat` | String | Read-only | `on_http_request_headers` | Latitude, derived from client IP |
| `request.geo.long` | String | Read-only | `on_http_request_headers` | Longitude, derived from client IP |
| `request.region` | String | Read-only | `on_http_request_headers` | Region, derived from client IP |
| `request.continent` | String | Read-only | `on_http_request_headers` | Continent, derived from client IP |
| `request.country.name` | String | Read-only | `on_http_request_headers` | Country name, derived from client IP |
| `nginx.log_field1` | String | Write-only | `on_http_request_headers` | Appends a value to the CDN access log. Requires [Log Uploader](/cdn/logs/raw-logs-export-cdn-resource-logs-to-your-storage). |
| `response.status` | Integer | Read-only | `on_http_response_headers`, `on_http_response_body` | HTTP response status code |

Property paths are case-sensitive.

The following example reads the client country and conditionally sets the log field:

```rust theme={null}
fn on_http_request_headers(&mut self, _: usize, _: bool) -> Action {
    if let Some(country) = self.get_property(vec!["request.country"]) {
        let code = String::from_utf8_lossy(&country);
        self.set_property(vec!["nginx.log_field1"], Some(code.as_bytes()));
    }
    Action::Continue
}
```

## Custom properties

Applications can define custom properties to pass state between related hooks. For example, a property set in `on_http_response_headers` is readable in `on_http_response_body`.

> [!WARNING]
>
> Custom properties created in `on_http_request_headers` are not available in later hooks.

The following example marks a response as Markdown in `on_http_response_headers` and reads that flag in `on_http_response_body`:

```rust theme={null}
fn on_http_response_headers(&mut self, _: usize, _: bool) -> Action {
    if let Some(content_type) = self.get_http_response_header("Content-Type") {
        if content_type.starts_with("text/plain") || content_type.starts_with("text/markdown") {
            self.set_http_response_header("Content-Length", None);
            self.set_http_response_header("Transfer-Encoding", Some("chunked"));
            self.set_http_response_header("Content-Type", Some("text/html"));
            self.set_property(vec!["response.markdown"], Some(b"true"));
        }
    }
    Action::Continue
}

fn on_http_response_body(&mut self, _: usize, _: bool) -> Action {
    if self.get_property(vec!["response.markdown"]).is_none() {
        return Action::Continue;
    }
    // convert body to HTML here
    Action::Continue
}
```
