Skip to content

Commit 05beeb1

Browse files
committed
fix(execute): create RFC 6265 compliant Cookie headers
Every Cookie header produced by this library can now be properly parsed by RFC 6265 parser, and resulting cookie-value can be further percent decoded and processed by RFC 6570 implementations
1 parent 7e813a0 commit 05beeb1

File tree

5 files changed

+54
-30
lines changed

5 files changed

+54
-30
lines changed

src/execute/oas3/parameter-builders.js

+30-15
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,9 @@
11
import { resolve as resolvePathTemplate } from 'openapi-path-templating';
2+
import { serializeCookie } from '@swaggerexpert/cookie';
23

34
import stylize, { encodeCharacters } from './style-serializer.js';
45
import serialize from './content-serializer.js';
6+
import cookieValueEncoder from '../../helpers/cookie-value-encoder.js';
57

68
export function path({ req, value, parameter, baseURL }) {
79
const { name, style, explode, content } = parameter;
@@ -29,7 +31,7 @@ export function path({ req, value, parameter, baseURL }) {
2931
key: parameter.name,
3032
value: val,
3133
style: style || 'simple',
32-
explode: explode || false,
34+
explode: explode ?? false,
3335
escape: 'reserved',
3436
}),
3537
}
@@ -106,28 +108,41 @@ export function header({ req, parameter, value }) {
106108
}
107109

108110
export function cookie({ req, parameter, value }) {
111+
const { name: cookieName } = parameter;
112+
109113
req.headers = req.headers || {};
110-
const type = typeof value;
111114

112115
if (value !== undefined && parameter.content) {
113116
const effectiveMediaType = Object.keys(parameter.content)[0];
117+
const cookieValue = serialize(value, effectiveMediaType);
114118

115-
req.headers.Cookie = `${parameter.name}=${serialize(value, effectiveMediaType)}`;
119+
req.headers.Cookie = serializeCookie(
120+
{ [cookieName]: cookieValue },
121+
{
122+
encoders: { value: cookieValueEncoder },
123+
}
124+
);
116125
return;
117126
}
118127

119128
if (value !== undefined && !(Array.isArray(value) && value.length === 0)) {
120-
const prefix =
121-
type === 'object' && !Array.isArray(value) && parameter.explode ? '' : `${parameter.name}=`;
122-
123-
req.headers.Cookie =
124-
prefix +
125-
stylize({
126-
key: parameter.name,
127-
value,
128-
escape: false,
129-
style: parameter.style || 'form',
130-
explode: typeof parameter.explode === 'undefined' ? false : parameter.explode,
131-
});
129+
const serializedValue = stylize({
130+
key: parameter.name,
131+
value,
132+
escape: false,
133+
style: parameter.style || 'form',
134+
explode: parameter.explode ?? false,
135+
});
136+
const cookieValue =
137+
Array.isArray(value) && parameter.explode
138+
? `${cookieName}=${serializedValue}`
139+
: serializedValue;
140+
141+
req.headers.Cookie = serializeCookie(
142+
{ [cookieName]: cookieValue },
143+
{
144+
encoders: { value: cookieValueEncoder },
145+
}
146+
);
132147
}
133148
}

src/helpers/cookie-value-encoder.js

+11
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
import { cookieValueStrictEncoder } from '@swaggerexpert/cookie';
2+
3+
const eqSignPE = '%3D';
4+
const ampersandPE = '%26';
5+
6+
const cookieValueEncoder = (cookieValue) =>
7+
cookieValueStrictEncoder(cookieValue).replace(/[=&]/gu, (match) =>
8+
match === '=' ? eqSignPE : ampersandPE
9+
);
10+
11+
export default cookieValueEncoder;

test/oas3/execute/authorization.js

+1-4
Original file line numberDiff line numberDiff line change
@@ -615,9 +615,6 @@ describe('Authorization - OpenAPI Specification 3.0', () => {
615615
myApiKey: {
616616
value: 'MyToken',
617617
},
618-
myApiKey1: {
619-
value: 'MyToken1',
620-
},
621618
},
622619
},
623620
});
@@ -627,7 +624,7 @@ describe('Authorization - OpenAPI Specification 3.0', () => {
627624
url: '/',
628625
credentials: 'same-origin',
629626
headers: {
630-
Cookie: 'id=1&id=2&id=3; MyApiKeyCookie=MyToken',
627+
Cookie: 'id=id%3D1%26id%3D2%26id%3D3; MyApiKeyCookie=MyToken',
631628
},
632629
});
633630
});

test/oas3/execute/main.js

