Skip to content

Commit de7b61e

Browse files
committed
Add Content-Encoding, Content-Language, and Location support
1 parent 3d49e31 commit de7b61e

File tree

4 files changed

+169
-39
lines changed

4 files changed

+169
-39
lines changed

packages/headers/CHANGELOG.md

+3
Original file line numberDiff line numberDiff line change
@@ -132,7 +132,10 @@ header.getPreferred(['gzip', 'deflate']); // 'gzip'
132132
- `acceptEncoding`
133133
- `acceptRanges`
134134
- `connection`
135+
- `contentEncoding`
136+
- `contentLanguage`
135137
- `host`
138+
- `location`
136139
- `referer`
137140

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

packages/headers/README.md

+28-21
Original file line numberDiff line numberDiff line change
@@ -28,8 +28,8 @@ let headers = new Headers();
2828
headers.accept = { 'text/html': 1, 'text/*': 0.9 };
2929
// or headers.accept = 'text/html,text/*;q=0.9';
3030

31-
console.log(headers.accept.mediaTypes); // [ 'text/html', 'text/*' ]
32-
console.log(Object.fromEntries(headers.accept.entries())); // { 'text/html': 1, 'text/*': 0.9 }
31+
headers.accept.mediaTypes; // [ 'text/html', 'text/*' ]
32+
Object.fromEntries(headers.accept.entries()); // { 'text/html': 1, 'text/*': 0.9 }
3333

3434
headers.accept.accepts('text/html'); // true
3535
headers.accept.accepts('text/plain'); // true
@@ -40,7 +40,7 @@ headers.accept.getPreferred(['text/plain', 'text/html']); // 'text/html'
4040
headers.accept.set('text/plain', 0.9);
4141
headers.accept.set('text/*', 0.8);
4242

43-
console.log(headers.get('Accept')); // "text/html,text/plain;q=0.9,text/*;q=0.8"
43+
headers.get('Accept'); // 'text/html,text/plain;q=0.9,text/*;q=0.8'
4444

4545
// Accept-Encoding
4646
headers.acceptEncoding = { gzip: 1, deflate: 0.8 };
@@ -55,8 +55,8 @@ headers.acceptEncoding.getPreferred(['gzip', 'deflate']); // 'gzip'
5555
headers.acceptLanguage = { 'en-US': 1, en: 0.9 };
5656
// or headers.acceptLanguage = 'en-US,en;q=0.9';
5757

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

6161
headers.acceptLanguage.accepts('en'); // true
6262
headers.acceptLanguage.accepts('ja'); // false
@@ -73,51 +73,58 @@ headers.connection = 'close';
7373
// Content-Type
7474
headers.contentType = 'application/json; charset=utf-8';
7575

76-
console.log(headers.contentType.mediaType); // "application/json"
77-
console.log(headers.contentType.charset); // "utf-8"
76+
headers.contentType.mediaType; // "application/json"
77+
headers.contentType.charset; // "utf-8"
7878

7979
headers.contentType.charset = 'iso-8859-1';
8080

81-
console.log(headers.get('Content-Type')); // "application/json; charset=iso-8859-1"
81+
headers.get('Content-Type'); // "application/json; charset=iso-8859-1"
8282

8383
// Content-Disposition
8484
headers.contentDisposition =
8585
'attachment; filename="example.pdf"; filename*=UTF-8\'\'%E4%BE%8B%E5%AD%90.pdf';
8686

87-
console.log(headers.contentDisposition.type); // 'attachment'
88-
console.log(headers.contentDisposition.filename); // 'example.pdf'
89-
console.log(headers.contentDisposition.filenameSplat); // 'UTF-8\'\'%E4%BE%8B%E5%AD%90.pdf'
90-
console.log(headers.contentDisposition.preferredFilename); // '例子.pdf'
87+
headers.contentDisposition.type; // 'attachment'
88+
headers.contentDisposition.filename; // 'example.pdf'
89+
headers.contentDisposition.filenameSplat; // 'UTF-8\'\'%E4%BE%8B%E5%AD%90.pdf'
90+
headers.contentDisposition.preferredFilename; // '例子.pdf'
9191

