-
Notifications
You must be signed in to change notification settings - Fork 124
/
Middleware.test.ts
146 lines (127 loc) · 6.01 KB
/
Middleware.test.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
import type { Server } from 'http';
import request from 'supertest';
import type { BaseHttpServerFactory } from '../../src/server/BaseHttpServerFactory';
import type { HttpHandlerInput } from '../../src/server/HttpHandler';
import { HttpHandler } from '../../src/server/HttpHandler';
import { getPort } from '../util/Util';
import { getTestConfigPath, instantiateFromConfig } from './Config';
const port = getPort('Middleware');
class SimpleHttpHandler extends HttpHandler {
public async handle(input: HttpHandlerInput): Promise<void> {
input.response.writeHead(200, { location: '/' });
input.response.end('Hello World');
}
}
describe('An http server with middleware', (): void => {
let server: Server;
beforeAll(async(): Promise<void> => {
const factory = await instantiateFromConfig(
'urn:solid-server:default:HttpServerFactory',
getTestConfigPath('server-middleware.json'),
{
'urn:solid-server:default:LdpHandler': new SimpleHttpHandler(),
'urn:solid-server:default:variable:baseUrl': 'https://example.pod/',
'urn:solid-server:default:variable:showStackTrace': true,
},
) as BaseHttpServerFactory;
server = factory.startServer(port);
});
afterAll(async(): Promise<void> => {
server.close();
});
it('sets a Vary header containing Accept.', async(): Promise<void> => {
const res = await request(server).get('/');
expect(res.header).toEqual(expect.objectContaining({
vary: expect.stringMatching(/(^|,)\s*Accept\s*(,|$)/iu),
}));
});
it('sets a Vary header containing Authorization.', async(): Promise<void> => {
const res = await request(server).get('/');
expect(res.header).toEqual(expect.objectContaining({
vary: expect.stringMatching(/(^|,)\s*Authorization\s*(,|$)/iu),
}));
});
it('sets a Vary header containing Origin.', async(): Promise<void> => {
const res = await request(server).get('/');
expect(res.header).toEqual(expect.objectContaining({
vary: expect.stringMatching(/(^|,)\s*Origin\s*(,|$)/iu),
}));
});
it('sends server identification in the X-Powered-By header.', async(): Promise<void> => {
const res = await request(server).get('/');
expect(res.header).toEqual(expect.objectContaining({
'x-powered-by': 'Community Solid Server',
}));
});
it('returns all relevant headers for an OPTIONS request.', async(): Promise<void> => {
const res = await request(server)
.options('/')
.set('Access-Control-Allow-Credentials', 'true')
.set('Access-Control-Request-Headers', 'content-type')
.set('Access-Control-Request-Method', 'POST')
.set('Host', 'test.com')
.expect(200);
expect(res.header).toEqual(expect.objectContaining({
'access-control-allow-origin': '*',
'access-control-allow-headers': 'content-type',
'updates-via': 'wss://example.pod/',
'x-powered-by': 'Community Solid Server',
}));
const { vary } = res.header;
expect(vary).toMatch(/(^|,)\s*Accept\s*(,|$)/iu);
expect(vary).toMatch(/(^|,)\s*Authorization\s*(,|$)/iu);
expect(vary).toMatch(/(^|,)\s*Origin\s*(,|$)/iu);
const corsMethods = res.header['access-control-allow-methods'].split(',')
.map((method: string): string => method.trim());
const allowedMethods = [ 'GET', 'HEAD', 'OPTIONS', 'POST', 'PUT', 'PATCH', 'DELETE' ];
expect(corsMethods).toEqual(expect.arrayContaining(allowedMethods));
expect(corsMethods).toHaveLength(allowedMethods.length);
});
it('specifies CORS origin header if an origin was supplied.', async(): Promise<void> => {
const res = await request(server).get('/').set('origin', 'test.com').expect(200);
expect(res.header).toEqual(expect.objectContaining({ 'access-control-allow-origin': 'test.com' }));
});
it('exposes the Accept-[Method] header via CORS.', async(): Promise<void> => {
const res = await request(server).get('/').expect(200);
const exposed = res.header['access-control-expose-headers'];
expect(exposed.split(/\s*,\s*/u)).toContain('Accept-Patch');
expect(exposed.split(/\s*,\s*/u)).toContain('Accept-Post');
expect(exposed.split(/\s*,\s*/u)).toContain('Accept-Put');
});
it('exposes the Last-Modified and ETag headers via CORS.', async(): Promise<void> => {
const res = await request(server).get('/').expect(200);
const exposed = res.header['access-control-expose-headers'];
expect(exposed.split(/\s*,\s*/u)).toContain('ETag');
expect(exposed.split(/\s*,\s*/u)).toContain('Last-Modified');
});
it('exposes the Link header via CORS.', async(): Promise<void> => {
const res = await request(server).get('/').expect(200);
const exposed = res.header['access-control-expose-headers'];
expect(exposed.split(/\s*,\s*/u)).toContain('Link');
});
it('exposes the Location header via CORS.', async(): Promise<void> => {
const res = await request(server).get('/').expect(200);
const exposed = res.header['access-control-expose-headers'];
expect(exposed.split(/\s*,\s*/u)).toContain('Location');
});
it('exposes the MS-Author-Via header via CORS.', async(): Promise<void> => {
const res = await request(server).get('/').expect(200);
const exposed = res.header['access-control-expose-headers'];
expect(exposed.split(/\s*,\s*/u)).toContain('MS-Author-Via');
});
it('exposes the WAC-Allow header via CORS.', async(): Promise<void> => {
const res = await request(server).get('/').expect(200);
const exposed = res.header['access-control-expose-headers'];
expect(exposed.split(/\s*,\s*/u)).toContain('WAC-Allow');
});
it('exposes the Updates-Via header via CORS.', async(): Promise<void> => {
const res = await request(server).get('/').expect(200);
const exposed = res.header['access-control-expose-headers'];
expect(exposed.split(/\s*,\s*/u)).toContain('Updates-Via');
});
it('sends incoming requests to the handler.', async(): Promise<void> => {
const response = request(server).get('/').set('Host', 'test.com');
expect(response).toBeDefined();
await response.expect(200).expect('Hello World');
});
});