Skip to content

Commit

Permalink
Finish up support for Accept
Browse files Browse the repository at this point in the history
  • Loading branch information
mjackson committed Dec 20, 2024
1 parent 9726d85 commit 0735a75
Show file tree
Hide file tree
Showing 7 changed files with 310 additions and 118 deletions.
42 changes: 35 additions & 7 deletions packages/headers/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -72,22 +72,50 @@ let ms = new Date().getTime();
let headers = new SuperHeaders({ lastModified: ms });
```

- Adds support for
- Added `AcceptLanguage.prototype.accepts(language)`, `AcceptLanguage.prototype.getQuality(language)`,
`AcceptLanguage.prototype.getPreferred(languages)`

- `headers.accept`
- `headers.connection`
- `headers.host`
- `headers.referer`
```ts
import { AcceptLanguage } from '@mjackson/headers';

let header = new AcceptLanguage({ 'en-US': 1, en: 0.9 });

header.accepts('en-US'); // true
header.accepts('en-GB'); // true
header.accepts('en'); // true
header.accepts('fr'); // false

header.getQuality('en-US'); // 1
header.getQuality('en-GB'); // 0.9

header.getPreferred(['en-GB', 'en-US']); // 'en-US'
```

- Adds low-level `Accept` API
- Added `Accept` support

```ts
import { Accept } from '@mjackson/headers';

let header = new Accept({ 'text/html': 1, 'text/*': 0.9 });
header.get('text/html'); // 1

header.accepts('text/html'); // true
header.accepts('text/plain'); // true
header.accepts('text/*'); // true
header.accepts('image/jpeg'); // false

header.getQuality('text/html'); // 1
header.getQuality('text/plain'); // 0.9

header.getPreferred(['text/html', 'text/plain']); // 'text/html'
```

- Added property support (getters and setters) for

- `headers.accept`
- `headers.connection`
- `headers.host`
- `headers.referer`

## v0.8.0 (2024-11-14)

- Added CommonJS build
Expand Down
47 changes: 36 additions & 11 deletions packages/headers/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ HTTP headers contain a wealth of information:
- Who is sending this request?
- What's in the payload and how is it encoded?
- What is the filename of this file upload?
- and much, much more!
- and much more!

The [built-in JavaScript `Headers` interface](https://developer.mozilla.org/en-US/docs/Web/API/Headers) accepts and gives you strings for everything, which you're probably used to parsing and stringifying manually as needed. This library aims to give you a more fluent interface for all of this information. Similar to how the DOM gives you programmatic access to HTML documents, `headers` gives you access to HTTP headers.

Expand All @@ -30,6 +30,12 @@ headers.accept = 'text/html,text/*;q=0.9';
console.log(headers.accept.mediaTypes); // [ 'text/html', 'text/*' ]
console.log(Object.fromEntries(headers.accept.entries())); // { 'text/html': 1, 'text/*': 0.9 }

headers.accept.accepts('text/html'); // true
headers.accept.accepts('text/plain'); // true
headers.accept.accepts('image/jpeg'); // false

headers.accept.getPreferred(['text/plain', 'text/html']); // 'text/html'

headers.accept.set('text/plain', 0.9);
headers.accept.set('text/*', 0.8);

Expand All @@ -38,8 +44,14 @@ console.log(headers.get('Accept')); // "text/html,text/plain;q=0.9,text/*;q=0.8"
// Accept-Language
headers.acceptLanguage = 'en-US,en;q=0.9';

console.log(headers.acceptLanguage.languages); // [ 'en-US', 'en' ]
console.log(Object.fromEntries(headers.acceptLanguage.entries())); // { 'en-US': 1, en: 0.9 }
console.log(headers.acceptLanguage.languages); // [ 'en-us', 'en' ]
console.log(Object.fromEntries(headers.acceptLanguage.entries())); // { 'en-us': 1, en: 0.9 }

headers.acceptLanguage.accepts('en'); // true
headers.acceptLanguage.accepts('ja'); // false

headers.acceptLanguage.getPreferred(['en-US', 'en-GB']); // 'en-US'
headers.acceptLanguage.getPreferred(['en', 'fr']); // 'en'

// Content-Type
headers.contentType = 'application/json; charset=utf-8';
Expand Down Expand Up @@ -192,10 +204,16 @@ If you need support for a header that isn't listed here, please [send a PR](http

```ts
let header = new Accept('text/html;text/*;q=0.9');
header.get('text/html'); // 1
header.set('text/html', 0.8);
header.delete('text/html');
header.has('text/*'); // true

