{"id":49880095,"url":"https://github.com/pardnio/node-image-server","last_synced_at":"2026-05-15T13:40:48.518Z","repository":{"id":353609421,"uuid":"994000253","full_name":"pardnio/node-image-server","owner":"pardnio","description":"A image caching server derived from joball.tw, optimizing content delivery with WebP transformation and comprehensive caching strategies (browser, CDN, backend).","archived":false,"fork":false,"pushed_at":"2025-06-01T01:51:14.000Z","size":6020,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":0,"default_branch":"master","last_synced_at":"2026-04-24T17:35:29.119Z","etag":null,"topics":["cloudflare-worker","image-caching","image-server","nginx","pardnchiu"],"latest_commit_sha":null,"homepage":"","language":"TypeScript","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/pardnio.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,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2025-06-01T01:14:40.000Z","updated_at":"2026-04-05T18:00:19.000Z","dependencies_parsed_at":null,"dependency_job_id":null,"html_url":"https://github.com/pardnio/node-image-server","commit_stats":null,"previous_names":["pardnio/node-image-server"],"tags_count":null,"template":false,"template_full_name":null,"purl":"pkg:github/pardnio/node-image-server","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/pardnio%2Fnode-image-server","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/pardnio%2Fnode-image-server/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/pardnio%2Fnode-image-server/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/pardnio%2Fnode-image-server/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/pardnio","download_url":"https://codeload.github.com/pardnio/node-image-server/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/pardnio%2Fnode-image-server/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":33068889,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-05-15T11:35:32.926Z","status":"ssl_error","status_checked_at":"2026-05-15T11:35:31.362Z","response_time":103,"last_error":"SSL_connect returned=1 errno=0 peeraddr=140.82.121.5:443 state=error: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"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":["cloudflare-worker","image-caching","image-server","nginx","pardnchiu"],"created_at":"2026-05-15T13:40:47.687Z","updated_at":"2026-05-15T13:40:48.512Z","avatar_url":"https://github.com/pardnio.png","language":"TypeScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Image Caching Server\n\n\u003e Upload and delete functions are designed for internal network use, so they will have minimal restrictions.\n\n## Features\n\n\u003e This system provides storage and caching for uploaded images to improve web resource response speed.\n\n- **Browser Caching**\n    Stores previously requested resources to reduce repeated backend requests, serving directly from browser \u003cbr\u003e\n    Expected expiration time (1 week)\n- **Cloudflare CDN**\n    Enables users from different countries to access content from the nearest node, reducing cross-regional transmission delays (high latency in transoceanic transmission) \u003cbr\u003e\n    Expected expiration time (1 week)\n- **Backend Caching**\n    Avoids regenerating identical resources, saving server computation, expected expiration time (1 month) \u003cbr\u003e\n    Nginx caching, reduces Nodejs backend processing, expected expiration time (1 month)\n\n### Default Webp\n\nDefault output format is Webp, maintaining good image quality while significantly reducing output traffic. Using the `t / type` parameter can specify output format (avif/webp/jpg/png), or the `o / origin` parameter controls whether to output the original file.\n\n### Caching Design\n\nMulti-level cache structure: Provides four layers of caching - browser, CDN, Nginx, and cached images\n- Parameterized caching: Different versions of the same image are generated and cached based on various size and quality parameters\n- Cache directory structure: Based on the original file path, corresponding directory structures are created under `/storage/image/cache/`\n\n### Error Handling\n\n- For non-existent images: Returns a custom 404 image (controlled by the `d / dark` parameter for dark/light mode)\n- For image processing failures: Returns an explanatory message\n\n### Trash\n\nDate-organized trash bin mechanism\n\n- Deleted files are moved to the `/storage/image/upload/.trash/YYYY-MM-DD/`# Uploads image to the `/storage/image/upload/[PATH]` folder\n- Trash organized by date for easier recovery of files deleted on a specific date\n- System returns the file's location in the trash bin for easy restoration if needed\n\n***\n\n### POST：`/upload/{:path}` \n\n\u003e The `:path` part can include `/` and will upload directly to the specified location.\n\n```Shell\n# Uploads image to the `/storage/image/upload/[PATH]` folder\ncurl -X POST \\\n-H \"Content-Type: multipart/form-data\" \\\n-F \"filepath=@/Users/pardn/Desktop/Wallpaper-Desktop/rain_clouds_sky-wallpaper-5120x3200.jpg\" \\\n[URL]/upload/[PATH]\n```\n- Successful upload: 201 -\u003e `JSON`\n    ```Json\n    {\n        \"success\": 1,\n        \"filename\": \"ERftP1gTS7WCTeJ8_1744080848530.jpg\",\n        \"type\": \"image/jpeg\",\n        \"size\": 2501808,\n        \"src\": \"[URL]/upload/[PATH]/c/img/test2/test1/ERftP1gTS7WCTeJ8_1744080848530.jpg\"\n    }\n    ```\n- Path Null: 400 -\u003e `String`\n    ```\n    請至少規劃一個資料夾位置\n    ```\n- Type Error: 400 -\u003e `String`\n    ```\n    僅支持 jpg / png / webp / svg / pdf\n    ```\n- Upload Error: 500 -\u003e `String`\n    ```\n    檔案不存在或上傳失敗\n    ```\n\n### DELETE：`/del/{:path}` \n\n\u003e The `:path` part can include `/` and will delete the image at the specified location.\n\n```Shell\n# Delete `AQepGMnNiOxrnsKu_1744035656038.jpg` in the `/storage/image/upload/[PATH]` folder\ncurl -X DELETE \\\n-H \"Content-Type: application/json\" \\\n[URL]/del/[PATH]/AQepGMnNiOxrnsKu_1744035656038.jpg\n\n# Delete folder /storage/image/upload/[PATH]\ncurl -X DELETE \\\n-H \"Content-Type: application/json\" \\\n[URL]/del/[PATH]\n```\n- Successful deletion: 200 -\u003e `JSON`\n    ```Json\n    // 檔案\n    {\n        \"success\": 1,\n        \"message\": \"檔案已移動至垃圾桶: /storage/image/upload/.trash/2025-04-08/[PATH]/AQepGMnNiOxrnsKu_1744035656038.jpg\"\n    }\n\n    // 檔案夾\n    {\n        \"success\": 1,\n        \"message\": \"檔案夾已移動至垃圾桶: /storage/image/upload/.trash/2025-04-08/[PATH]\"\n    }\n    ```\n- 400 -\u003e `String`\n    ```\n    未指定檔案/檔案夾\n    ```\n- 404 -\u003e `String`\n    ```\n    檔案/檔案夾不存在\n    ```\n- 500 -\u003e `String`\n    ```\n    [Error Message]\n    ```\n\n### GET：`/c/img/{:filepath}`\n\n#### Available Parameters\n- `o / origin`: Return original file (highest priority)\n- `s / size`: Specify image short edge length (higher priority than width/height)\n- `w / width`: Specify image width\n- `h / height`: Specify image height\n- `q / quality`: Specify image quality (1-100), default 75\n- `t / type`: Specify type (avif|webp|jpg|png), default webp\n- `d / dark`: Specify 404 image color scheme (1|0), default 0\n\n### CDN\n\n\u003e Change URL to point to Cloudflare worker to achieve global caching.\n\n### Flow\n\n\u003cdetails\u003e\n\u003csummary\u003eLoad\u003c/summary\u003e\n\n```mermaid\nflowchart TD\n    A[\"Client\"] -- GET --\u003e S{\"Browser cache exists?\u003cbr\u003e(7 days)\"}\n    S -- Yes --\u003e A\n    S -- No --\u003e B{\"Request source\"}\n    B -- \"Image Server\" --\u003e C[\"Nginx proxy\"]\n    B -- Cloudflare Worker --\u003e D[\"CDN node\"]\n    C -- Check Nginx cache --\u003e E{\"Nginx cache exists?\u003cbr\u003e(30 days)\"}\n    E -- Yes --\u003e F[\"Return Nginx cache\"]\n    E -- No --\u003e G[\"Forward to image processing service\"]\n    D -- Check Cloudflare cache --\u003e H{\"Cloudflare cache exists?\u003cbr\u003e(7 days)\"}\n    H -- Yes --\u003e I[\"Return Cloudflare cache\"]\n    H -- No --\u003e C\n    G --\u003e K{\"Check if local cache file\u003cbr\u003eexists\u003cbr\u003e(30 days)\"}\n    K -- Yes --\u003e L[\"Return local cache file\"]\n    K -- No --\u003e M{\"Check parameters\"}\n    M -- \"origin=1\" --\u003e N[\"Return original image\"]\n    M -- Generate cache file\u003cbr\u003eDefault max long edge 1024 px --\u003e P[\"Process image and convert to WebP\"]\n    P --\u003e Q[\"Save as local cache file\"]\n    Q --\u003e R[\"Return local cache file\"]\n    F --\u003e T[\"Set HTTP cache headers\"]\n    I --\u003e T\n    L --\u003e T\n    N --\u003e T\n    R --\u003e T\n    T --\u003e A\n```\n\n\u003c/details\u003e\n\n\u003cdetails\u003e\n\u003csummary\u003eUpload\u003c/summary\u003e\n\n```mermaid\nflowchart TD\n    A[Client] --\u003e|POST| B[Upload service]\n    B --\u003e|Receive request| C{Check client IP}\n    C --\u003e|IP not allowed| D[Return permission error]\n    C --\u003e|IP passed| E{Check path parameter}\n    E --\u003e|Invalid path| F[Return error]\n    E --\u003e|Valid path| G[Create folder]\n    G --\u003e H[Generate random filename]\n    H --\u003e I{Check file type}\n    I --\u003e|Unsupported type| J[Return error]\n    I --\u003e|Supported type| K[Save file]\n    K --\u003e L[Return success response]\n    L --\u003e M[Include cache link and CDN link]\n    M --\u003e A\n    D --\u003e A\n    F --\u003e A\n    J --\u003e A\n```\n\n\u003c/details\u003e\n\n## License\n\nThis source code project is licensed under the [MIT](https://github.com/pardnchiu/FlexPlyr/blob/main/LICENSE) license.\n\n## Creator\n\n\u003cimg src=\"https://avatars.githubusercontent.com/u/25631760\" align=\"left\" width=\"96\" height=\"96\" style=\"margin-right: 0.5rem;\"\u003e\n\n\u003ch4 style=\"padding-top: 0\"\u003e邱敬幃 Pardn Chiu\u003c/h4\u003e\n\n\u003ca href=\"mailto:dev@pardn.io\" target=\"_blank\"\u003e\n    \u003cimg src=\"https://pardn.io/image/email.svg\" width=\"48\" height=\"48\"\u003e\n\u003c/a\u003e \u003ca href=\"https://linkedin.com/in/pardnchiu\" target=\"_blank\"\u003e\n    \u003cimg src=\"https://pardn.io/image/linkedin.svg\" width=\"48\" height=\"48\"\u003e\n\u003c/a\u003e\n\n***\n\n©️ 2025 [邱敬幃 Pardn Chiu](https://pardn.io)","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fpardnio%2Fnode-image-server","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fpardnio%2Fnode-image-server","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fpardnio%2Fnode-image-server/lists"}