{"id":16671341,"url":"https://github.com/bluefeet/starch","last_synced_at":"2025-08-31T10:40:29.437Z","repository":{"id":33890454,"uuid":"37603207","full_name":"bluefeet/Starch","owner":"bluefeet","description":"A framework independent HTTP session library.","archived":false,"fork":false,"pushed_at":"2021-12-02T17:45:51.000Z","size":368,"stargazers_count":3,"open_issues_count":0,"forks_count":4,"subscribers_count":1,"default_branch":"master","last_synced_at":"2025-04-09T19:49:25.457Z","etag":null,"topics":["cpan","perl5"],"latest_commit_sha":null,"homepage":"https://metacpan.org/pod/Starch","language":"Perl","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":"cloudfoundry/gorouter","license":"gpl-3.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/bluefeet.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}},"created_at":"2015-06-17T15:23:20.000Z","updated_at":"2021-07-21T12:50:32.000Z","dependencies_parsed_at":"2022-08-17T19:55:14.250Z","dependency_job_id":null,"html_url":"https://github.com/bluefeet/Starch","commit_stats":null,"previous_names":[],"tags_count":14,"template":false,"template_full_name":null,"purl":"pkg:github/bluefeet/Starch","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/bluefeet%2FStarch","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/bluefeet%2FStarch/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/bluefeet%2FStarch/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/bluefeet%2FStarch/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/bluefeet","download_url":"https://codeload.github.com/bluefeet/Starch/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/bluefeet%2FStarch/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":272971420,"owners_count":25024093,"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","status":"online","status_checked_at":"2025-08-31T02:00:09.071Z","response_time":79,"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":["cpan","perl5"],"created_at":"2024-10-12T11:44:09.704Z","updated_at":"2025-08-31T10:40:29.405Z","avatar_url":"https://github.com/bluefeet.png","language":"Perl","funding_links":[],"categories":[],"sub_categories":[],"readme":"# NAME\n\nStarch - A framework independent HTTP session library.\n\n# DESCRIPTION\n\nWelcome to Starch!\n\nStarch solves the problems introduced when complex HTTP session libraries\nare written as web framework built-ins.  When complex libraries like these\nare tied directly into a web framework they become much more difficult to\ntest, difficult to debug, impossible to integrate with other languages, and\nthey lose the ability to be independent which is always a loss.\n\nThe prime example, and the reason this module was originally built, is\n[Catalyst::Plugin::Session](https://metacpan.org/pod/Catalyst::Plugin::Session) which has no business being so monolithic\nand still being tied directly into [Catalyst](https://metacpan.org/pod/Catalyst).  Thus Starch was created\nalong with the super-thin glue [Catalyst::Plugin::Starch](https://metacpan.org/pod/Catalyst::Plugin::Starch).\n\nAt its foundation Starch provides the ability to create state objects, store\nthem, update, and remove them.  Starch is extremely generic despite the\nfact that it was built to fill the no-framework HTTP session need.  Out\nof the box Starch is about states and their storage backend and can be\nused for purposes that have nothing to do with HTTP or sessions.  So far\nnobody has done this, but there is no reason that Starch couldn't be used\nas the workhorse behind an object store, for example.\n\nOne of the strengths that Starch provides is very flexible storage backends.\n[Starch::Store](https://metacpan.org/pod/Starch::Store) objects can be layered, prioritized, rate-limited, behaviors\ncan be changed with plugins, states can be easily migrated from one backend to\nanother, caching is super easy to setup, etc, etc.\n\nStarch has several design philosophies:\n\n- Is as fast as possible by limiting method calls, implementing\nlazy-loading wherever it can be done, and using libraries which\nexhibit run-time efficiencies which beat out their competitors.\n- Reduces data store reads and writes to just the most essential.\n- Is independent from any particular framework (such as Catalyst or\nPlack).\n- Provides a straight-forward and powerful mechanism for customizing just\nabout any part of Starch via stores and plugin bundles.\n- Is easy to understand due to everything being well documented,\nhyper-linked, and containing thorough examples and tests.\n- Low dependency overhead, and no XS dependencies in the core distribution.\n\nThere are many [\"ALTERNATIVES\"](#alternatives) to Starch to choose from, all of which\nStarch was inspired from.\n\n# BASIC USAGE\n\nWhen setting up you need to, at a minimum, define a store:\n\n```perl\nuse Starch;\n\nmy $starch = Starch-\u003enew(\n    store =\u003e { class=\u003e'::Memory' },\n);\n```\n\nA store is a hash ref of arguments which are used for constructing the\nstore object.  A store object implements a very simple interface for\nsetting, getting, and removing state data.  Beyond defining the\nstore you will not be interacting with it as the [Starch::State](https://metacpan.org/pod/Starch::State)\nobjects do all the store interaction for you.\n\nWhen defining the store you must specify at least the `class`\nargument which determines the store class to use.  This class name\ncan be relative to `Starch::Store` so that if you specify\n`::Memory`, as in the example above, it will be resolved to the\n[Starch::Store::Memory](https://metacpan.org/pod/Starch::Store::Memory) class.  An absolute store class name\nmay be used without the leading `::` if you have a custom store in\na different namespace.\n\nCalling the `new` method on the `Starch` package actually returns\na [Starch::Manager](https://metacpan.org/pod/Starch::Manager) object, so refer to its documentation for details\non what arguments you can pass.\n\nNow that you have the `$starch` object you can create a state object:\n\n```perl\nmy $state = $starch-\u003estate();\n```\n\nThis creates a new [Starch::State](https://metacpan.org/pod/Starch::State) object which you can then\ninteract with:\n\n```\n$state-\u003edata-\u003e{some_key} = 'some_value';\n```\n\nThe [\"data\" in Starch::State](https://metacpan.org/pod/Starch::State#data) attribute is a writeable hash ref\nwhich can contain any data you want.  This is the data which will\nbe stored by, and retrieved from, the store.  Once you're done\nmaking changes to the data, call save:\n\n```\n$state-\u003esave();\n```\n\nThis stores the state data in the store.\n\nEach state gets assigned a state ID automatically, unless you specify a custom\none when creating the state, which can be used to retrieve the state data at a\nlater time.  The state ID is a randomly generated SHA-1 hex digest.\n\n```perl\nmy $id = $state-\u003eid();\n```\n\nTo retrieve a previously saved state pass the state ID to the\n[\"state\" in Starch::Manager](https://metacpan.org/pod/Starch::Manager#state) method:\n\n```perl\nmy $state = $starch-\u003estate( $id );\n```\n\nAnd now you can access the data you previously saved:\n\n```\nprint $state-\u003edata-\u003e{some_key}; # \"some_value\"\n```\n\nYour framework integration, such as [Catalyst::Plugin::Starch](https://metacpan.org/pod/Catalyst::Plugin::Starch),\nwill wrap up and hide away most of these details from you, but\nit's still good to know what is happening behind the scenes.\n\n# EXPIRATION\n\nExpiration can be specified globally when instantiating the [Starch::Manager](https://metacpan.org/pod/Starch::Manager)\nobject, as well as per-state and per-store.  The expires value has various properties\nand behaviors that are important to understand:\n\n- The `expires` field is always specified as the number of seconds before\nthe state will expire.\n- Setting `expires` to `0` generally disables expiration, but behavior\ncan be store-specific.  For example, often times caching stores assume no\nexpiration to mean the storage backend gets to pick when to expire the data.\n- The [Starch::Manager](https://metacpan.org/pod/Starch::Manager) class accepts an `expires` argument which is used\nas the default expires for new state objects and used as the expiration\nfor cookies via [Starch::Plugin::CookieArgs](https://metacpan.org/pod/Starch::Plugin::CookieArgs).\n- States have an `expires` argument which defaults to the value of\nthe global expires set in the [Starch::Manager](https://metacpan.org/pod/Starch::Manager) object.  Each state\ncan then have their individual expire extended or reduced via the\n[\"set\\_expires\" in Starch::State](https://metacpan.org/pod/Starch::State#set_expires) method.\n- Stores may have a `max_expires` argument passed to them.  If the state's\nexpires is larger than the store's max\\_expires then the state's expires will\nbe replaced with the store's max\\_expires when writing the data to the store.\n\n    This is useful for when you have a caching store in front of your persistent\n    store and you'd like your sessions to expire out of the caching store, by\n    setting `max_expires` on it, well before they will expire out of the\n    persistent store.\n\n# LOGGING\n\nStarch has built-in logging facilities via [Log::Any](https://metacpan.org/pod/Log::Any).  By default,\nnothing is logged.  Various plugins and stores do use logging, such\nas the [Starch::Plugin::LogStoreExceptions](https://metacpan.org/pod/Starch::Plugin::LogStoreExceptions) plugin.\n\nIf you do not set up a log adapter then these log messages will disappear\ninto the void.  Read the [Log::Any](https://metacpan.org/pod/Log::Any) documentation for instructions on\nconfiguring an adapter to capture the log output.\n\nThe [Starch::Plugin::Trace](https://metacpan.org/pod/Starch::Plugin::Trace) plugin adds a bunch of additional\nlogging output useful for development.\n\n# METHOD PROXIES\n\nThe Starch manager ([Starch::Manager](https://metacpan.org/pod/Starch::Manager)) and stores support method proxies\nout of the box for all arguments passed to them.  A method proxy is\nan array ref which is lightly inspired by JSON references.  This array\nref must have the string `\u0026proxy` as the first value, a package name\nas the second value, a method name as the third value, and any number\nof arguments to pass to the method after that:\n\n```\n[ '\u0026proxy', $package, $method, @args ]\n```\n\nMethod proxies are really useful when you are configuring Starch from\nstatic configuration where you cannot dynamically pass a value from Perl.\n\nAn example from [Starch::Store::CHI](https://metacpan.org/pod/Starch::Store::CHI) illustrates how this works:\n\n```perl\nmy $starch = Starch-\u003enew(\n    store =\u003e {\n        class =\u003e '::CHI',\n        chi =\u003e ['\u0026proxy', 'My::CHI::Builder', 'get_chi'],\n    },\n);\n```\n\nThis will cause `My::CHI::Builder` to be loaded, if it hasn't already, and then\n`My::CHI::Builder-\u003eget_chi()` will be called and the return value used as\nthe value for the `chi` argument.\n\nAnother practical example of using this is with [DBI](https://metacpan.org/pod/DBI) where normally\nyou would end up making a separate connection to your database for states.\nIf your state database is the same database as you use for other things\nit may make sense to use the same `$dbh` for both so that you do not\ndouble the number of connections you are making to your database.\n\nMethod proxies can be used with the manager and store objects at any point in\ntheir arguments.  For example, if you have Perl code that builds the Starch\nconfiguration from the ground up you could:\n\n```perl\nmy $starch = Starch-\u003enew(\n    [ '\u0026proxy', 'My::Starch::Config', 'get_config' ],\n);\n```\n\nWhich will call `get_config` on the `My::Starch::Config` package and use its\nreturn value as the arguments for instantiating the Starch object.\n\nMethod proxies are provided by [MooX::MethodProxyArgs](https://metacpan.org/pod/MooX::MethodProxyArgs) and\n[Data::MethodProxy](https://metacpan.org/pod/Data::MethodProxy); check those for more details.\n\n# PERFORMANCE\n\nOn a decently-specced developer laptop Starch adds, at most, one half of one\nmillisecond to every HTTP request.  This non-scientific benchmark was done using\nthe `Memory` store and a contrived example of the typical use of a state as the\nbackend for an HTTP session.\n\nStarch is meant to be as fast as possible while still being flexible.\nDue to Starch avoiding dependencies, and having zero non-core XS dependencies,\nthere are still some areas which could be slightly faster.  At this time there\nis one plugin which will provide a small performance gain [Starch::Plugin::Sereal](https://metacpan.org/pod/Starch::Plugin::Sereal).\nEven then, the gain using this plugin will be in the order of a fraction of a\nmillisecond per each HTTP request.\n\nStarch has gone through the wringer with respect to performance and there just are\nnot many performance gains to be eked out of Starch.  Instead, you'll\nlikely find that your time in Starch is primarily spent in your store.\nSo, when setting up Starch, picking a store is the most important\ndecision you can make with respect to performance.\n\n# STORES\n\nThese stores are included with the Starch distribution:\n\n- [Starch::Store::Layered](https://metacpan.org/pod/Starch::Store::Layered)\n- [Starch::Store::Memory](https://metacpan.org/pod/Starch::Store::Memory)\n\nThese stores are distributed separately on CPAN:\n\n- [Starch::Store::Amazon::DynamoDB](https://metacpan.org/pod/Starch::Store::Amazon::DynamoDB)\n- [Starch::Store::Catalyst::Plugin::Session](https://metacpan.org/pod/Starch::Store::Catalyst::Plugin::Session)\n- [Starch::Store::CHI](https://metacpan.org/pod/Starch::Store::CHI) - This store is a meta-store which provides\naccess to many other stores such as [CHI::Driver::Redis](https://metacpan.org/pod/CHI::Driver::Redis),\n[CHI::Driver::BerkleyDB](https://metacpan.org/pod/CHI::Driver::BerkleyDB), [CHI::Driver::File](https://metacpan.org/pod/CHI::Driver::File), [CHI::Driver::FastMmap](https://metacpan.org/pod/CHI::Driver::FastMmap),\n[CHI::Driver::Memcached](https://metacpan.org/pod/CHI::Driver::Memcached), and [CHI::Driver::CacheCache](https://metacpan.org/pod/CHI::Driver::CacheCache).\n- [Starch::Store::DBI](https://metacpan.org/pod/Starch::Store::DBI)\n- [Starch::Store::DBIx::Connector](https://metacpan.org/pod/Starch::Store::DBIx::Connector)\n\nMore third-party stores can be found on\n[meta::cpan](https://metacpan.org/search?q=Starch%3A%3AStore).\n\n# PLUGINS\n\nPlugins alter the behavior of the manager ([Starch::Manager](https://metacpan.org/pod/Starch::Manager)),\nstate ([Starch::State](https://metacpan.org/pod/Starch::State)), and store ([Starch::Store](https://metacpan.org/pod/Starch::Store))\nobjects.  To use a plugin pass the `plugins` argument when\ncreating your Starch object:\n\n```perl\nmy $starch = Starch-\u003enew(\n    plugins =\u003e ['::Trace'],\n    store =\u003e { ... },\n    ...,\n);\n```\n\nThese plugins are included with the Starch distribution:\n\n- [Starch::Plugin::AlwaysLoad](https://metacpan.org/pod/Starch::Plugin::AlwaysLoad)\n- [Starch::Plugin::CookieArgs](https://metacpan.org/pod/Starch::Plugin::CookieArgs)\n- [Starch::Plugin::DisableStore](https://metacpan.org/pod/Starch::Plugin::DisableStore)\n- [Starch::Plugin::LogStoreExceptions](https://metacpan.org/pod/Starch::Plugin::LogStoreExceptions)\n- [Starch::Plugin::RenewExpiration](https://metacpan.org/pod/Starch::Plugin::RenewExpiration)\n- [Starch::Plugin::ThrottleStore](https://metacpan.org/pod/Starch::Plugin::ThrottleStore)\n- [Starch::Plugin::Trace](https://metacpan.org/pod/Starch::Plugin::Trace)\n\nThese plugins are distributed separately on CPAN:\n\n- [Starch::Plugin::Net::Statsd](https://metacpan.org/pod/Starch::Plugin::Net::Statsd)\n- [Starch::Plugin::SecureStateID](https://metacpan.org/pod/Starch::Plugin::SecureStateID)\n- [Starch::Plugin::Sereal](https://metacpan.org/pod/Starch::Plugin::Sereal)\n- [Starch::Plugin::TimeoutStore](https://metacpan.org/pod/Starch::Plugin::TimeoutStore)\n\nMore third-party plugins can be found on\n[meta::cpan](https://metacpan.org/search?q=Starch%3A%3APlugin).\n\n# INTEGRATIONS\n\nThe following Starch integrations are available:\n\n- [Catalyst::Plugin::Starch](https://metacpan.org/pod/Catalyst::Plugin::Starch)\n\nIntegrations for [Plack](https://metacpan.org/pod/Plack), [Dancer2](https://metacpan.org/pod/Dancer2), [Mojolicious](https://metacpan.org/pod/Mojolicious), etc will\nbe developed as needed by the people that need them.\n\n# EXTENDING\n\nStarch can be extended by plugins and stores.  See [Starch::Extending](https://metacpan.org/pod/Starch::Extending)\nfor instructions on writing your own.\n\n# ALTERNATIVES\n\n- [CGI::Session](https://metacpan.org/pod/CGI::Session)\n- [Data::Session](https://metacpan.org/pod/Data::Session)\n- [HTTP::Session](https://metacpan.org/pod/HTTP::Session)\n- [Catalyst::Plugin::Session](https://metacpan.org/pod/Catalyst::Plugin::Session)\n- [Plack::Middleware::Session](https://metacpan.org/pod/Plack::Middleware::Session)\n- [Dancer::Session](https://metacpan.org/pod/Dancer::Session)\n- [Mojolicious::Sessions](https://metacpan.org/pod/Mojolicious::Sessions)\n- [MojoX::Session](https://metacpan.org/pod/MojoX::Session)\n\n# SUPPORT\n\nPlease submit bugs and feature requests to the\nStarch GitHub issue tracker:\n\n[https://github.com/bluefeet/Starch/issues](https://github.com/bluefeet/Starch/issues)\n\n# ACKNOWLEDGEMENTS\n\nThanks to [ZipRecruiter](https://www.ziprecruiter.com/)\nfor encouraging their employees to contribute back to the open\nsource ecosystem.  Without their dedication to quality software\ndevelopment this distribution would not exist.\n\n# AUTHORS\n\n```\nAran Clary Deltac \u003caran@bluefeet.dev\u003e\nArthur Axel \"fREW\" Schmidt \u003cfrioux+cpan@gmail.com\u003e\nJonathan Scott Duff \u003cduff@pobox.com\u003e\nIsmail Kerim \u003cismail.kerim@assurant.com\u003e\n```\n\n# COPYRIGHT AND LICENSE\n\nCopyright (C) 2015 Aran Clary Deltac\n\nThis program is free software: you can redistribute it and/or modify\nit under the terms of the GNU General Public License as published by\nthe Free Software Foundation, either version 3 of the License, or\n(at your option) any later version.\n\nThis program is distributed in the hope that it will be useful,\nbut WITHOUT ANY WARRANTY; without even the implied warranty of\nMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\nGNU General Public License for more details.\n\nYou should have received a copy of the GNU General Public License\nalong with this program.  If not, see [http://www.gnu.org/licenses/](http://www.gnu.org/licenses/).\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fbluefeet%2Fstarch","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fbluefeet%2Fstarch","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fbluefeet%2Fstarch/lists"}