{"id":22546629,"url":"https://github.com/prx/dovetail-cdn-viewer-request","last_synced_at":"2025-03-28T08:45:57.957Z","repository":{"id":41996817,"uuid":"368258245","full_name":"PRX/dovetail-cdn-viewer-request","owner":"PRX","description":"CloudFront Function handling Dovetail CDN viewer requests","archived":false,"fork":false,"pushed_at":"2024-08-30T15:40:37.000Z","size":244,"stargazers_count":0,"open_issues_count":1,"forks_count":0,"subscribers_count":8,"default_branch":"main","last_synced_at":"2025-02-02T09:31:11.565Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":"https://dovetail.prx.org","language":"JavaScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"agpl-3.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/PRX.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2021-05-17T16:48:52.000Z","updated_at":"2024-08-30T15:40:38.000Z","dependencies_parsed_at":"2024-01-23T19:27:18.827Z","dependency_job_id":"70df77be-f9bf-4efc-a2ce-2f7d83714bd8","html_url":"https://github.com/PRX/dovetail-cdn-viewer-request","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/PRX%2Fdovetail-cdn-viewer-request","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/PRX%2Fdovetail-cdn-viewer-request/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/PRX%2Fdovetail-cdn-viewer-request/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/PRX%2Fdovetail-cdn-viewer-request/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/PRX","download_url":"https://codeload.github.com/PRX/dovetail-cdn-viewer-request/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":245999320,"owners_count":20707554,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2024-12-07T15:08:24.722Z","updated_at":"2025-03-28T08:45:57.934Z","avatar_url":"https://github.com/PRX.png","language":"JavaScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Dovetail CDN Viewer Request\n\n[CloudFront Function](https://docs.aws.amazon.com/AmazonCloudFront/latest/DeveloperGuide/cloudfront-functions.html)\nto verify and normalize all requests to the [Dovetail CDN](https://github.com/PRX/Infrastructure/tree/main/cdn/dovetail-cdn).\n\nThis function is tied to the CloudFront `viewer-request` event, verifies the\nrequest, redirects old/expired urls, and normalizes the requested paths.\n\n![image](https://user-images.githubusercontent.com/1410587/121265887-cb73eb80-c876-11eb-8cd8-7292da09208c.png)\n\n## Configuration\n\nAs this is a CloudFront Function, you must hardcode everything instead of any\nconfigurations. That said, we use a [Custom::CodeFetcher](https://github.com/PRX/Infrastructure/tree/main/cdn/dovetail-cdn) and a bit of python in CloudFormation to replace values at deploy time.\n\n- `\u003cEXPIRED_REDIRECT_PREFIX\u003e` - the scheme, domain, and optional path to\n  redirect requests back to if your url `?exp=` is expired.\n\n## Usage\n\n### Inputs\n\nThe lambda is invoked with a CloudFront Function [viewer-request event](https://docs.aws.amazon.com/AmazonCloudFront/latest/DeveloperGuide/functions-event-structure.html#functions-event-structure-request)\n_(which is **NOT** the same as an edge function viewer-request event!!!)_ of the\nstructure:\n\n```js\n{\n  \"request\": {\n    \"method\": \"GET\",\n    \"uri\": \"/\u003cpodcast_id\u003e/\u003cepisode_guid\u003e/\u003carrangement_digest\u003e/filename.mp3\",\n    \"querystring\": {\n      \"exp\": { \"value\": \"99999999\" },\n      \"force\": { \"value\": \"1\" }\n    }\n  }\n}\n```\n\nThe `uri` may also optionally include a `\u003cfeed_id\u003e` token, to indicate this came\nfrom a non-default feed (such as \"adfree\"):\n\n```\n\"uri\": \"/\u003cpodcast_id\u003e/\u003cfeed_id\u003e/\u003cepisode_guid\u003e/\u003carrangement_digest\u003e/filename.mp3\"\n```\n\nAND the `uri` may also also optionally start with an `\u003cbehavior_prefix\u003e` token,\nto indicate which \"stack\" the Dovetail Router redirect originated from. This\nwill tie the CloudFront behavior + realtime-logs to that specific dovetail\nstack within a region, for analytics processing. This token must start with a\nlowercase character, not a number.\n\nThe `exp` is a (currently optional) epoch seconds timestamp, when this url will\nno longer be valid and must be redirected back for a newer arrangement.\n\nThe `force` param optionally forces an edge-server cache miss, so we have to go\nall the way down through the origin-request and arranger lambdas to restitch.\n\n### Work\n\n1. Check that the `uri` looks valid, and 404 right away on unknown paths.\n2. Verify that the `?exp=\u003cepoch_seconds\u003e` param is still valid. If the url has\n   expired, redirect back to `EXPIRED_REDIRECT_PREFIX` for a new redirect.\n3. Normalize `uri` so that we don't make a bunch of redundant requests for the\n   same `arrangement_digest`. The [dovetail-cdn-origin-request](https://github.com/PRX/dovetail-cdn-origin-request)\n   expects `/\u003cpodcast_id\u003e/\u003cepisode_guid\u003e/\u003cdigest\u003e` ... so rewrite to that.\n4. If we're `?force`-ing, append a random `/random-\u003crandom-stuff\u003e` string to\n   the request `uri`. The CloudFront edge server will not have that full path\n   cached, so the request will fall through to origin-requesting.\n5. Return the rewritten request.\n\n### Error Handling\n\nThis function is very simple, and generally should never error. But if it did,\nthe user would just get a 500.\n\n## Development\n\nTests can only be run locally. And since this is a CloudFront Function, it's not\nreally modern javascript, so you can't do any real linting and your syntax is\nlimited. But `prettier` is installed, so at least use that!\n\n```sh\nnvm use\nyarn\nnpm test\n\n# lint things up before committing\nnpm run lint\n```\n\n## Deploying\n\nThis function's code is pulled directly from Github via our Infrastructure\n[Custom::CodeFetcher](https://github.com/PRX/Infrastructure/blob/master/cdn/dovetail3-cdn.yml).\nYou will need to change the `Cycle` param and redeploy the stack to pick up any\ncode changes here.\n\n## License\n\n[AGPL License](https://www.gnu.org/licenses/agpl-3.0.html)\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fprx%2Fdovetail-cdn-viewer-request","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fprx%2Fdovetail-cdn-viewer-request","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fprx%2Fdovetail-cdn-viewer-request/lists"}