Skip to content

Commit e582e54

Browse files
ihexxajackkav
andcommitted
feat: enable headers in pre-request scripting [INS-3379] (Kong#7121)
* chore: enable Headers in pre-request scripting * Update packages/insomnia/src/sdk/objects/__tests__/headers.test.ts --------- Co-authored-by: Jack Kavanagh <jackkav@gmail.com>
1 parent fa204d4 commit e582e54

4 files changed

Lines changed: 149 additions & 2 deletions

File tree

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
import { describe, expect, it } from '@jest/globals';
2+
3+
import { Header } from '../headers';
4+
5+
describe('test Header object', () => {
6+
it('test basic operations', () => {
7+
const headerStr = 'Content-Type: application/json\nUser-Agent: MyClientLibrary/2.0\n';
8+
const headerObjs = [
9+
{ key: 'Content-Type', value: 'application/json' },
10+
{ key: 'User-Agent', value: 'MyClientLibrary/2.0' },
11+
];
12+
13+
expect(Header.parse(headerStr)).toEqual(headerObjs);
14+
expect(
15+
Header.parse(Header.unparse(headerObjs))
16+
).toEqual(headerObjs);
17+
});
18+
});
Lines changed: 128 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,128 @@
1+
import { unsupportedError } from './insomnia';
2+
import { Property, PropertyList } from './properties';
3+
4+
export interface HeaderDefinition {
5+
key: string;
6+
value: string;
7+
id?: string;
8+
name?: string;
9+
type?: string;
10+
disabled?: boolean;
11+
}
12+
13+
export class Header extends Property {
14+
_kind: string = 'Header';
15+
type: string = '';
16+
key: string;
17+
value: string;
18+
19+
constructor(
20+
opts: HeaderDefinition | string,
21+
name?: string, // if it is defined, it overrides 'key' (not 'name')
22+
) {
23+
super();
24+
25+
if (typeof opts === 'string') {
26+
const obj = Header.parseSingle(opts);
27+
this.key = obj.key;
28+
this.value = obj.value;
29+
} else {
30+
this.id = opts.id ? opts.id : '';
31+
this.key = opts.key ? opts.key : '';
32+
this.name = name ? name : (opts.name ? opts.name : '');
33+
this.value = opts.value ? opts.value : '';
34+
this.type = opts.type ? opts.type : '';
35+
this.disabled = opts ? opts.disabled : false;
36+
}
37+
}
38+
39+
static create(input?: { key: string; value: string } | string, name?: string): Header {
40+
return new Header(input || { key: '', value: '' }, name);
41+
}
42+
43+
static isHeader(obj: object) {
44+
return '_kind' in obj && obj._kind === 'Header';
45+
}
46+
47+
// example: 'Content-Type: application/json\nUser-Agent: MyClientLibrary/2.0\n'
48+
static parse(headerString: string): { key: string; value: string }[] {
49+
return headerString
50+
.split('\n')
51+
.filter(kvPart => kvPart.trim() !== '')
52+
.map(kvPart => Header.parseSingle(kvPart));
53+
}
54+
55+
static parseSingle(headerStr: string): { key: string; value: string } {
56+
// https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers
57+
// the first colon is the separator
58+
const separatorPos = headerStr.indexOf(':');
59+
60+
if (separatorPos <= 0) {
61+
throw Error('Header.parseSingle: the header string seems invalid');
62+
}
63+
64+
const key = headerStr.slice(0, separatorPos);
65+
const value = headerStr.slice(separatorPos + 1);
66+
67+
return { key: key.trim(), value: value.trim() };
68+
}
69+
70+
static unparse(headers: { key: string; value: string }[] | PropertyList<Header>, separator?: string): string {
71+
const headerArray: { key: string; value: string }[] = [
72+
...headers.map(
73+
header => this.unparseSingle(header), {}
74+
),
75+
];
76+
77+
return headerArray.join(separator || '\n');
78+
}
79+
80+
static unparseSingle(header: { key: string; value: string } | Header): string {
81+
// both PropertyList and object contains 'key' and 'value'
82+
return `${header.key}: ${header.value}`;
83+
}
84+
85+
update(newHeader: { key: string; value: string }) {
86+
this.key = newHeader.key;
87+
this.value = newHeader.value;
88+
}
89+
90+
valueOf() {
91+
return this.value;
92+
}
93+
}
94+
95+
export class HeaderList<T extends Header> extends PropertyList<T> {
96+
constructor(
97+
parent: PropertyList<T> | undefined,
98+
populate: T[]
99+
) {
100+
super(
101+
Header,
102+
undefined,
103+
populate
104+
);
105+
this.parent = parent;
106+
}
107+
108+
static isHeaderList(obj: any) {
109+
return '_kind' in obj && obj._kind === 'HeaderList';
110+
}
111+
112+
// eslint-disable-next-line @typescript-eslint/no-unused-vars
113+
eachParent(_iterator: any, _context?: object | undefined) {
114+
throw unsupportedError('eachParent');
115+
}
116+
117+
// eslint-disable-next-line @typescript-eslint/no-unused-vars
118+
toObject(_excludeDisabled?: boolean, _caseSensitive?: boolean, _multiValue?: boolean, _sanitizeKeys?: boolean) {
119+
throw unsupportedError('toObject');
120+
}
121+
122+
contentSize(): number {
123+
return this.list
124+
.map(header => header.toString())
125+
.map(headerStr => headerStr.length) // TODO: handle special characters
126+
.reduce((totalSize, headerSize) => totalSize + headerSize, 0);
127+
}
128+
}
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1 +1,2 @@
11
export { PropertyBase, Property, PropertyList } from './properties';
2+
export { Header, HeaderList } from './headers';

packages/insomnia/src/sdk/objects/properties.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -184,8 +184,8 @@ export class PropertyList<T extends Property> {
184184
protected list: T[] = [];
185185

186186
constructor(
187-
protected readonly _typeClass: {}, // TODO: it is not used before collection is introduced
188-
protected readonly parent: Property | PropertyList<any> | undefined,
187+
protected _typeClass: {}, // TODO: it is not used before collection is introduced
188+
protected parent: Property | PropertyList<any> | undefined,
189189
populate: T[],
190190
) {
191191
this.parent = parent;

0 commit comments

Comments
 (0)