9292
// Cookie
9393
headers.cookie = 'session_id=abc123; user_id=12345';
9494

95-
console.log(headers.cookie.get('session_id')); // 'abc123'
96-
console.log(headers.cookie.get('user_id')); // '12345'
95+
headers.cookie.get('session_id'); // 'abc123'
96+
headers.cookie.get('user_id'); // '12345'
9797

9898
headers.cookie.set('theme', 'dark');
99-
console.log(headers.get('Cookie')); // 'session_id=abc123; user_id=12345; theme=dark'
99+
headers.get('Cookie'); // 'session_id=abc123; user_id=12345; theme=dark'
100100

101101
// Host
102102
headers.host = 'example.com';
103103

104+
// Last-Modified
105+
headers.lastModified = new Date();
106+
// or headers.lastModified = new Date().getTime();
107+
headers.get('Last-Modified'); // 'Fri, 20 Dec 2024 08:08:05 GMT'
108+
109+
// Location
110+
headers.location = 'https://example.com';
111+
104112
// Referer
105113
headers.referer = 'https://example.com/';
106114

107115
// Set-Cookie
108116
headers.setCookie = ['session_id=abc123; Path=/; HttpOnly'];
109117

110-
console.log(headers.setCookie[0].name); // 'session_id'
111-
console.log(headers.setCookie[0].value); // 'abc123'
112-
console.log(headers.setCookie[0].path); // '/'
113-
console.log(headers.setCookie[0].httpOnly); // true
118+
headers.setCookie[0].name; // 'session_id'
119+
headers.setCookie[0].value; // 'abc123'
120+
headers.setCookie[0].path; // '/'
121+
headers.setCookie[0].httpOnly; // true
114122

115123
// Modifying Set-Cookie attributes
116124
headers.setCookie[0].maxAge = 3600;
117125
headers.setCookie[0].secure = true;
118126

119-
console.log(headers.get('Set-Cookie'));
120-
// session_id=abc123; Path=/; HttpOnly; Max-Age=3600; Secure
127+
headers.get('Set-Cookie'); // 'session_id=abc123; Path=/; HttpOnly; Max-Age=3600; Secure'
121128

122129
// Setting multiple cookies is easy, it's just an array
123130
headers.setCookie.push('user_id=12345; Path=/api; Secure');

packages/headers/src/lib/super-headers.test.ts

+75-18
Original file line numberDiff line numberDiff line change
@@ -200,6 +200,16 @@ describe('SuperHeaders', () => {
200200
assert.equal(headers.get('Content-Disposition'), 'attachment; filename=example.txt');
201201
});
202202