header.has('text/html'); // true
header.has('text/plain'); // false

header.accepts('text/html'); // true
header.accepts('text/plain'); // true
header.accepts('text/*'); // true
header.accepts('image/jpeg'); // false

header.getPreferred(['text/html', 'text/plain']); // 'text/html'

// Iterate over media type/quality pairs
for (let [mediaType, quality] of header) {
Expand All @@ -211,10 +229,17 @@ let header = new Accept(['text/html', ['text/*', 0.9]]);

```ts
let header = new AcceptLanguage('en-US,en;q=0.9');
header.get('en-US'); // 1
header.set('en-US', 0.8);
header.delete('en-US');
header.has('en'); // true

header.has('en-US'); // true
header.has('en-GB'); // false

header.accepts('en-US'); // true
header.accepts('en-GB'); // true
header.accepts('en'); // true
header.accepts('fr'); // true

header.getPreferred(['en-US', 'en-GB']); // 'en-US'
header.getPreferred(['en', 'fr']); // 'en'

// Iterate over language/quality pairs
for (let [language, quality] of header) {
Expand Down
92 changes: 54 additions & 38 deletions packages/headers/src/lib/accept-language.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,32 +11,64 @@ describe('Accept-Language', () => {

it('initializes with a string', () => {
let header = new AcceptLanguage('en-US,en;q=0.9');
assert.equal(header.get('en-US'), 1);
assert.equal(header.get('en'), 0.9);
assert.equal(header.size, 2);
});

it('initializes with an array', () => {
let header = new AcceptLanguage(['en-US', ['en', 0.9]]);
assert.equal(header.get('en-US'), 1);
assert.equal(header.get('en'), 0.9);
assert.equal(header.size, 2);
});

it('initializes with an object', () => {
let header = new AcceptLanguage({ 'en-US': 1, en: 0.9 });
assert.equal(header.get('en-US'), 1);
assert.equal(header.get('en'), 0.9);
assert.equal(header.size, 2);
});

it('initializes with another AcceptLanguage', () => {
let header = new AcceptLanguage(new AcceptLanguage('en-US,en;q=0.9'));
assert.equal(header.get('en-US'), 1);
assert.equal(header.get('en'), 0.9);
assert.equal(header.size, 2);
});

it('handles whitespace in initial value', () => {
let header = new AcceptLanguage(' en-US , en;q= 0.9 ');
assert.equal(header.get('en-US'), 1);
assert.equal(header.get('en'), 0.9);
assert.equal(header.size, 2);
});

it('gets all languages', () => {
let header = new AcceptLanguage('en-US,en;q=0.9');
assert.deepEqual(header.languages, ['en-us', 'en']);
});

it('gets all qualities', () => {
let header = new AcceptLanguage('en-US,en;q=0.9');
assert.deepEqual(header.qualities, [1, 0.9]);
});

it('checks if a language is acceptable', () => {
let header = new AcceptLanguage('en-US,en;q=0.9,fr;q=0.8');
assert.equal(header.accepts('en-US'), true);
assert.equal(header.accepts('en'), true);
assert.equal(header.accepts('en-GB'), true);
assert.equal(header.accepts('fr'), true);
assert.equal(header.accepts('fi'), false);
});

it('gets the correct quality values', () => {
let header = new AcceptLanguage('en-US,en;q=0.9,fr;q=0.8');
assert.equal(header.getQuality('en-US'), 1);
assert.equal(header.getQuality('*'), 1);
assert.equal(header.getQuality('en'), 1);
assert.equal(header.getQuality('en-GB'), 0.9);
assert.equal(header.getQuality('fr'), 0.8);
assert.equal(header.getQuality('fi'), 0);
});

it('gets the preferred language', () => {
let header = new AcceptLanguage('en-US,en;q=0.9');
assert.equal(header.getPreferred(['en-GB', 'en-US']), 'en-US');
assert.equal(header.getPreferred(['en-GB', 'en']), 'en');
assert.equal(header.getPreferred(['fr', 'en-GB']), 'en-GB');
assert.equal(header.getPreferred(['fi', 'ja']), null);
});

it('sets and gets languages', () => {
Expand All @@ -46,16 +78,10 @@ describe('Accept-Language', () => {
});

it('deletes languages', () => {
let header = new AcceptLanguage('en-US');
assert.equal(header.delete('en-US'), true);
assert.equal(header.delete('en'), false);
assert.equal(header.get('en-US'), undefined);
});

it('checks if language exists', () => {
let header = new AcceptLanguage('en-US');
assert.equal(header.has('en-US'), true);
assert.equal(header.has('fs'), false);
header.delete('en-US');
assert.equal(header.has('en-US'), false);
});

it('clears all languages', () => {
Expand All @@ -64,21 +90,11 @@ describe('Accept-Language', () => {
assert.equal(header.size, 0);
});

it('gets all languages', () => {
let header = new AcceptLanguage('en-US,en;q=0.9');
assert.deepEqual(header.languages, ['en-US', 'en']);
});

it('gets all qualities', () => {
let header = new AcceptLanguage('en-US,en;q=0.9');
assert.deepEqual(header.qualities, [1, 0.9]);
});

it('iterates over entries', () => {
let header = new AcceptLanguage('en-US,en;q=0.9');
let entries = Array.from(header.entries());
assert.deepEqual(entries, [
['en-US', 1],
['en-us', 1],
['en', 0.9],
]);
});
Expand All @@ -87,7 +103,7 @@ describe('Accept-Language', () => {
let header = new AcceptLanguage('en-US,en;q=0.9');
let entries = Array.from(header);
assert.deepEqual(entries, [
['en-US', 1],
['en-us', 1],
['en', 0.9],
]);
});
Expand All @@ -99,7 +115,7 @@ describe('Accept-Language', () => {
result.push([language, quality]);
});
assert.deepEqual(result, [
['en-US', 1],
['en-us', 1],
['en', 0.9],
]);
});
Expand All @@ -111,7 +127,7 @@ describe('Accept-Language', () => {

it('converts to string correctly', () => {
let header = new AcceptLanguage('en-US,en;q=0.9');
assert.equal(header.toString(), 'en-US,en;q=0.9');
assert.equal(header.toString(), 'en-us,en;q=0.9');
});

it('handles setting empty quality values', () => {
Expand All @@ -134,17 +150,17 @@ describe('Accept-Language', () => {

it('sorts initial value', () => {
let header = new AcceptLanguage('en;q=0.9,en-US');
assert.equal(header.toString(), 'en-US,en;q=0.9');
assert.deepEqual(header.languages, ['en-US', 'en']);
assert.equal(header.toString(), 'en-us,en;q=0.9');
assert.deepEqual(header.languages, ['en-us', 'en']);
});

it('sorts updated value', () => {
let header = new AcceptLanguage('en-US,en;q=0.9');
header.set('fi');
assert.equal(header.toString(), 'en-US,fi,en;q=0.9');
assert.deepEqual(header.languages, ['en-US', 'fi', 'en']);
assert.equal(header.toString(), 'en-us,fi,en;q=0.9');
assert.deepEqual(header.languages, ['en-us', 'fi', 'en']);
header.set('en-US', 0.8);
assert.equal(header.toString(), 'fi,en;q=0.9,en-US;q=0.8');
assert.deepEqual(header.languages, ['fi', 'en', 'en-US']);
assert.equal(header.toString(), 'fi,en;q=0.9,en-us;q=0.8');
assert.deepEqual(header.languages, ['fi', 'en', 'en-us']);
});
});
Loading

0 comments on commit 0735a75

Please sign in to comment.