Fetch, resize, reformat, and cache Atmosphere avatar images atp.pics
atproto

ADDED Requirements #

Requirement: Accept AT Protocol identifier as URL path segment #

The system SHALL expose a single HTTP route GET /{identifier} where {identifier} is either an AT Protocol handle or a DID. The identifier SHALL be extracted from the first path segment and passed to the resolution pipeline. All requests SHALL pass through request logging middleware before reaching the handler.

Scenario: Handle in path #

  • WHEN a request arrives at GET /alice.bsky.social
  • THEN the system SHALL treat alice.bsky.social as the identifier

Scenario: DID in path #

  • WHEN a request arrives at GET /did:plc:abc123
  • THEN the system SHALL treat did:plc:abc123 as the identifier

Scenario: Request is logged #

  • WHEN any request arrives at the handler
  • THEN the system SHALL emit a log line via the request logging middleware after the response is sent

Requirement: Accept image transform parameters via query string #

The system SHALL accept the following optional query parameters and pass them to the image transform pipeline:

Parameter Type Description
w integer Output width in pixels
h integer Output height in pixels
q integer (1–100) Output quality; default 85; ignored for PNG
f string (webp, jpg, png) Output format; default webp

Scenario: Valid transform parameters accepted #

  • WHEN the request includes valid ?w=200&h=200&q=80&f=jpg
  • THEN the system SHALL parse and apply all four parameters

Scenario: Unknown query parameters ignored #

  • WHEN the request includes query parameters not in the supported set
  • THEN the system SHALL ignore them without error

Scenario: Invalid parameter value #

  • WHEN ?w or ?h is not a positive integer, or ?q is outside 1–100, or ?f is not one of webp, jpg, png
  • THEN the system SHALL return a 400 Bad Request with a plain-text error message

Requirement: Return 302 redirect to S3 URL #

Upon successfully resolving and caching the avatar image, the system SHALL respond with 302 Found and a Location header pointing to the public S3 URL of the cached object. The response SHALL NOT include a Cache-Control header, ensuring browsers do not cache the redirect itself.

Scenario: Successful resolution returns redirect #

  • WHEN the identifier is resolved and the image is available in S3
  • THEN the system SHALL respond with 302 Found and Location: https://{bucket}.s3.{region}.amazonaws.com/avatars/{did}/{cid}/{key}

Scenario: Redirect is not cached by browser #

  • WHEN the 302 response is received by a browser
  • THEN the browser SHALL re-request the service on the next page load due to the absence of Cache-Control

Requirement: Return 404 when no avatar is found #

If resolution succeeds but the user has no avatar set on any resolver, the system SHALL respond with 404 Not Found.

Scenario: User has no avatar #

  • WHEN the profile record exists but contains no avatar blob reference
  • THEN the system SHALL respond with 404 Not Found and a plain-text message

Requirement: Return 404 when identifier cannot be resolved #

If the identifier cannot be resolved to a DID, or the DID document cannot be fetched, or no profile record exists, the system SHALL respond with 404 Not Found.

Scenario: Handle does not resolve #

  • WHEN both DNS TXT and HTTPS fallback fail for the given handle
  • THEN the system SHALL respond with 404 Not Found

Scenario: Profile record missing #

  • WHEN the PDS returns 404 for the profile record
  • THEN the system SHALL respond with 404 Not Found

Requirement: Return 502 on upstream failure #

If a PDS, plc.directory, or S3 operation fails due to a server-side or network error (not a 404), the system SHALL respond with 502 Bad Gateway.

Scenario: PDS unreachable #

  • WHEN the PDS is unreachable or returns a 5xx response
  • THEN the system SHALL respond with 502 Bad Gateway

Scenario: S3 upload fails #

  • WHEN the S3 upload fails with a non-client error
  • THEN the system SHALL respond with 502 Bad Gateway