{"id":15870804,"url":"https://github.com/ido50/mccs","last_synced_at":"2025-06-25T04:41:06.219Z","repository":{"id":1616899,"uuid":"2268585","full_name":"ido50/mccs","owner":"ido50","description":"Fully-featured static file server","archived":false,"fork":false,"pushed_at":"2024-02-04T14:33:54.000Z","size":180,"stargazers_count":2,"open_issues_count":0,"forks_count":4,"subscribers_count":2,"default_branch":"master","last_synced_at":"2024-12-28T01:03:07.662Z","etag":null,"topics":["file-server","http-server","perl","plack-app","psgi","static-site"],"latest_commit_sha":null,"homepage":"http://search.cpan.org/dist/Plack-App-MCCS","language":"Perl","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"apache-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/ido50.png","metadata":{"files":{"readme":"README.md","changelog":"Changes","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":"2011-08-25T15:03:26.000Z","updated_at":"2023-08-04T14:42:00.000Z","dependencies_parsed_at":"2024-10-27T07:47:03.444Z","dependency_job_id":"fdf2ec24-edee-4747-aa3b-8c31d1a033af","html_url":"https://github.com/ido50/mccs","commit_stats":{"total_commits":44,"total_committers":3,"mean_commits":"14.666666666666666","dds":"0.20454545454545459","last_synced_commit":"7629dc55c85bdf9883b12f27f7ff2be725da8021"},"previous_names":["ido50/mccs","ido50/plack-app-mccs"],"tags_count":12,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ido50%2Fmccs","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ido50%2Fmccs/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ido50%2Fmccs/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ido50%2Fmccs/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/ido50","download_url":"https://codeload.github.com/ido50/mccs/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":233456045,"owners_count":18678965,"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":["file-server","http-server","perl","plack-app","psgi","static-site"],"created_at":"2024-10-06T00:23:38.756Z","updated_at":"2025-01-11T14:45:08.611Z","avatar_url":"https://github.com/ido50.png","language":"Perl","funding_links":[],"categories":[],"sub_categories":[],"readme":"# NAME\n\nmccs - Fully-featured static file server.\n\n# SYNOPSIS\n\n    $ mccs [OPTS] [DIR]\n\n    # serve current working directory over HTTP, port 5000\n    $ mccs\n\n    # serve a directory on port 80 using Starman\n    $ mccs -s Starman --listen :80 /some/directory\n\n# DESCRIPTION\n\n`mccs` is an HTTP static file server that can be used as a standalone\napplication, or as a [Plack](https://metacpan.org/pod/Plack) component.\n\n## FEATURES\n\n- Automatic, durable compression of files based on client support.\n- Automatic minification of CSS and JavaScript files.\n- Content negotiation including proper setting and handling of\ncache-related headers.\n- Optional virtual-hosts mode for serving multiple websites.\n- Flexible deployment with support for various HTTP servers, FastCGI\nservers, UNIX domain sockets, and more.\n\n`mccs` aims for reducing CPU load by retaining minified and compressed\nrepresentations of files until they are no longer valid. It does not recompress\non every request.\n\nFor information on how to use `mccs` as a library or embedded in [Plack](https://metacpan.org/pod/Plack)\napplications, see [Plack::App::MCCS](https://metacpan.org/pod/Plack%3A%3AApp%3A%3AMCCS) and [Plack::Middleware::MCCS](https://metacpan.org/pod/Plack%3A%3AMiddleware%3A%3AMCCS).\n\n# ARGUMENTS\n\nDIR\n\n    The directory to serve files from. Defaults to the current working\n    directory.\n\n# OPTIONS\n\n- --minify/--nominify\n\n    Whether to minify CSS/JS files automatically. By default, `--minify` is on.\n\n- --compress/--nocompress\n\n    Whether to compress files automatically. By default, `--compress` is on.\n\n- --etag/--noetag\n\n    Whether to calculate ETag values for files and support `If-None-Match` headers.\n    By default, `--etag` is on.\n\n- --vhost-mode\n\n    Enables virtual hosts mode, which allows serving multiple websites based on the\n    HTTP Host header (HTTP/1.0 requests will not be supported in this mode). When\n    enabled, the directory being served must contain subdirectories named after\n    each host/domain to be served.\n\n- --ignore-file\n\n    Accepts a path to a file in the [Gitignore](https://git-scm.com/docs/gitignore)\n    format. Any request that matches a rule in this file will result in a 404 Not\n    Found response. Defaults to .mccsignore in the root directory. In vhost mode,\n    every host can have its own ignore file, and there can also one global file for\n    all hosts. Both the host-specific file and the global file will be used if they\n    exist.\n\n- -s, --server, the `PLACK_SERVER` environment variable\n\n    Selects a specific server implementation to run on. When provided, the `-s` or\n    `--server` flag will be preferred over the environment variable.\n\n    If no option is given, `mccs` will try to detect the _best_ server\n    implementation based on the environment variables as well as modules loaded by\n    your application in `%INC`. See [Plack::Loader](https://metacpan.org/pod/Plack%3A%3ALoader) for details.\n\n- -S, --socket\n\n    Listens on a UNIX domain socket path. Defaults to undef. This option is only\n    valid for servers which support UNIX sockets.\n\n- -l, --listen\n\n    Listens on one or more addresses, whether \"HOST:PORT\", \":PORT\", or \"PATH\"\n    (without colons). You may use this option multiple times to listen on multiple\n    addresses, but the server will decide whether it supports multiple interfaces.\n\n- -D, --daemonize\n\n    Makes the process run in the background. It's up to the backend server/handler\n    implementation whether this option is respected or not.\n\n- --access-log\n\n    Specifies the pathname of a file where the access log should be written.  By\n    default, in the development environment access logs will go to STDERR.\n\nNote that `mccs` is an extension of [plackup](https://metacpan.org/pod/plackup), and accepts all the flags\nand options supported by it, but not all make sense in the context of `mccs`\nusage. It is recommended to use an HTTP server such as [Twiggy](https://metacpan.org/pod/Twiggy) or [Starman](https://metacpan.org/pod/Starman)\nin a production setting. Other options that starts with \"--\" are passed through\nto the backend server. See each [Plack::Handler](https://metacpan.org/pod/Plack%3A%3AHandler) backend's documentation for\nmore details on their available options.\n\n# HOW DOES IT WORK?\n\nWhen a request is accepted by the server, the following process is initiated:\n\n- 1. Discovery:\n\n    `mccs` attempts to find the requested path in the root directory. If the\n    path is not found, `404 Not Found` is returned. If the path exists but\n    is a directory, `403 Forbidden` is returned (directory listings are currently\n    not supported).\n\n- 2. Examination:\n\n    `mccs` will try to find the content type of the file, either by its extension\n    (relying on [Plack::MIME](https://metacpan.org/pod/Plack%3A%3AMIME) for that), or by a specific setting provided\n    to the app by the user (will take precedence). If not found (or file has\n    no extension), `text/plain` is assumed (which means you should give your\n    files proper extensions if possible).\n\n    `mccs` will also determine for how long to allow clients (whether browsers,\n    proxy caches, etc.) to cache the file. By default, it will set a representation\n    as valid for 86400 seconds (i.e. one day). However, this can be changed either\n    by setting a different global validity interval, or by setting a specific value\n    for certain file types.\n\n    By default, `mccs` also sets the `public` option for the `Cache-Control`\n    header, meaning caches are allowed to save responses even when authentication is\n    performed. You can change that the same way.\n\n- 3. Minification\n\n    If the content type is `text/css` or `application/javascript`, `mccs` will\n    try to find a pre-minified version of it on disk. If found, and the version is\n    younger than the original file, then it will be marked for serving. Otherwise,\n    if [CSS::Minifier::XS](https://metacpan.org/pod/CSS%3A%3AMinifier%3A%3AXS) or [JavaScript::Minifier:XS](https://metacpan.org/pod/JavaScript%3A%3AMinifier%3AXS) are installed, `mccs`\n    will minify the file, save the minified version to disk, and mark it as the\n    version to serve. Future requests to the same file will see the minified version\n    and not minify again.\n\n    `mccs` searches for files that end with `.min.css` and `.min.js`, and that's\n    how it creates them too. If a request comes to `style.css`, for example, then\n    `mccs` will look for `style.min.css`, possibly creating it if not found or\n    stale. The request path remains the same (`style.css`) though, even internally.\n    If a request comes to `style.min.css` (which you don't really want when\n    using `mccs`), the app will not attempt to minify it again (so you won't\n    get things like `style.min.min.css`).\n\n    If `min_cache_dir` is specified, it will do all its searching and storing of\n    generated minified files within `$root`/`$min_cache_dir` and ignore minified\n    files outside that directory.\n\n- 4. Compression\n\n    If the client supports compressed responses (via the gzip, deflate or\n    zstd algorithms), as noted by the `Accept-Encoding` header, `mccs` will try to\n    find a precompressed version of the file on disk. If found, and is not stale,\n    this version is marked for serving. Otherwise, if the appropriate compression\n    module is installed, `mccs` will compress the file, save the compressed version\n    to disk, and mark it as the version to serve. Future requests to the same file\n    will see the compressed version and not compress again.\n\n    `mccs` searches for files that end with the appropriate extension for the\n    algorithm (i.e. `.gz`, `.zip`, `.zstd`), and that's how it creates them too.\n    If a request comes to `style.css` from a client that prefers gzip responses,\n    for example, and the file was minified in the previous step, `mccs` will look\n    for `style.min.css.gz`, possibly creating it if not found. The request path\n    remains the same (`style.css`) though, even internally.\n\n    `mccs` honors weight values supplied in the `Accept-Encoding` header, and will\n    serve using the highest-weighted algorithm it supports.\n\n- 5. Cache Validation\n\n    If the client provided the `If-Modified-Since` header, `mccs` will determine\n    if the file we're serving has been modified after the supplied date, and return\n    `304 Not Modified` immediately if not.\n\n    If file doesn't have the 'no-store' cache control option, and the client\n    provided the `If-None-Match` header, `mccs` will look for a file that has the\n    the same name as the file we're going to serve, plus an `.etag` suffix, such\n    as `style.min.css.gz.etag`, for example. If found, and not stale, the content\n    of this file is read and compared with the provided ETag. If the two values are\n    equal, `mccs` will immediately return `304 Not Modified`.\n\n- 6. ETagging\n\n    If an `.etag` file wasn't found in the previous step, and the file we're\n    serving doesn't have the 'no-store' cache control option, `mccs` will create\n    one from the file's inode, last modification date and size. Future requests\n    to the same file will see this ETag file, so it is not created again.\n\n- 7. Headers and Cache-Control\n\n    `mccs` now sets headers, especially cache control headers, as appropriate:\n\n    - `Content-Encoding` is set to the compression algorithm used, if any.\n    - `Content-Length` is set with the size of the file in bytes.\n    - `Content-Type` is set with the MIME type of the file (if a text file,\n    the character string is appended, e.g. `text/css; charset=UTF-8`).\n    - `Last-Modified` is set with the last modification date of the file in\n    HTTP date format.\n    - `Expires` is set with the date on which cached versions should expire,\n    as determined in stage 2, in HTTP date format.\n    - `Cache-Control` is set with the number of seconds the representation is\n    valid for (unless caching of the file is not allowed) and other options, as\n    determined in stage 2.\n    - `Etag` is set with the ETag value (if exists).\n    - `Vary` is set with `Accept-Encoding`.\n\n- 8. Serving\n\n    The selected file is served to the client.\n\n# CAVEATS AND THINGS TO CONSIDER\n\n- You can't tell `mccs` not to minify/compress a specific file type, but\nonly disable minification/compression altogether.\n- Directory listings are not supported.\n- Caching middlewares such as [Plack::Middleware::Cache](https://metacpan.org/pod/Plack%3A%3AMiddleware%3A%3ACache) and [Plack::Middleware::Cached](https://metacpan.org/pod/Plack%3A%3AMiddleware%3A%3ACached)\ndon't rely on Cache-Control headers (or so I understand) for\ntheir expiration values, which makes them less useful for applications that\nrely on [Plack::App::MCCS](https://metacpan.org/pod/Plack%3A%3AApp%3A%3AMCCS) or [Plack::Middleware::MCCS](https://metacpan.org/pod/Plack%3A%3AMiddleware%3A%3AMCCS). You'll probably be\nbetter off with an external cache like [Varnish](https://www.varnish-cache.org/)\nif you want a cache on your application server. Even without a server cache, your\napplication should still appear faster for users due to browser caching (and\nalso CPU load should be decreased).\n- `Range` requests are not supported. See [Plack::App::File::Range](https://metacpan.org/pod/Plack%3A%3AApp%3A%3AFile%3A%3ARange) if\nyou need that.\n- The app is mounted on a directory and can't be set to only serve\nrequests that match a certain regular expression. Use the\n[middleware](https://metacpan.org/pod/Plack%3A%3AMiddleware%3A%3AMCCS) for that.\n\n# DIAGNOSTICS\n\n`mccs` doesn't directly throw any exceptions, instead returning HTTP errors\nto the client and possibly issuing some `warn`s. The following list should\nhelp you to determine some potential problems with `MCCS`:\n\n- `\"Failed compressing %s with %s: %s\"`\n\n    This warning is issued when `mccs` fails to compress a file with a certain\n    algorithm. When it happens, a compressed representation will not be returned.\n\n- `\"Can't open ETag file %s.etag for reading\"`\n\n    This warning is issued when `mccs` can't read an ETag file, probably because\n    it does not have enough permissions. The request will still be fulfilled,\n    but it won't have the `ETag` header.\n\n- `\"Can't open ETag file %s.etag for writing\"`\n\n    Same as before, but when `mccs` can't write an ETag file.\n\n- `403 Forbidden` is returned for files that exist\n\n    If a request for a certain file results in a `403 Forbidden` error, it\n    probably means `mccs` has no read permissions for that file.\n\n# CONFIGURATION AND ENVIRONMENT\n\n`mccs` requires no configuration files or environment variables.\n\n# REQUIREMENTS\n\n`mccs` **requires** the following dependencies:\n\n- [Perl 5.36+](https://www.perl.org/)\n- [HTTP::Date](https://metacpan.org/pod/HTTP%3A%3ADate)\n- [Plack](https://metacpan.org/pod/Plack)\n\n`mccs` will use the following CPAN modules if they exist:\n\n- [CSS::Minifier::XS](https://metacpan.org/pod/CSS%3A%3AMinifier%3A%3AXS)\n- [JavaScript::Minifier::XS](https://metacpan.org/pod/JavaScript%3A%3AMinifier%3A%3AXS)\n- [IO::Compress::Zstd](https://metacpan.org/pod/IO%3A%3ACompress%3A%3AZstd)\n\nThe following CPAN modules are also recommended:\n\n- [Twiggy](https://metacpan.org/pod/Twiggy) for an event-loop based HTTP server.\n- [Starman](https://metacpan.org/pod/Starman) for a preforking HTTP server.\n\n# INCOMPATIBILITIES WITH OTHER MODULES\n\nNone reported.\n\n# BUGS AND LIMITATIONS\n\nPlease report any bugs or feature requests to `bug-Plack-App-MCCS@rt.cpan.org`,\nor through the web interface at\n[http://rt.cpan.org/NoAuth/ReportBug.html?Queue=Plack-App-MCCS](http://rt.cpan.org/NoAuth/ReportBug.html?Queue=Plack-App-MCCS).\n\n# SEE ALSO\n\n[Plack::App::MCCS](https://metacpan.org/pod/Plack%3A%3AApp%3A%3AMCCS), [Plack::Middleware::MCCS](https://metacpan.org/pod/Plack%3A%3AMiddleware%3A%3AMCCS), [Plack::Runner](https://metacpan.org/pod/Plack%3A%3ARunner), [plackup](https://metacpan.org/pod/plackup).\n\n# AUTHOR\n\nIdo Perlmuter \u003cido@ido50.net\u003e\n\n# ACKNOWLEDGMENTS\n\nSome of this application's code is based on [Plack::App::File](https://metacpan.org/pod/Plack%3A%3AApp%3A%3AFile) by Tatsuhiko\nMiyagawa and [Plack::Middleware::ETag](https://metacpan.org/pod/Plack%3A%3AMiddleware%3A%3AETag) by Franck Cuny.\n\nChristian Walde contributed new features and fixes for the 1.0.0 release.\n\n# LICENSE AND COPYRIGHT\n\nCopyright (c) 2011-2023, Ido Perlmuter `ido@ido50.net`.\n\nLicensed under the Apache License, Version 2.0 (the \"License\");\nyou may not use this file except in compliance with the License.\nYou may obtain a copy of the License at\n\n    http://www.apache.org/licenses/LICENSE-2.0\n\nUnless required by applicable law or agreed to in writing, software\ndistributed under the License is distributed on an \"AS IS\" BASIS,\nWITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\nSee the License for the specific language governing permissions and\nlimitations under the License.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fido50%2Fmccs","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fido50%2Fmccs","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fido50%2Fmccs/lists"}