Note
This repository was branched out of storiny/web which was originally a monolith. If you're looking for the original git history before the split, you can find it over on the original repository.
Discovery microservice powers embedding of third-party content on Storiny.
- Framework: Actix Web serves our HTTP endpoints and middlewares
- State & caching: Redis handles rate limiting
- Metadata & DOM parsing: Visdom, html5ever, and
markup5ever_rcdomfor parsing, querying and safely manipulating HTML DOM nodes - HTTP client: reqwest for making HTTP requests to oEmbed endpoints and web pages
- Serialization:
serdeandserde_jsonfor mapping oEmbed specifications into typed Rust structures - Telemetry: Sentry for tracing, monitoring, and capturing errors in production
The heart of this repository is its embed resolution logic (src/routes/embed.rs and src/utils/). Whenever a user pastes a link into a story/document, this service determines exactly how to render it:
- as a rich interactive iframe
- a native video
- a photo
- or a standard link card
-
Request & URL decompression: When the client requests an embed from the frontend, they pass an LZ-compressed URL to our
/embed/{compressed_url}endpoint. Inside the route handler, we uselz-strto decompress the string back into a valid URL. This simplifies caching behaviour as all of our/embed/endpoints are heavily cached to prevent third-party rate limits. -
Provider resolution (
providers.rs): We maintain a curated registry of supported oEmbed providers insrc/providers/providers.json. The decompressed URL is matched against pre compiled Regex schemas to see if it belongs to a known provider (like YouTube, Twitter, Spotify...).- If a match is found, we know exactly which
endpointto hit and whether the provider supports light/dark binary themes. - If no match is found, we immediately fallback to our custom metadata scraper.
- If a match is found, we know exactly which
-
oEmbed fetching & parsing (
spec.rs): For supported providers, we make a request to their oEmbed endpoint. The JSON response is parsed into ourEmbedResponseandEmbedTypeenums (Photo,Video,Link,Rich).- Based on the
EmbedType, we parse the returned HTML usingvisdom, inject our own iframe styling, apply responsive aspect ratio paddings, and safely sanitize the output. - The heavily customized HTML (or raw JSON for scripted embeds) is then piped through the
sailfishtemplating engine and returned to the client.
- Based on the
-
Metadata fallback: If the link isn't supported by an oEmbed provider or if the provider returns a generic
Linktype, we fall back toget_metadata. This utility fetches the raw HTML of the webpage and extracts opengraph (og:) tags, Twitter card tags, titles and descriptions; returning a JSON metadata payload for rendering link preview cards on the frontend.
src/: The microserviceproviders/: Provider definitions and theproviders.jsonregistry. Compiles Regex matchers on bootroutes/: HTTP handlers and controllersutils/: Utilitiesmiddlewares/: Actix middlewares (rate limiting)spec.rs: Strictly typed struct definitions for the standard oEmbed specification
GET /embed/{compressed_url}: Takes an LZ-compressed URL, resolves its provider, fetches the oEmbed data or falls back to raw metadata scraping and returns the sanitized HTML (or JSON for scripted embeds) for embedding on the frontend. This endpoint is heavily cached (using Cloudflare) to prevent third-party rate limits.GET /provider_check/{compressed_url}: Checks whether an embed provide is supported. Decompresses the URL and checks it against ourproviders.jsonregistry. Returns anOK ({provider_name})response if supported, or an error otherwise.GET /health: Health check endpoint. ReturnsOK.
- Rust
- Redis
- Just: a handy command runner (install via
cargo install just)
Copy the mapping file and fill in your own environment variables:
cp .env.mapping .envFire up the development server with host reload (requires cargo-watch and optionally bunyan for pretty logs):
just devWe use cargo-nextest for running our test suites:
just test