Ecosyste.ms: Awesome
An open API service indexing awesome lists of open source software.
https://github.com/socketry/http-accept
Parse Accept and Accept-Language HTTP headers in Ruby.
https://github.com/socketry/http-accept
http http-client http-server parsing
Last synced: 3 months ago
JSON representation
Parse Accept and Accept-Language HTTP headers in Ruby.
- Host: GitHub
- URL: https://github.com/socketry/http-accept
- Owner: socketry
- License: mit
- Created: 2016-02-03T13:41:56.000Z (over 8 years ago)
- Default Branch: main
- Last Pushed: 2024-02-05T04:01:43.000Z (9 months ago)
- Last Synced: 2024-05-08T18:26:16.440Z (6 months ago)
- Topics: http, http-client, http-server, parsing
- Language: Ruby
- Size: 104 KB
- Stars: 81
- Watchers: 10
- Forks: 10
- Open Issues: 4
-
Metadata Files:
- Readme: readme.md
- License: license.md
Awesome Lists containing this project
README
# HTTP::Accept
Provides a robust set of parsers for dealing with HTTP `Accept`, `Accept-Language`, `Accept-Encoding`, `Accept-Charset` headers.
[![Development Status](https://github.com/socketry/http-accept/workflows/Test/badge.svg)](https://github.com/socketry/http-accept/actions?workflow=Test)
## Motivation
I'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/).
The `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.
I 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.
## Installation
Add this line to your application's Gemfile:
``` ruby
gem 'http-accept'
```And then execute:
$ bundle
Or install it yourself as:
$ gem install http-accept
You can then require it in your code like so:
``` ruby
require 'http/accept'
```## Usage
Here are some examples of how to parse various headers.
### Parsing Accept: headers
You can parse the incoming `Accept:` header:
``` ruby
media_types = HTTP::Accept::MediaTypes.parse("text/html;q=0.5, application/json; version=1")expect(media_types[0].mime_type).to be == "application/json"
expect(media_types[0].parameters).to be == {'version' => '1'}
expect(media_types[1].mime_type).to be == "text/html"
expect(media_types[1].parameters).to be == {'q' => '0.5'}
```Normally, you'd want to match the media types against some set of available mime types:
``` ruby
module ToJSON
def content_type
HTTP::Accept::ContentType.new("application", "json", charset: 'utf-8')
end# Used for inserting into map.
def split(*args)
content_type.split(*args)
enddef convert(object, options)
object.to_json
end
endmodule ToXML
# Are you kidding?
endmap = HTTP::Accept::MediaTypes::Map.new
map << ToJSON
map << ToXMLobject, media_range = map.for(media_types)
content = object.convert(model, media_range.parameters)
response = [200, {'Content-Type' => object.content_type}, [content]]
```### Parsing Accept-Language: headers
You can parse the incoming `Accept-Language:` header:
``` ruby
languages = HTTP::Accept::Languages.parse("da, en-gb;q=0.8, en;q=0.7")expect(languages[0].locale).to be == "da"
expect(languages[1].locale).to be == "en-gb"
expect(languages[2].locale).to be == "en"
```Normally, you'd want to match the languages against some set of available localizations:
``` ruby
available_localizations = HTTP::Accept::Languages::Locales.new(["en-nz", "en-us"])# Given the languages that the user wants, and the localizations available, compute the set of desired localizations.
desired_localizations = available_localizations & languages
```The `desired_localizations` in the example above is a subset of `available_localizations`.
`HTTP::Accept::Languages::Locales` provides an efficient data-structure for matching the Accept-Languages header to set of available localizations according to and
## Contributing
We welcome contributions to this project.
1. Fork it.
2. Create your feature branch (`git checkout -b my-new-feature`).
3. Commit your changes (`git commit -am 'Add some feature'`).
4. Push to the branch (`git push origin my-new-feature`).
5. Create new Pull Request.### Developer Certificate of Origin
This 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.
### Contributor Covenant
This project is governed by the [Contributor Covenant](https://www.contributor-covenant.org/). All contributors and participants agree to abide by its terms.