Skip to main content
GET
/
link
/
:hash
Access Public Link
curl --request GET \
  --url https://api.example.com/link/:hash
{
  "error": "<string>"
}
Download a file using its public access link hash. This endpoint validates access restrictions through middleware before serving the file.

Endpoint

GET /link/:hash

Parameters

hash
string
required
The unique hash identifier for the access link (e.g., abc123def456)

Access Restriction Flow

Before the file is served, the AccessRestrictions middleware enforces several security checks in this order:
  • Verifies the access link exists in the database
  • Returns 404 if link not found

2. File Validation

  • Confirms the linked file exists
  • Returns 404 if file not found

3. Public Access Check

  • Both the file and the access link must have public: true
  • Returns 403 with message "Access denied: file or access is not public" if either is private

4. Subnet Restriction

  • If subnets array is non-empty, validates client IP against CIDR ranges
  • Parses each subnet as CIDR notation (e.g., 192.168.1.0/24)
  • Returns 403 with message "Access restricted to specific subnets" if IP not in allowed subnets
  • Skips check if subnets array is empty
Source: middleware/access_restrictions.go:82-96

5. IP Whitelist

  • If ips array is non-empty, validates client IP against exact matches
  • Returns 403 with message "Access restricted to specific IPs" if IP not in whitelist
  • Skips check if ips array is empty
Source: middleware/access_restrictions.go:98-111

6. Expiration Check

  • If expires field is set, parses as RFC3339 timestamp
  • Returns 403 with message "Access link has expired" if current time is past expiration
  • Skips check if expires is empty string
Source: middleware/access_restrictions.go:61-71

7. One-Time Use Check

  • If one_time_use: true and used: true, denies access
  • Returns 403 with message `“Access link has already been used”
  • After successful access, marks used: true in database
Source: middleware/access_restrictions.go:73-80

8. TTL (Time-To-Live) Decrement

  • If enable_ttl: true and ttl > 0, decrements TTL by 1
  • If TTL reaches 0, returns 403 with message "Access link has reached its TTL limit"
  • Persists updated TTL value to database on each access
  • No action if enable_ttl: false
Source: middleware/access_restrictions.go:113-124
The TTL counter decrements before checking if it has reached zero, meaning a TTL of 1 allows exactly one access.

Response

Success Response (200)

On successful validation, the file is served as a download with proper headers:
  • Content-Disposition: attachment; filename="{original_filename}"
  • File served from: /app/data/uploads/{username}/{filename}
The response streams the file binary content directly. Source: controllers/link.go:109-110

Error Responses

error
string
Error message describing why access was denied
404 Not Found
{
  "error": "Access link not found"
}
Or:
{
  "error": "File not found"
}
403 Forbidden Various restriction failures:
{
  "error": "Access denied: file or access is not public"
}
{
  "error": "Access restricted to specific subnets"
}
{
  "error": "Access restricted to specific IPs"
}
{
  "error": "Access link has expired"
}
{
  "error": "Access link has already been used"
}
{
  "error": "Access link has reached its TTL limit"
}

Implementation Notes

The controller at controllers/link.go:25 contains commented-out validation logic. All access restriction checks are now handled by the AccessRestrictions middleware at middleware/access_restrictions.go:14.

Side Effects

  • One-time use: Sets used: true after successful access (persisted to database)
  • TTL: Decrements counter by 1 on each access attempt (persisted to database)

Client IP Detection

Client IP is extracted using Gin’s c.ClientIP() which respects:
  • X-Forwarded-For header
  • X-Real-IP header
  • Remote address as fallback

Example Usage

curl -O -J https://api.defdrive.com/link/abc123def456
This downloads the file with its original filename preserved via the Content-Disposition header.

Build docs developers (and LLMs) love