203+
it('handles the contentEncoding property', () => {
204+
let headers = new SuperHeaders({ contentEncoding: 'gzip' });
205+
assert.equal(headers.get('Content-Encoding'), 'gzip');
206+
});
207+
208+
it('handles the contentLanguage property', () => {
209+
let headers = new SuperHeaders({ contentLanguage: 'en-US' });
210+
assert.equal(headers.get('Content-Language'), 'en-US');
211+
});
212+
203213
it('handles the contentLength property', () => {
204214
let headers = new SuperHeaders({ contentLength: 42 });
205215
assert.equal(headers.get('Content-Length'), '42');
@@ -232,11 +242,6 @@ describe('SuperHeaders', () => {
232242
assert.equal(headers.get('Host'), 'example.com');
233243
});
234244

235-
it('handles the lastModified property', () => {
236-
let headers = new SuperHeaders({ lastModified: new Date('2021-01-01T00:00:00Z') });
237-
assert.equal(headers.get('Last-Modified'), 'Fri, 01 Jan 2021 00:00:00 GMT');
238-
});
239-
240245
it('handles the ifModifiedSince property', () => {
241246
let headers = new SuperHeaders({ ifModifiedSince: new Date('2021-01-01T00:00:00Z') });
242247
assert.equal(headers.get('If-Modified-Since'), 'Fri, 01 Jan 2021 00:00:00 GMT');
@@ -247,6 +252,16 @@ describe('SuperHeaders', () => {
247252
assert.equal(headers.get('If-Unmodified-Since'), 'Fri, 01 Jan 2021 00:00:00 GMT');
248253
});
249254

255+
it('handles the lastModified property', () => {
256+
let headers = new SuperHeaders({ lastModified: new Date('2021-01-01T00:00:00Z') });
257+
assert.equal(headers.get('Last-Modified'), 'Fri, 01 Jan 2021 00:00:00 GMT');
258+
});
259+
260+
it('handles the location property', () => {
261+
let headers = new SuperHeaders({ location: 'https://example.com' });
262+
assert.equal(headers.get('Location'), 'https://example.com');
263+
});
264+
250265
it('handles the referer property', () => {
251266
let headers = new SuperHeaders({ referer: 'https://example.com' });
252267
assert.equal(headers.get('Referer'), 'https://example.com');
@@ -413,6 +428,36 @@ describe('SuperHeaders', () => {
413428
assert.equal(headers.contentDisposition.toString(), '');
414429
});
415430

431+
it('supports the contentEncoding property', () => {
432+
let headers = new SuperHeaders();
433+
434+
assert.equal(headers.contentEncoding, null);
435+
436+
headers.contentEncoding = 'gzip';
437+
assert.equal(headers.contentEncoding, 'gzip');
438+
439+
headers.contentEncoding = ['deflate', 'gzip'];
440+
assert.equal(headers.contentEncoding, 'deflate, gzip');
441+
442+
headers.contentEncoding = null;
443+
assert.equal(headers.contentEncoding, null);
444+
});
445+
446+
it('supports the contentLanguage property', () => {
447+
let headers = new SuperHeaders();
448+
449+
assert.equal(headers.contentLanguage, null);
450+
451+
headers.contentLanguage = 'en-US';
452+
assert.equal(headers.contentLanguage, 'en-US');
453+
454+
headers.contentLanguage = ['en', 'fr'];
455+
assert.equal(headers.contentLanguage, 'en, fr');
456+
457+
headers.contentLanguage = null;
458+
assert.equal(headers.contentLanguage, null);
459+
});
460+
416461
it('supports the contentLength property', () => {
417462
let headers = new SuperHeaders();
418463

@@ -506,19 +551,6 @@ describe('SuperHeaders', () => {
506551
assert.equal(headers.host, null);
507552
});
508553

509-
it('supports the lastModified property', () => {
510-
let headers = new SuperHeaders();
511-
512-
assert.equal(headers.lastModified, null);
513-
514-
headers.lastModified = new Date('2021-01-01T00:00:00Z');
515-
assert.ok(headers.lastModified instanceof Date);
516-
assert.equal(headers.lastModified.toUTCString(), 'Fri, 01 Jan 2021 00:00:00 GMT');
517-
518-
headers.lastModified = null;
519-
assert.equal(headers.lastModified, null);
520-
});
521-
522554
it('supports the ifModifiedSince property', () => {
523555
let headers = new SuperHeaders();
524556

@@ -545,6 +577,31 @@ describe('SuperHeaders', () => {
545577
assert.equal(headers.ifUnmodifiedSince, null);
546578
});
547579

580+
it('supports the lastModified property', () => {
581+
let headers = new SuperHeaders();
582+
583+
assert.equal(headers.lastModified, null);
584+
585+
headers.lastModified = new Date('2021-01-01T00:00:00Z');
586+
assert.ok(headers.lastModified instanceof Date);
587+
assert.equal(headers.lastModified.toUTCString(), 'Fri, 01 Jan 2021 00:00:00 GMT');
588+
589+
headers.lastModified = null;
590+
assert.equal(headers.lastModified, null);
591+
});
592+
593+
it('supports the location property', () => {
594+
let headers = new SuperHeaders();
595+
596+
assert.equal(headers.location, null);
597+
598+
headers.location = 'https://example.com';
599+
assert.equal(headers.location, 'https://example.com');
600+
601+
headers.location = null;
602+
assert.equal(headers.location, null);
603+
});
604+
548605
it('supports the referer property', () => {
549606
let headers = new SuperHeaders();
550607

packages/headers/src/lib/super-headers.ts

+63
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,14 @@ interface SuperHeadersPropertyInit {
4848
* The [`Content-Disposition`](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Content-Disposition) header value.
4949
*/
5050
contentDisposition?: string | ContentDispositionInit;
51+
/**
52+
* The [`Content-Encoding`](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Content-Encoding) header value.
53+
*/
54+
contentEncoding?: string | string[];
55+
/**
56+
* The [`Content-Language`](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Content-Language) header value.
57+
*/
58+
contentLanguage?: string | string[];
5159
/**
5260
* The [`Content-Length`](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Content-Length) header value.
5361
*/
@@ -84,6 +92,10 @@ interface SuperHeadersPropertyInit {
8492
* The [`Last-Modified`](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Last-Modified) header value.
8593
*/
8694
lastModified?: string | DateInit;
95+
/**
96+
* The [`Location`](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Location) header value.
97+
*/
98+
location?: string;
8799
/**
88100
* The [`Referer`](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Referer) header value.
89101
*/
@@ -434,6 +446,42 @@ export class SuperHeaders extends Headers {
434446
this.#setHeaderValue('content-disposition', ContentDisposition, value);
435447
}
436448

449+
/**
450+
* The `Content-Encoding` header specifies the encoding of the resource.
451+
*
452+
* Note: If multiple encodings have been used, this value may be a comma-separated list. However, most often this
453+
* header will only contain a single value.
454+
*
455+
* [MDN `Content-Encoding` Reference](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Content-Encoding)
456+
*
457+
* [HTTP/1.1 Specification](https://httpwg.org/specs/rfc9110.html#field.content-encoding)
458+
*/
459+
get contentEncoding(): string | null {
460+
return this.get('content-encoding');
461+
}
462+
463+
set contentEncoding(value: string | string[] | undefined | null) {
464+
this.#setValue('content-encoding', Array.isArray(value) ? value.join(', ') : value);
465+
}
466+
467+
/**
468+
* The `Content-Language` header describes the natural language(s) of the intended audience for the response content.
469+
*
470+
* Note: If the response content is intended for multiple audiences, this value may be a comma-separated list. However,
471+
* most often this header will only contain a single value.
472+
*
473+
* [MDN `Content-Language` Reference](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Content-Language)
474+
*
475+
* [HTTP/1.1 Specification](https://httpwg.org/specs/rfc9110.html#field.content-language)
476+
*/
477+
get contentLanguage(): string | null {
478+
return this.get('content-language');
479+
}
480+
481+
set contentLanguage(value: string | string[] | undefined | null) {
482+
this.#setValue('content-language', Array.isArray(value) ? value.join(', ') : value);
483+
}
484+
437485
/**
438486
* The `Content-Length` header indicates the size of the entity-body in bytes.
439487
*
@@ -572,6 +620,21 @@ export class SuperHeaders extends Headers {
572620
this.#setDateValue('last-modified', value);
573621
}
574622

623+
/**
624+
* The `Location` header indicates the URL to redirect to.
625+
*
626+
* [MDN `Location` Reference](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Location)
627+
*
628+
* [HTTP/1.1 Specification](https://datatracker.ietf.org/doc/html/rfc7231#section-7.1.2)
629+
*/
630+
get location(): string | null {
631+
return this.get('location');
632+
}
633+
634+
set location(value: string | undefined | null) {
635+
this.#setValue('location', value);
636+
}
637+
575638
/**
576639
* The `Referer` header contains the address of the previous web page from which a link to the
577640
* currently requested page was followed.

0 commit comments

Comments
 (0)