Update documentation
This commit is contained in:
@@ -43,6 +43,14 @@
|
||||
<li><a href="#metrics">Metrics History</a></li>
|
||||
<li><a href="#operation-metrics">Operation Metrics</a></li>
|
||||
<li><a href="#troubleshooting">Troubleshooting</a></li>
|
||||
<li><a href="#health-check">Health Check</a></li>
|
||||
<li><a href="#object-lock">Object Lock & Retention</a></li>
|
||||
<li><a href="#access-logging">Access Logging</a></li>
|
||||
<li><a href="#notifications">Notifications & Webhooks</a></li>
|
||||
<li><a href="#select-content">SelectObjectContent</a></li>
|
||||
<li><a href="#advanced-ops">Advanced Operations</a></li>
|
||||
<li><a href="#acls">Access Control Lists</a></li>
|
||||
<li><a href="#tagging">Object & Bucket Tagging</a></li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
@@ -1694,6 +1702,403 @@ curl "{{ api_base | replace('/api', '/ui') }}/metrics/operations/history?hours=6
|
||||
</div>
|
||||
</div>
|
||||
</article>
|
||||
<article id="health-check" class="card shadow-sm docs-section">
|
||||
<div class="card-body">
|
||||
<div class="d-flex align-items-center gap-2 mb-3">
|
||||
<span class="docs-section-kicker">17</span>
|
||||
<h2 class="h4 mb-0">Health Check Endpoint</h2>
|
||||
</div>
|
||||
<p class="text-muted">The API exposes a health check endpoint for monitoring and load balancer integration.</p>
|
||||
|
||||
<pre class="mb-3"><code class="language-bash"># Check API health
|
||||
curl {{ api_base }}/myfsio/health
|
||||
|
||||
# Response
|
||||
{"status": "ok", "version": "0.1.7"}</code></pre>
|
||||
|
||||
<p class="small text-muted mb-3">Use this endpoint for:</p>
|
||||
<ul class="small text-muted mb-0">
|
||||
<li>Load balancer health checks</li>
|
||||
<li>Kubernetes liveness/readiness probes</li>
|
||||
<li>Monitoring system integration (Prometheus, Datadog, etc.)</li>
|
||||
</ul>
|
||||
</div>
|
||||
</article>
|
||||
<article id="object-lock" class="card shadow-sm docs-section">
|
||||
<div class="card-body">
|
||||
<div class="d-flex align-items-center gap-2 mb-3">
|
||||
<span class="docs-section-kicker">18</span>
|
||||
<h2 class="h4 mb-0">Object Lock & Retention</h2>
|
||||
</div>
|
||||
<p class="text-muted">Object Lock prevents objects from being deleted or overwritten for a specified retention period.</p>
|
||||
|
||||
<h3 class="h6 text-uppercase text-muted mt-4">Retention Modes</h3>
|
||||
<div class="table-responsive mb-3">
|
||||
<table class="table table-sm table-bordered small">
|
||||
<thead class="table-light">
|
||||
<tr>
|
||||
<th>Mode</th>
|
||||
<th>Description</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td><strong>GOVERNANCE</strong></td>
|
||||
<td>Objects can't be deleted by normal users, but admins with bypass permission can override</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><strong>COMPLIANCE</strong></td>
|
||||
<td>Objects can't be deleted or overwritten by anyone until the retention period expires</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
|
||||
<h3 class="h6 text-uppercase text-muted mt-4">API Usage</h3>
|
||||
<pre class="mb-3"><code class="language-bash"># Set object retention
|
||||
curl -X PUT "{{ api_base }}/<bucket>/<key>?retention" \
|
||||
-H "Content-Type: application/json" \
|
||||
-H "X-Access-Key: <key>" -H "X-Secret-Key: <secret>" \
|
||||
-d '{"Mode": "GOVERNANCE", "RetainUntilDate": "2025-12-31T23:59:59Z"}'
|
||||
|
||||
# Enable legal hold (indefinite protection)
|
||||
curl -X PUT "{{ api_base }}/<bucket>/<key>?legal-hold" \
|
||||
-H "Content-Type: application/json" \
|
||||
-H "X-Access-Key: <key>" -H "X-Secret-Key: <secret>" \
|
||||
-d '{"Status": "ON"}'
|
||||
|
||||
# Get legal hold status
|
||||
curl "{{ api_base }}/<bucket>/<key>?legal-hold" \
|
||||
-H "X-Access-Key: <key>" -H "X-Secret-Key: <secret>"</code></pre>
|
||||
|
||||
<div class="alert alert-light border mb-0">
|
||||
<div class="d-flex gap-2">
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" class="bi bi-info-circle text-muted mt-1 flex-shrink-0" viewBox="0 0 16 16">
|
||||
<path d="M8 15A7 7 0 1 1 8 1a7 7 0 0 1 0 14zm0 1A8 8 0 1 0 8 0a8 8 0 0 0 0 16z"/>
|
||||
<path d="m8.93 6.588-2.29.287-.082.38.45.083c.294.07.352.176.288.469l-.738 3.468c-.194.897.105 1.319.808 1.319.545 0 1.178-.252 1.465-.598l.088-.416c-.2.176-.492.246-.686.246-.275 0-.375-.193-.304-.533L8.93 6.588zM9 4.5a1 1 0 1 1-2 0 1 1 0 0 1 2 0z"/>
|
||||
</svg>
|
||||
<div>
|
||||
<strong>Legal Hold:</strong> Provides indefinite protection independent of retention settings. Use for litigation holds or regulatory requirements.
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</article>
|
||||
<article id="access-logging" class="card shadow-sm docs-section">
|
||||
<div class="card-body">
|
||||
<div class="d-flex align-items-center gap-2 mb-3">
|
||||
<span class="docs-section-kicker">19</span>
|
||||
<h2 class="h4 mb-0">Access Logging</h2>
|
||||
</div>
|
||||
<p class="text-muted">Enable S3-style access logging to track all requests to your buckets for audit and analysis.</p>
|
||||
|
||||
<pre class="mb-3"><code class="language-bash"># Enable access logging
|
||||
curl -X PUT "{{ api_base }}/<bucket>?logging" \
|
||||
-H "Content-Type: application/json" \
|
||||
-H "X-Access-Key: <key>" -H "X-Secret-Key: <secret>" \
|
||||
-d '{
|
||||
"LoggingEnabled": {
|
||||
"TargetBucket": "log-bucket",
|
||||
"TargetPrefix": "logs/my-bucket/"
|
||||
}
|
||||
}'
|
||||
|
||||
# Get logging configuration
|
||||
curl "{{ api_base }}/<bucket>?logging" \
|
||||
-H "X-Access-Key: <key>" -H "X-Secret-Key: <secret>"</code></pre>
|
||||
|
||||
<h3 class="h6 text-uppercase text-muted mt-4">Log Contents</h3>
|
||||
<p class="small text-muted mb-0">Logs include: timestamp, bucket, key, operation type, request ID, requester, source IP, HTTP status, error codes, bytes transferred, timing, referrer, and User-Agent.</p>
|
||||
</div>
|
||||
</article>
|
||||
<article id="notifications" class="card shadow-sm docs-section">
|
||||
<div class="card-body">
|
||||
<div class="d-flex align-items-center gap-2 mb-3">
|
||||
<span class="docs-section-kicker">20</span>
|
||||
<h2 class="h4 mb-0">Notifications & Webhooks</h2>
|
||||
</div>
|
||||
<p class="text-muted">Configure event notifications to trigger webhooks when objects are created or deleted.</p>
|
||||
|
||||
<h3 class="h6 text-uppercase text-muted mt-4">Supported Events</h3>
|
||||
<div class="table-responsive mb-3">
|
||||
<table class="table table-sm table-bordered small">
|
||||
<thead class="table-light">
|
||||
<tr>
|
||||
<th>Event Type</th>
|
||||
<th>Description</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td><code>s3:ObjectCreated:*</code></td>
|
||||
<td>Any object creation (PUT, POST, COPY, multipart)</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><code>s3:ObjectRemoved:*</code></td>
|
||||
<td>Any object deletion</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
|
||||
<pre class="mb-3"><code class="language-bash"># Set notification configuration
|
||||
curl -X PUT "{{ api_base }}/<bucket>?notification" \
|
||||
-H "Content-Type: application/json" \
|
||||
-H "X-Access-Key: <key>" -H "X-Secret-Key: <secret>" \
|
||||
-d '{
|
||||
"TopicConfigurations": [{
|
||||
"Id": "upload-notify",
|
||||
"TopicArn": "https://webhook.example.com/s3-events",
|
||||
"Events": ["s3:ObjectCreated:*"],
|
||||
"Filter": {
|
||||
"Key": {
|
||||
"FilterRules": [
|
||||
{"Name": "prefix", "Value": "uploads/"},
|
||||
{"Name": "suffix", "Value": ".jpg"}
|
||||
]
|
||||
}
|
||||
}
|
||||
}]
|
||||
}'</code></pre>
|
||||
|
||||
<div class="alert alert-warning border-warning bg-warning-subtle mb-0">
|
||||
<div class="d-flex gap-2">
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" class="bi bi-exclamation-triangle mt-1" viewBox="0 0 16 16">
|
||||
<path d="M7.938 2.016A.13.13 0 0 1 8.002 2a.13.13 0 0 1 .063.016.146.146 0 0 1 .054.057l6.857 11.667c.036.06.035.124.002.183a.163.163 0 0 1-.054.06.116.116 0 0 1-.066.017H1.146a.115.115 0 0 1-.066-.017.163.163 0 0 1-.054-.06.176.176 0 0 1 .002-.183L7.884 2.073a.147.147 0 0 1 .054-.057zm1.044-.45a1.13 1.13 0 0 0-1.96 0L.165 13.233c-.457.778.091 1.767.98 1.767h13.713c.889 0 1.438-.99.98-1.767L8.982 1.566z"/>
|
||||
<path d="M7.002 12a1 1 0 1 1 2 0 1 1 0 0 1-2 0zM7.1 5.995a.905.905 0 1 1 1.8 0l-.35 3.507a.552.552 0 0 1-1.1 0L7.1 5.995z"/>
|
||||
</svg>
|
||||
<div>
|
||||
<strong>Security:</strong> Webhook URLs are validated to prevent SSRF attacks. Internal/private IP ranges are blocked.
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</article>
|
||||
<article id="select-content" class="card shadow-sm docs-section">
|
||||
<div class="card-body">
|
||||
<div class="d-flex align-items-center gap-2 mb-3">
|
||||
<span class="docs-section-kicker">21</span>
|
||||
<h2 class="h4 mb-0">SelectObjectContent (SQL)</h2>
|
||||
</div>
|
||||
<p class="text-muted">Query CSV, JSON, or Parquet files directly using SQL without downloading the entire object.</p>
|
||||
|
||||
<div class="alert alert-info border small mb-3">
|
||||
<strong>Prerequisite:</strong> Requires DuckDB to be installed (<code>pip install duckdb</code>)
|
||||
</div>
|
||||
|
||||
<pre class="mb-3"><code class="language-bash"># Query a CSV file
|
||||
curl -X POST "{{ api_base }}/<bucket>/data.csv?select" \
|
||||
-H "Content-Type: application/json" \
|
||||
-H "X-Access-Key: <key>" -H "X-Secret-Key: <secret>" \
|
||||
-d '{
|
||||
"Expression": "SELECT name, age FROM s3object WHERE age > 25",
|
||||
"ExpressionType": "SQL",
|
||||
"InputSerialization": {
|
||||
"CSV": {"FileHeaderInfo": "USE", "FieldDelimiter": ","}
|
||||
},
|
||||
"OutputSerialization": {"JSON": {}}
|
||||
}'</code></pre>
|
||||
|
||||
<h3 class="h6 text-uppercase text-muted mt-4">Supported Formats</h3>
|
||||
<div class="row g-2 mb-0">
|
||||
<div class="col-md-4">
|
||||
<div class="bg-light rounded p-2 small text-center">
|
||||
<strong>CSV</strong><br><span class="text-muted">Headers, delimiters</span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-md-4">
|
||||
<div class="bg-light rounded p-2 small text-center">
|
||||
<strong>JSON</strong><br><span class="text-muted">Document or lines</span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-md-4">
|
||||
<div class="bg-light rounded p-2 small text-center">
|
||||
<strong>Parquet</strong><br><span class="text-muted">Auto schema</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</article>
|
||||
<article id="advanced-ops" class="card shadow-sm docs-section">
|
||||
<div class="card-body">
|
||||
<div class="d-flex align-items-center gap-2 mb-3">
|
||||
<span class="docs-section-kicker">22</span>
|
||||
<h2 class="h4 mb-0">Advanced S3 Operations</h2>
|
||||
</div>
|
||||
<p class="text-muted">Copy objects, upload part copies, and use range requests for partial downloads.</p>
|
||||
|
||||
<h3 class="h6 text-uppercase text-muted mt-4">CopyObject</h3>
|
||||
<pre class="mb-3"><code class="language-bash"># Copy within same bucket
|
||||
curl -X PUT "{{ api_base }}/<bucket>/copy-of-file.txt" \
|
||||
-H "X-Access-Key: <key>" -H "X-Secret-Key: <secret>" \
|
||||
-H "x-amz-copy-source: /<bucket>/original-file.txt"
|
||||
|
||||
# Copy with metadata replacement
|
||||
curl -X PUT "{{ api_base }}/<bucket>/file.txt" \
|
||||
-H "X-Access-Key: <key>" -H "X-Secret-Key: <secret>" \
|
||||
-H "x-amz-copy-source: /<bucket>/file.txt" \
|
||||
-H "x-amz-metadata-directive: REPLACE" \
|
||||
-H "x-amz-meta-newkey: newvalue"</code></pre>
|
||||
|
||||
<h3 class="h6 text-uppercase text-muted mt-4">UploadPartCopy</h3>
|
||||
<p class="small text-muted">Copy data from an existing object into a multipart upload part:</p>
|
||||
<pre class="mb-3"><code class="language-bash"># Copy bytes 0-10485759 from source as part 1
|
||||
curl -X PUT "{{ api_base }}/<bucket>/<key>?uploadId=X&partNumber=1" \
|
||||
-H "X-Access-Key: <key>" -H "X-Secret-Key: <secret>" \
|
||||
-H "x-amz-copy-source: /source-bucket/source-file.bin" \
|
||||
-H "x-amz-copy-source-range: bytes=0-10485759"</code></pre>
|
||||
|
||||
<h3 class="h6 text-uppercase text-muted mt-4">Range Requests</h3>
|
||||
<pre class="mb-3"><code class="language-bash"># Get first 1000 bytes
|
||||
curl "{{ api_base }}/<bucket>/<key>" \
|
||||
-H "X-Access-Key: <key>" -H "X-Secret-Key: <secret>" \
|
||||
-H "Range: bytes=0-999"
|
||||
|
||||
# Get last 500 bytes
|
||||
curl "{{ api_base }}/<bucket>/<key>" \
|
||||
-H "X-Access-Key: <key>" -H "X-Secret-Key: <secret>" \
|
||||
-H "Range: bytes=-500"</code></pre>
|
||||
|
||||
<h3 class="h6 text-uppercase text-muted mt-4">Conditional Requests</h3>
|
||||
<div class="table-responsive mb-0">
|
||||
<table class="table table-sm table-bordered small mb-0">
|
||||
<thead class="table-light">
|
||||
<tr>
|
||||
<th>Header</th>
|
||||
<th>Behavior</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td><code>If-Modified-Since</code></td>
|
||||
<td>Only download if changed after date</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><code>If-None-Match</code></td>
|
||||
<td>Only download if ETag differs</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><code>If-Match</code></td>
|
||||
<td>Only download if ETag matches</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
</article>
|
||||
<article id="acls" class="card shadow-sm docs-section">
|
||||
<div class="card-body">
|
||||
<div class="d-flex align-items-center gap-2 mb-3">
|
||||
<span class="docs-section-kicker">23</span>
|
||||
<h2 class="h4 mb-0">Access Control Lists (ACLs)</h2>
|
||||
</div>
|
||||
<p class="text-muted">ACLs provide legacy-style permission management for buckets and objects.</p>
|
||||
|
||||
<h3 class="h6 text-uppercase text-muted mt-4">Canned ACLs</h3>
|
||||
<div class="table-responsive mb-3">
|
||||
<table class="table table-sm table-bordered small">
|
||||
<thead class="table-light">
|
||||
<tr>
|
||||
<th>ACL</th>
|
||||
<th>Description</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td><code>private</code></td>
|
||||
<td>Owner gets FULL_CONTROL (default)</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><code>public-read</code></td>
|
||||
<td>Owner FULL_CONTROL, public READ</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><code>public-read-write</code></td>
|
||||
<td>Owner FULL_CONTROL, public READ and WRITE</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><code>authenticated-read</code></td>
|
||||
<td>Owner FULL_CONTROL, authenticated users READ</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
|
||||
<pre class="mb-3"><code class="language-bash"># Set bucket ACL
|
||||
curl -X PUT "{{ api_base }}/<bucket>?acl" \
|
||||
-H "X-Access-Key: <key>" -H "X-Secret-Key: <secret>" \
|
||||
-H "x-amz-acl: public-read"
|
||||
|
||||
# Set object ACL during upload
|
||||
curl -X PUT "{{ api_base }}/<bucket>/<key>" \
|
||||
-H "X-Access-Key: <key>" -H "X-Secret-Key: <secret>" \
|
||||
-H "x-amz-acl: private" \
|
||||
--data-binary @file.txt</code></pre>
|
||||
|
||||
<div class="alert alert-light border mb-0">
|
||||
<strong>Recommendation:</strong> For most use cases, prefer bucket policies over ACLs for more flexible access control.
|
||||
</div>
|
||||
</div>
|
||||
</article>
|
||||
<article id="tagging" class="card shadow-sm docs-section">
|
||||
<div class="card-body">
|
||||
<div class="d-flex align-items-center gap-2 mb-3">
|
||||
<span class="docs-section-kicker">24</span>
|
||||
<h2 class="h4 mb-0">Object & Bucket Tagging</h2>
|
||||
</div>
|
||||
<p class="text-muted">Add metadata tags to buckets and objects for organization, cost allocation, or lifecycle rule filtering.</p>
|
||||
|
||||
<h3 class="h6 text-uppercase text-muted mt-4">Object Tagging</h3>
|
||||
<pre class="mb-3"><code class="language-bash"># Set object tags
|
||||
curl -X PUT "{{ api_base }}/<bucket>/<key>?tagging" \
|
||||
-H "Content-Type: application/json" \
|
||||
-H "X-Access-Key: <key>" -H "X-Secret-Key: <secret>" \
|
||||
-d '{
|
||||
"TagSet": [
|
||||
{"Key": "Classification", "Value": "Confidential"},
|
||||
{"Key": "Owner", "Value": "john@example.com"}
|
||||
]
|
||||
}'
|
||||
|
||||
# Get object tags
|
||||
curl "{{ api_base }}/<bucket>/<key>?tagging" \
|
||||
-H "X-Access-Key: <key>" -H "X-Secret-Key: <secret>"
|
||||
|
||||
# Set tags during upload
|
||||
curl -X PUT "{{ api_base }}/<bucket>/<key>" \
|
||||
-H "X-Access-Key: <key>" -H "X-Secret-Key: <secret>" \
|
||||
-H "x-amz-tagging: Environment=Staging&Team=QA" \
|
||||
--data-binary @file.txt</code></pre>
|
||||
|
||||
<h3 class="h6 text-uppercase text-muted mt-4">Bucket Tagging</h3>
|
||||
<pre class="mb-3"><code class="language-bash"># Set bucket tags
|
||||
curl -X PUT "{{ api_base }}/<bucket>?tagging" \
|
||||
-H "Content-Type: application/json" \
|
||||
-H "X-Access-Key: <key>" -H "X-Secret-Key: <secret>" \
|
||||
-d '{
|
||||
"TagSet": [
|
||||
{"Key": "Environment", "Value": "Production"},
|
||||
{"Key": "Team", "Value": "Engineering"}
|
||||
]
|
||||
}'</code></pre>
|
||||
|
||||
<h3 class="h6 text-uppercase text-muted mt-4">Use Cases</h3>
|
||||
<div class="row g-2 mb-0">
|
||||
<div class="col-md-6">
|
||||
<ul class="small text-muted mb-0 ps-3">
|
||||
<li>Filter objects for lifecycle expiration by tag</li>
|
||||
<li>Use tag conditions in bucket policies</li>
|
||||
</ul>
|
||||
</div>
|
||||
<div class="col-md-6">
|
||||
<ul class="small text-muted mb-0 ps-3">
|
||||
<li>Group objects by project or department</li>
|
||||
<li>Trigger automation based on object tags</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</article>
|
||||
</div>
|
||||
<div class="col-xl-4 docs-sidebar-col">
|
||||
<aside class="card shadow-sm docs-sidebar">
|
||||
@@ -1716,6 +2121,14 @@ curl "{{ api_base | replace('/api', '/ui') }}/metrics/operations/history?hours=6
|
||||
<li><a href="#metrics">Metrics History</a></li>
|
||||
<li><a href="#operation-metrics">Operation Metrics</a></li>
|
||||
<li><a href="#troubleshooting">Troubleshooting</a></li>
|
||||
<li><a href="#health-check">Health Check</a></li>
|
||||
<li><a href="#object-lock">Object Lock & Retention</a></li>
|
||||
<li><a href="#access-logging">Access Logging</a></li>
|
||||
<li><a href="#notifications">Notifications & Webhooks</a></li>
|
||||
<li><a href="#select-content">SelectObjectContent</a></li>
|
||||
<li><a href="#advanced-ops">Advanced Operations</a></li>
|
||||
<li><a href="#acls">Access Control Lists</a></li>
|
||||
<li><a href="#tagging">Object & Bucket Tagging</a></li>
|
||||
</ul>
|
||||
<div class="docs-sidebar-callouts">
|
||||
<div>
|
||||
|
||||
Reference in New Issue
Block a user