{"id":13878151,"url":"https://github.com/socketry/http-accept","last_synced_at":"2025-03-06T09:16:33.785Z","repository":{"id":46986551,"uuid":"51002118","full_name":"socketry/http-accept","owner":"socketry","description":"Parse Accept and Accept-Language HTTP headers in Ruby.","archived":false,"fork":false,"pushed_at":"2024-09-03T22:38:02.000Z","size":108,"stargazers_count":83,"open_issues_count":5,"forks_count":10,"subscribers_count":10,"default_branch":"main","last_synced_at":"2024-10-29T12:57:39.897Z","etag":null,"topics":["http","http-client","http-server","parsing"],"latest_commit_sha":null,"homepage":null,"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/socketry.png","metadata":{"files":{"readme":"readme.md","changelog":null,"contributing":null,"funding":null,"license":"license.md","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":"2016-02-03T13:41:56.000Z","updated_at":"2024-07-22T23:16:41.000Z","dependencies_parsed_at":"2024-06-18T14:08:01.019Z","dependency_job_id":"021f7e39-3b7e-44ba-b25c-bfec2970f402","html_url":"https://github.com/socketry/http-accept","commit_stats":{"total_commits":84,"total_committers":8,"mean_commits":10.5,"dds":"0.11904761904761907","last_synced_commit":"fb4fabbf2e95e097147c3580fe061638fc7bcb3f"},"previous_names":["ioquatix/http-accept"],"tags_count":18,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/socketry%2Fhttp-accept","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/socketry%2Fhttp-accept/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/socketry%2Fhttp-accept/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/socketry%2Fhttp-accept/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/socketry","download_url":"https://codeload.github.com/socketry/http-accept/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":230454410,"owners_count":18228392,"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":["http","http-client","http-server","parsing"],"created_at":"2024-08-06T08:01:41.161Z","updated_at":"2024-12-23T20:10:43.609Z","avatar_url":"https://github.com/socketry.png","language":"Ruby","readme":"# HTTP::Accept\n\nProvides a robust set of parsers for dealing with HTTP `Accept`, `Accept-Language`, `Accept-Encoding`, `Accept-Charset` headers.\n\n[![Development Status](https://github.com/socketry/http-accept/workflows/Test/badge.svg)](https://github.com/socketry/http-accept/actions?workflow=Test)\n\n## Motivation\n\nI've been [developing some tools for building RESTful endpoints](https://github.com/ioquatix/utopia/blob/master/lib/utopia/controller/respond.rb) and part of that involved versioning. After reviewing the options, I settled on using the `Accept: application/json;version=1` method [as outlined here](http://labs.qandidate.com/blog/2014/10/16/using-the-accept-header-to-version-your-api/).\n\nThe `version=1` part of the `media-type` is a `parameter` as defined by [RFC7231 Section 3.1.1.1](https://tools.ietf.org/html/rfc7231#section-3.1.1.1). After reviewing several existing different options for parsing the `Accept:` header, I noticed a disturbing trend: `header.split(',')`. Because parameters may contain quoted strings which contain commas, this is clearly not an appropriate way to parse the header.\n\nI am concerned about correctness, security and performance. As such, I implemented this gem to provide a simple high level interface for both parsing and correctly interpreting these headers.\n\n## Installation\n\nAdd this line to your application's Gemfile:\n\n``` ruby\ngem 'http-accept'\n```\n\nAnd then execute:\n\n    $ bundle\n\nOr install it yourself as:\n\n    $ gem install http-accept\n\nYou can then require it in your code like so:\n\n``` ruby\nrequire 'http/accept'\n```\n\n## Usage\n\nHere are some examples of how to parse various headers.\n\n### Parsing Accept: headers\n\nYou can parse the incoming `Accept:` header:\n\n``` ruby\nmedia_types = HTTP::Accept::MediaTypes.parse(\"text/html;q=0.5, application/json; version=1\")\n\nexpect(media_types[0].mime_type).to be == \"application/json\"\nexpect(media_types[0].parameters).to be == {'version' =\u003e '1'}\nexpect(media_types[1].mime_type).to be == \"text/html\"\nexpect(media_types[1].parameters).to be == {'q' =\u003e '0.5'}\n```\n\nNormally, you'd want to match the media types against some set of available mime types:\n\n``` ruby\nmodule ToJSON\n  def content_type\n    HTTP::Accept::ContentType.new(\"application\", \"json\", charset: 'utf-8')\n  end\n\n  # Used for inserting into map.\n  def split(*args)\n    content_type.split(*args)\n  end\n\n  def convert(object, options)\n    object.to_json\n  end\nend\n\nmodule ToXML\n  # Are you kidding?\nend\n\nmap = HTTP::Accept::MediaTypes::Map.new\nmap \u003c\u003c ToJSON\nmap \u003c\u003c ToXML\n\nobject, media_range = map.for(media_types)\ncontent = object.convert(model, media_range.parameters)\nresponse = [200, {'Content-Type' =\u003e object.content_type}, [content]]\n```\n\n### Parsing Accept-Language: headers\n\nYou can parse the incoming `Accept-Language:` header:\n\n``` ruby\nlanguages = HTTP::Accept::Languages.parse(\"da, en-gb;q=0.8, en;q=0.7\")\n\nexpect(languages[0].locale).to be == \"da\"\nexpect(languages[1].locale).to be == \"en-gb\"\nexpect(languages[2].locale).to be == \"en\"\n```\n\nNormally, you'd want to match the languages against some set of available localizations:\n\n``` ruby\navailable_localizations = HTTP::Accept::Languages::Locales.new([\"en-nz\", \"en-us\"])\n\n# Given the languages that the user wants, and the localizations available, compute the set of desired localizations.\ndesired_localizations = available_localizations \u0026 languages\n```\n\nThe `desired_localizations` in the example above is a subset of `available_localizations`.\n\n`HTTP::Accept::Languages::Locales` provides an efficient data-structure for matching the Accept-Languages header to set of available localizations according to \u003chttps://tools.ietf.org/html/rfc7231#section-5.3.5\u003e and \u003chttps://tools.ietf.org/html/rfc4647#section-2.3\u003e\n\n## Contributing\n\nWe welcome contributions to this project.\n\n1.  Fork it.\n2.  Create your feature branch (`git checkout -b my-new-feature`).\n3.  Commit your changes (`git commit -am 'Add some feature'`).\n4.  Push to the branch (`git push origin my-new-feature`).\n5.  Create new Pull Request.\n\n### Developer Certificate of Origin\n\nThis project uses the [Developer Certificate of Origin](https://developercertificate.org/). All contributors to this project must agree to this document to have their contributions accepted.\n\n### Contributor Covenant\n\nThis project is governed by the [Contributor Covenant](https://www.contributor-covenant.org/). All contributors and participants agree to abide by its terms.\n","funding_links":[],"categories":["Ruby"],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fsocketry%2Fhttp-accept","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fsocketry%2Fhttp-accept","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fsocketry%2Fhttp-accept/lists"}