+5-5
Original file line numberDiff line numberDiff line change
@@ -659,7 +659,7 @@ describe('buildRequest - OpenAPI Specification 3.0', () => {
659659
credentials: 'same-origin',
660660
headers: {
661661
FooHeader: 'a={"b":{"c":{"d":"e"}}}',
662-
Cookie: 'myCookie=foo,{"bar":{"baz":"qux"}}',
662+
Cookie: 'myCookie=foo%2C{%22bar%22:{%22baz%22:%22qux%22}}',
663663
},
664664
});
665665
});
@@ -731,7 +731,7 @@ describe('buildRequest - OpenAPI Specification 3.0', () => {
731731
credentials: 'same-origin',
732732
headers: {
733733
FooHeader: 'c=',
734-
Cookie: 'myCookie=d,',
734+
Cookie: 'myCookie=d%2C',
735735
},
736736
});
737737
});
@@ -856,7 +856,7 @@ describe('buildRequest - OpenAPI Specification 3.0', () => {
856856
credentials: 'same-origin',
857857
headers: {
858858
FooHeader: ',,',
859-
Cookie: 'myCookie=,,',
859+
Cookie: 'myCookie=%2C%2C',
860860
},
861861
});
862862
});
@@ -1063,7 +1063,7 @@ describe('buildRequest - OpenAPI Specification 3.0', () => {
10631063
credentials: 'same-origin',
10641064
headers: {
10651065
FooHeader: '{"foo":"bar"}',
1066-
Cookie: 'myCookie={"flavor":"chocolate chip"}',
1066+
Cookie: 'myCookie={%22flavor%22:%22chocolate%20chip%22}',
10671067
},
10681068
});
10691069
});
@@ -1218,7 +1218,7 @@ describe('buildRequest - OpenAPI Specification 3.0', () => {
12181218
credentials: 'same-origin',
12191219
headers: {
12201220
FooHeader: '[{"foo":"bar"}]',
1221-
Cookie: 'myCookie=[{"flavor":"chocolate chip"}]',
1221+
Cookie: 'myCookie=[{%22flavor%22:%22chocolate%20chip%22}]',
12221222
},
12231223
});
12241224
});

test/oas3/execute/style-explode/cookie.js

+7-6
Original file line numberDiff line numberDiff line change
@@ -137,6 +137,7 @@ describe('OAS 3.0 - buildRequest w/ `style` & `explode` - cookie parameters', ()
137137
{
138138
name: 'id',
139139
in: 'cookie',
140+
explode: false,
140141
},
141142
],
142143
},
@@ -158,7 +159,7 @@ describe('OAS 3.0 - buildRequest w/ `style` & `explode` - cookie parameters', ()
158159
url: '/users',
159160
credentials: 'same-origin',
160161
headers: {
161-
Cookie: 'id=3,4,5',
162+
Cookie: 'id=3%2C4%2C5',
162163
},
163164
});
164165
});
@@ -198,7 +199,7 @@ describe('OAS 3.0 - buildRequest w/ `style` & `explode` - cookie parameters', ()
198199
url: '/users',
199200
credentials: 'same-origin',
200201
headers: {
201-
Cookie: 'id=3,4,5',
202+
Cookie: 'id=3%2C4%2C5',
202203
},
203204
});
204205
});
@@ -238,7 +239,7 @@ describe('OAS 3.0 - buildRequest w/ `style` & `explode` - cookie parameters', ()
238239
url: '/users',
239240
credentials: 'same-origin',
240241
headers: {
241-
Cookie: 'id=3&id=4&id=5',
242+
Cookie: 'id=id%3D3%26id%3D4%26id%3D5',
242243
},
243244
});
244245
});
@@ -282,7 +283,7 @@ describe('OAS 3.0 - buildRequest w/ `style` & `explode` - cookie parameters', ()
282283
url: '/users',
283284
credentials: 'same-origin',
284285
headers: {
285-
Cookie: 'id=role,admin,firstName,Alex',
286+
Cookie: 'id=role%2Cadmin%2CfirstName%2CAlex',
286287
},
287288
});
288289
});
@@ -322,7 +323,7 @@ describe('OAS 3.0 - buildRequest w/ `style` & `explode` - cookie parameters', ()
322323
url: '/users',
323324
credentials: 'same-origin',
324325
headers: {
325-
Cookie: 'id=role,admin,firstName,Alex',
326+
Cookie: 'id=role%2Cadmin%2CfirstName%2CAlex',
326327
},
327328
});
328329
});
@@ -362,7 +363,7 @@ describe('OAS 3.0 - buildRequest w/ `style` & `explode` - cookie parameters', ()
362363
url: '/users',
363364
credentials: 'same-origin',
364365
headers: {
365-
Cookie: 'role=admin&firstName=Alex',
366+
Cookie: 'id=role%3Dadmin%26firstName%3DAlex',
366367
},
367368
});
368369
});

0 commit comments

Comments
 (0)