Serve Site Path
curl --request GET \
--url https://api.example.com/site/{tape}/{path}import requests
url = "https://api.example.com/site/{tape}/{path}"
response = requests.get(url)
print(response.text)const options = {method: 'GET'};
fetch('https://api.example.com/site/{tape}/{path}', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));<?php
$curl = curl_init();
curl_setopt_array($curl, [
CURLOPT_URL => "https://api.example.com/site/{tape}/{path}",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "GET",
]);
$response = curl_exec($curl);
$err = curl_error($curl);
curl_close($curl);
if ($err) {
echo "cURL Error #:" . $err;
} else {
echo $response;
}package main
import (
"fmt"
"net/http"
"io"
)
func main() {
url := "https://api.example.com/site/{tape}/{path}"
req, _ := http.NewRequest("GET", url, nil)
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close()
body, _ := io.ReadAll(res.Body)
fmt.Println(string(body))
}HttpResponse<String> response = Unirest.get("https://api.example.com/site/{tape}/{path}")
.asString();require 'uri'
require 'net/http'
url = URI("https://api.example.com/site/{tape}/{path}")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Get.new(url)
response = http.request(request)
puts response.read_bodySite
Serve Site Path
Serve an object from a tape by path, rendered inline.
GET
/
site
/
{tape}
/
{path}
Serve Site Path
curl --request GET \
--url https://api.example.com/site/{tape}/{path}import requests
url = "https://api.example.com/site/{tape}/{path}"
response = requests.get(url)
print(response.text)const options = {method: 'GET'};
fetch('https://api.example.com/site/{tape}/{path}', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));<?php
$curl = curl_init();
curl_setopt_array($curl, [
CURLOPT_URL => "https://api.example.com/site/{tape}/{path}",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "GET",
]);
$response = curl_exec($curl);
$err = curl_error($curl);
curl_close($curl);
if ($err) {
echo "cURL Error #:" . $err;
} else {
echo $response;
}package main
import (
"fmt"
"net/http"
"io"
)
func main() {
url := "https://api.example.com/site/{tape}/{path}"
req, _ := http.NewRequest("GET", url, nil)
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close()
body, _ := io.ReadAll(res.Body)
fmt.Println(string(body))
}HttpResponse<String> response = Unirest.get("https://api.example.com/site/{tape}/{path}")
.asString();require 'uri'
require 'net/http'
url = URI("https://api.example.com/site/{tape}/{path}")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Get.new(url)
response = http.request(request)
puts response.read_bodyResolves
Name-addressed URLs revalidate rather than cache forever, because a name can be re-pointed at new content.
{path} as an object name on {tape} and serves the backing content inline, so a browser renders it in place. This is the read side of static site hosting; the same object is always reachable by track address through get object.
The same serving also answers by hostname: a request whose Host matches a configured custom domain or subdomain serves that tape from the domain root, with identical semantics and no /site prefix (custom domains).
Path resolution
An empty path or one ending in/ resolves index.html under that prefix, and the bare /site/{tape} form redirects (308) to /site/{tape}/. A path with no matching object serves the tape’s 404.html with status 404 when present, plain 404 otherwise. ?download=1 switches the response to an attachment named after the file.
Range headers work as on get object.
Response headers
| Header | Value |
|---|---|
Content-Type | from the object’s metadata, or inferred from the path extension when unknown |
ETag | the content commitment |
Cache-Control | public, max-age=60, must-revalidate |
X-Content-Type-Options | nosniff |
Content-Security-Policy | same-origin policy for served pages |
If-None-Match with the current ETag answers 304 Not Modified.
Errors
404 covers both an unknown tape path and content the network hasn’t certified yet. Everything else follows the shared error conventions. The route is metered per IP on its own site bucket (rate limits).
Example
curl -i "$TAPE_GATEWAY/site/7f3kD9mQxYz2pW8vN4cRtE5uH6bJamd9GvKq2rTeUWXs/"
Response
HTTP/2 200
content-type: text/html; charset=utf-8
etag: "HxbTgzim3nRPhWSyBEUvvteNRWLbrAxV3rDJyoW4mZ5J"
cache-control: public, max-age=60, must-revalidate
x-content-type-options: nosniff
accept-ranges: bytes