{"id":51066984,"url":"https://github.com/amake/s3dav","last_synced_at":"2026-06-23T07:30:59.989Z","repository":{"id":361715942,"uuid":"1255069419","full_name":"amake/s3dav","owner":"amake","description":"Minimal authenticated HTTP file service backed by Amazon S3","archived":false,"fork":false,"pushed_at":"2026-05-31T23:17:58.000Z","size":26,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":0,"default_branch":"master","last_synced_at":"2026-06-15T12:15:10.969Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":"Dart","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/amake.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE.txt","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,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null},"funding":{"github":"amake"}},"created_at":"2026-05-31T11:14:23.000Z","updated_at":"2026-05-31T23:18:02.000Z","dependencies_parsed_at":null,"dependency_job_id":null,"html_url":"https://github.com/amake/s3dav","commit_stats":null,"previous_names":["amake/s3dav"],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/amake/s3dav","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/amake%2Fs3dav","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/amake%2Fs3dav/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/amake%2Fs3dav/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/amake%2Fs3dav/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/amake","download_url":"https://codeload.github.com/amake/s3dav/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/amake%2Fs3dav/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":34680620,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-05-26T15:22:16.424Z","status":"online","status_checked_at":"2026-06-23T02:00:07.161Z","response_time":65,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"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":"2026-06-23T07:30:56.019Z","updated_at":"2026-06-23T07:30:59.981Z","avatar_url":"https://github.com/amake.png","language":"Dart","funding_links":["https://github.com/sponsors/amake"],"categories":[],"sub_categories":[],"readme":"# dav_s3_gateway\n\nMinimal authenticated HTTP file service backed by Amazon S3.\n\nThis project intentionally implements a narrow contract:\n\n- `GET` reads one object\n- `HEAD` returns object metadata\n- `PUT` replaces one object\n- Basic Auth protects the endpoint\n- request paths map to a fixed S3 bucket prefix\n\nIt is designed for low-volume personal use behind API Gateway HTTP API and AWS Lambda.\n\n## Local Development\n\nInstall dependencies:\n\n```sh\ndart pub get\n```\n\nRun the local server:\n\n```sh\nexport AWS_REGION=ap-northeast-1\nexport S3_REGION=ap-northeast-1\nexport S3_BUCKET=my-private-bucket\nexport S3_PREFIX=webdav/\nexport AUTH_MODE=basic\nexport AUTH_USERNAME=alice\nexport AUTH_PASSWORD=strong-secret\ndart run bin/server.dart\n```\n\nThe service listens on `HOST` and `PORT` if set, otherwise `0.0.0.0:8080`.\n\n## Environment\n\nRequired:\n\n- `AWS_REGION`\n- `S3_REGION` when the storage bucket is not in `AWS_REGION`\n- `S3_BUCKET`\n- `S3_PREFIX`\n- `AUTH_MODE=basic`\n- `AUTH_USERNAME`\n- `AUTH_PASSWORD`\n\nOptional:\n\n- `MAX_OBJECT_SIZE_BYTES`\n- `HOST`\n- `PORT`\n- `HEALTHCHECK_ENABLED`\n- `DAV_S3_GATEWAY_LOG_LEVEL`\n\nAWS credentials are read from the standard runtime variables:\n\n- `AWS_ACCESS_KEY_ID`\n- `AWS_SECRET_ACCESS_KEY`\n- `AWS_SESSION_TOKEN`\n\nIn Lambda these normally come from the execution role automatically.\n\n## Behavior\n\n- Unauthenticated requests return `401` and `WWW-Authenticate: Basic realm=\"dav-s3\"`.\n- Unsupported methods return `405`.\n- Missing objects return `404`.\n- Oversized `PUT` requests return `413`.\n- Root `/` is not addressable.\n- Encoded slashes such as `%2F` are rejected to avoid ambiguous key mapping.\n\n## Testing\n\n```sh\ndart test\ndart analyze\n```\n\n## Lambda Packaging\n\nThe repository includes:\n\n- ZIP-based Lambda packaging through [Makefile](Makefile)\n- deploy defaults through [deploy.env.example](deploy.env.example)\n- [infra/template.yaml](infra/template.yaml) as CloudFormation/SAM-style infrastructure scaffolding\n\nThe Lambda entrypoint is [bin/bootstrap.dart](bin/bootstrap.dart), which runs a custom runtime loop and converts API Gateway HTTP API v2 events into service requests.\n\nBuild the Lambda payload with:\n\n```sh\nmake build\n```\n\nThis produces `dist/lambda.zip` containing the compiled `bootstrap` binary for the AWS `provided.al2023` custom runtime.\n\nFor deployment, copy [deploy.env.example](deploy.env.example) to `deploy.env` and fill it out once:\n\n```sh\ncp deploy.env.example deploy.env\n```\n\nThen deploy with:\n\n```sh\nmake deploy\n```\n\nYou can inspect the resolved deploy settings with:\n\n```sh\nmake show-config\n```\n\nYou can still override any setting on the command line when needed:\n\n```sh\nmake deploy \\\n  artifact_bucket=some-other-bucket \\\n  domain_name=staging.example.com\n```\n\nOptional deploy variables:\n\n- `stack_name` defaults to `dav-s3-gateway`\n- `service_name` defaults to `dav-s3-gateway`\n- `aws_region` is required; the API Gateway custom-domain ACM certificate must be issued in this same region\n- `s3_region` defaults to `aws_region`; set it to the storage bucket's region if different\n- `artifact_key` defaults to `\u003cservice_name\u003e/lambda.zip`\n- `hosted_zone_id` is optional; leave it unset if DNS is managed elsewhere\n- `max_object_size_bytes` defaults to `5242880`\n\n`make deploy` validates that the region in `certificate_arn` matches `aws_region` before calling CloudFormation.\n\n`make deploy` builds the ZIP, uploads it to `s3://\u003cartifact_bucket\u003e/\u003cartifact_key\u003e`, and runs `aws cloudformation deploy --region \u003caws_region\u003e` against [infra/template.yaml](infra/template.yaml). The Lambda stack and API Gateway live in `aws_region`; object reads and writes are signed for `s3_region`.\n\nWhen only code changes, CloudFormation may report no stack changes because the artifact S3 key is unchanged. `make deploy` still refreshes the Lambda code by calling `aws lambda update-function-code` after the stack deployment step. To update only the Lambda payload without touching the stack, run:\n\n```sh\nmake upload update-code\n```\n\nIf DNS is managed outside this stack, create a DNS record for `domain_name` that points at the `CustomDomainTarget` stack output. For a subdomain such as `dav.example.com`, use a `CNAME` record. If your DNS provider supports alias-style records at the zone apex, use `CustomDomainTarget` plus `CustomDomainHostedZoneId`.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Famake%2Fs3dav","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Famake%2Fs3dav","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Famake%2Fs3dav/lists"}