{"id":13411450,"url":"https://github.com/stitchfix/stitches","last_synced_at":"2025-05-14T08:07:11.296Z","repository":{"id":33228131,"uuid":"36871711","full_name":"stitchfix/stitches","owner":"stitchfix","description":"Create a Microservice in Rails with minimal ceremony","archived":false,"fork":false,"pushed_at":"2025-03-03T18:06:24.000Z","size":315,"stargazers_count":551,"open_issues_count":6,"forks_count":19,"subscribers_count":99,"default_branch":"main","last_synced_at":"2025-04-15T00:37:29.733Z","etag":null,"topics":["gem","opensource","rails-engine","ruby","ruby-gem"],"latest_commit_sha":null,"homepage":"","language":"Ruby","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/stitchfix.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":"CONTRIBUTING.md","funding":null,"license":"LICENSE.txt","code_of_conduct":"CODE_OF_CONDUCT.md","threat_model":null,"audit":null,"citation":null,"codeowners":".github/CODEOWNERS","security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2015-06-04T13:25:24.000Z","updated_at":"2025-03-03T18:06:27.000Z","dependencies_parsed_at":"2024-04-19T22:28:36.432Z","dependency_job_id":"545d40df-d41f-41cf-8be7-ad14d4970685","html_url":"https://github.com/stitchfix/stitches","commit_stats":{"total_commits":166,"total_committers":41,"mean_commits":4.048780487804878,"dds":0.7048192771084337,"last_synced_commit":"6f9218eca4abf7599fc9731bad531d218cd070ca"},"previous_names":[],"tags_count":37,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/stitchfix%2Fstitches","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/stitchfix%2Fstitches/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/stitchfix%2Fstitches/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/stitchfix%2Fstitches/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/stitchfix","download_url":"https://codeload.github.com/stitchfix/stitches/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":254101618,"owners_count":22014909,"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":["gem","opensource","rails-engine","ruby","ruby-gem"],"created_at":"2024-07-30T20:01:13.795Z","updated_at":"2025-05-14T08:07:11.275Z","avatar_url":"https://github.com/stitchfix.png","language":"Ruby","readme":"Create Microservices in Rails by pretty much just writing regular Rails code.\n\nThis gem provides:\n\n- transparent API key authentication.\n- router-level API version based on headers.\n- a way to document your microservice endpoints via acceptance tests.\n- structured errors, buildable from invalid Active Records, Exceptions, or by hand.\n\nThis, plus much of what you get from Rails already, means you can create a microservice Rails application by just writing the\nsame Rails code you write today. Instead of rendering web views, you render JSON (which is built into Rails).\n\n## To install\n\nAdd to your `Gemfile`:\n\n```ruby\ngem 'stitches'\n```\n\nThen:\n\n```\nbundle install\n```\n\nThen, set it up:\n\n```bash\n\u003e bin/rails generate stitches:api\n\u003e bin/rails generate stitches:api_migration # only if you're using API key authentication\n\u003e bundle exec rake db:migrate               # only if you're using API key authentication\n```\n\n### Disable API Key Support\n\nIf you're not using the API Key authentication feature of the library, configure stitches:\n\n```ruby\nStitches.configure do |config|\n  config.disable_api_key_support = true\nend\n```\n\n### Upgrading from an older version\n\n- When upgrading to version 4.0.0 and above you may now take advantage of an in-memory cache\n\nYou can enabled it like so\n\n```ruby\nStitches.configure do |config|\n  config.max_cache_ttl = 5  # seconds\n  config.max_cache_size = 100  # how many keys to cache\nend\n```\n\nYou can also set a leniency for disabled API keys, which will allow old API keys to continue to be used if they have a\n`disabled_at` field set as long as the leniency is not exceeded. Note that if the `disabled_at` field is not populated\nthe behavior will remain the same as it always was, and the request will be denied when the `enabled` field is set to\n`true`. If Stitches allows a call due to leniency settings, a log message will be generated with a severity depending on\nhow long ago the API key was disabled.\n\n```ruby\nStitches.configure do |config|\n  config.disabled_key_leniency_in_seconds = 3 * 24 * 60 * 60 # Time in seconds, defaults to three days\n  config.disabled_key_leniency_error_log_threshold_in_seconds = 2 * 24 * 60 * 60 # Time in seconds, defaults to two days\nend\n```\n\nIf a disabled key is used within the `disabled_key_leniency_in_seconds`, it will be allowed.\n\nAnytime a disabled key is used a log will be generated. If it is before the\n`disabled_key_leniency_error_log_threshold_in_seconds` it will be a warning log message, if it is after that, it will be\nan error message. `disabled_key_leniency_error_log_threshold_in_seconds` should never be a greater number than\n`disabled_key_leniency_in_seconds`, as this provides an escallating series of warnings before finally disabling access.\n\n- If you are upgrading from a version older than 3.3.0 you need to run three generators, two of which create database\n  migrations on your `api_clients` table:\n\n  ```\n  \u003e bin/rails generate stitches:add_enabled_to_api_clients\n  \u003e bin/rails generate stitches:add_deprecation\n  \u003e bin/rails generate stitches:add_disabled_at_to_api_clients\n  ```\n\n- If you are upgrading from a version between 3.3.0 and 3.5.0 you need to run two generators:\n\n  ```\n  \u003e bin/rails generate stitches:add_deprecation\n  \u003e bin/rails generate stitches:add_disabled_at_to_api_clients\n  ```\n\n- If you are upgrading from a version between 3.6.0 and 4.0.2 you need to run one generator:\n\n  ```\n  \u003e bin/rails generate stitches:add_disabled_at_to_api_clients\n  ```\n\n## Example Microservice Endpoint\n\nSuppose we wish to allow our consumers to create Widgets\n\n```ruby\nclass Api::V1::WidgetsController \u003c ApiController\n  def create\n    widget = Widget.create(widget_params)\n    if widget.valid?\n      head 201\n    else\n      render json: {\n        errors: Stitches::Errors.from_active_record_object(widget)\n      }, status: 422\n    end\n  end\n\nprivate\n\n  def widget_params\n    params.require(:widget).permit(:name, :type, :sub_type)\n  end\nend\n```\n\nIf you think there's nothing special about this—you are correct. This is the vanillaest of vanilla Rails controllers, with a few\nnotable exceptions:\n\n- We aren't checking content type. A stitches-based microservice always uses JSON and refuses to route requests for non-JSON to\n  you, so there's zero need to use `respond_to` and friends.\n- The error-building is structured and reliable.\n- This is an authenticated request. No request without proper authentication will be routed here, so you don't have to worry\n  about it in your code.\n- This is a versioned request. While the URL will _not_ contain `v1` in it, the `Accept` header will require a version and get\n  routed here. If you make a V2, it's just a new controller and this concern is handled at the routing layer.\n\nAll this means that the Rails skills of you and your team can be directly applied to building microservices. You don't have to make a bunch of boring decisions about auth, versioning, or content-types. It also means you can start deploying and creating microservices with little friction. No need to deal with a complex DSL or new programming language to get yourselves going with Microservices.\n\n## More Info\n\nSee [the wiki](https://github.com/stitchfix/stitches/wiki/Setup) for how to setup stitches.\n\n- [Stitches Features](https://github.com/stitchfix/stitches/wiki/Features-of-Stitches) include:\n  - Authorization via API key\n  - Versioned requests via HTTP content types\n  - Structured Errors\n  - ISO 8601-formatted dates\n  - Deprecation using the `Sunset` header\n  - An optional ApiKey cache to allow mostly DB free APIs\n- The [Generator](https://github.com/stitchfix/stitches/wiki/Generator) sets up some code in your app, so you can start writing\n  APIs using vanilla Rails idioms:\n  - a \"ping\" controller that can validate your app is working\n  - version routing based on content-type (requests for V2 use the same URL, but are serviced by a different controller)\n  - An ApiClient Active Record\n  - Acceptance tests that can produce API documentation as they test your app.\n- Stitches provides [testing support](https://github.com/stitchfix/stitches/wiki/Testing)\n\n## API Key Caching\n\nSince version 4.0.0, stitches now has the ability to cache API keys in\nmemory for a configurable amount of time. This may be an improvement for\nsome applications.\n\nYou must configure the API Cache for it be used.\n\n```ruby\nStitches.configure do |config|\n  config.max_cache_ttl = 5  # seconds\n  config.max_cache_size = 100  # how many keys to cache\nend\n```\n\nYour cache size should be\nlarger then the number of consumer keys your service has.\n\n## Developing\n\nAlthough `Stitches.configuration` is global, do not depend directly on that in your logic. Instead, allow all classes to receive a configuration object in their constructor. This makes the classes easier to deal with and change, without incurring much of a real cost to development. Global symbols suck, but are convenient. This is how you make the most of it.\n\nAlso, the integration test does a lot of \"testing the implementation\", but since Rails generators are notorious for silently\nfailing with a successful result, we have to make sure that the various `inject_into_file` calls are actually working. Do not do\nany fancy refactors here, just keep it up to date.\n\n## Ruby / Rails version support\n\nThis gem attempts to support the most recent 2 major/minor versions of Ruby and Rails. This is a moving\ntarget, and we make a best effort to track to this policy. Older versions _may_ work, but supporting\nthose versions is outside of the scope of what we intend to maintain.\n\n## Releases\n\nSee the release process for open source gems in the Stitch Fix engineering wiki under technical topics.\n\n---\n\nProvided with love by your friends at [Stitch Fix Engineering](http://technology.stitchfix.com)\n","funding_links":[],"categories":["Ruby"],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fstitchfix%2Fstitches","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fstitchfix%2Fstitches","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fstitchfix%2Fstitches/lists"}