Skip to content

Commit 186a900

Browse files
github1github1
authored andcommitted
pass http headers in subject message header
1 parent dbd015d commit 186a900

File tree

4 files changed

+97
-90
lines changed

4 files changed

+97
-90
lines changed
Lines changed: 59 additions & 59 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
// tslint:disable:no-any
2+
13
import {
24
mesh,
35
Mesh,
@@ -29,37 +31,56 @@ describe('http-support', () => {
2931
it('can send messages over http', async () => {
3032
await p1.subject('test-sub-2')
3133
// tslint:disable-next-line:no-any
32-
.on('test-http', (msg : any) => {
33-
return {echo: msg};
34+
.on('test-http', (msg : any, header : SubjectMessageHeader) => {
35+
return {
36+
echo: {
37+
msg,
38+
header
39+
}
40+
};
3441
})
3542
.awaitRegistration();
36-
const res : Response = await fetch(`http://localhost:${port}/api/test-sub-2/123`,
37-
{
38-
headers: {
39-
'content-type': 'application/json'
40-
},
41-
method: 'post',
42-
body: JSON.stringify({name: 'test-http'})
43-
});
43+
const res : Response = await sendHttp(`${port}/api/test-sub-2/123`, {name: 'test-http'});
44+
expect(res.status)
45+
.toBe(200);
4446
const resJson = await res.json();
45-
expect(resJson.echo.name)
47+
expect(resJson.echo.msg.name)
48+
.toBe('test-http');
49+
expect(resJson.echo.header.http.headers['content-type'])
50+
.toBe('application/json');
51+
const resDirect : any = await p1.subject('test-sub-2')
52+
.send({name:'test-http'});
53+
expect(resDirect.echo.msg.name)
4654
.toBe('test-http');
4755
});
56+
it('can set the http response status in the handler', async () => {
57+
await p1.subject('test-sub-2')
58+
// tslint:disable-next-line:no-any
59+
.on('test-http', () => {
60+
return {
61+
http: {
62+
status: 202,
63+
headers: {
64+
'x-something': 'foo'
65+
}
66+
}
67+
};
68+
})
69+
.awaitRegistration();
70+
const res : Response = await sendHttp(`${port}/api/test-sub-2/123`, {name: 'test-http'});
71+
expect(res.status)
72+
.toBe(202);
73+
expect(res.headers.get('x-something'))
74+
.toBe('foo');
75+
});
4876
it('returns status 404 if there are no handlers', async () => {
4977
await p1.subject('test-sub-2')
5078
// tslint:disable-next-line:no-any
5179
.on('test-http', (msg : any) => {
5280
return {echo: msg};
5381
})
5482
.awaitRegistration();
55-
let res : Response = await fetch(`http://localhost:${port}/api/no-sub/123`,
56-
{
57-
headers: {
58-
'content-type': 'application/json'
59-
},
60-
method: 'post',
61-
body: JSON.stringify({name: 'test-http'})
62-
});
83+
let res : Response = await sendHttp(`${port}/api/no-sub/123`, {name: 'test-http'});
6384
expect(res.status)
6485
.toBe(404);
6586
res = await fetch(`http://localhost:${port}/api/broadcast/no-sub`,
@@ -80,14 +101,7 @@ describe('http-support', () => {
80101
return {echo: msg};
81102
})
82103
.awaitRegistration();
83-
const res : Response = await fetch(`http://localhost:${port}/api/test-sub-2/123?messageName=test-http`,
84-
{
85-
headers: {
86-
'content-type': 'application/json'
87-
},
88-
method: 'post',
89-
body: '{}'
90-
});
104+
const res : Response = await sendHttp(`${port}/api/test-sub-2/123?messageName=test-http`, {});
91105
const resJson = await res.json();
92106
expect(resJson.echo.name)
93107
.toBe('test-http');
@@ -99,14 +113,7 @@ describe('http-support', () => {
99113
return {echo: msg};
100114
})
101115
.awaitRegistration();
102-
const res : Response = await fetch(`http://localhost:${port}/api/broadcast/test-sub-2?messageName=test-http`,
103-
{
104-
headers: {
105-
'content-type': 'application/json'
106-
},
107-
method: 'post',
108-
body: '{}'
109-
});
116+
const res : Response = await sendHttp(`${port}/api/broadcast/test-sub-2?messageName=test-http`, {});
110117
const resJson = await res.json();
111118
expect(resJson.length)
112119
.toBe(1);
@@ -120,14 +127,7 @@ describe('http-support', () => {
120127
return {echo: msg};
121128
})
122129
.awaitRegistration();
123-
const res : Response = await fetch(`http://localhost:${port}/api/broadcast/test-sub-2?messageName=test-http&wait=false`,
124-
{
125-
headers: {
126-
'content-type': 'application/json'
127-
},
128-
method: 'post',
129-
body: '{}'
130-
});
130+
const res : Response = await sendHttp(`${port}/api/broadcast/test-sub-2?messageName=test-http&wait=false`, {});
131131
const resJson = await res.json();
132132
expect(resJson.length)
133133
.toBe(0);
@@ -141,14 +141,10 @@ describe('http-support', () => {
141141
return {name: header.name, pk: header.partitionKey};
142142
})
143143
.awaitRegistration();
144-
const res : Response = await fetch(`http://localhost:${port}/api/test-sub-2/{body.key}-123?messageName={body.something}`,
145-
{
146-
headers: {
147-
'content-type': 'application/json'
148-
},
149-
method: 'post',
150-
body: JSON.stringify({key: 'abc', something: 'some-val'})
151-
});
144+
const res : Response = await sendHttp(`${port}/api/test-sub-2/{body.key}-123?messageName={body.something}`, {
145+
key: 'abc',
146+
something: 'some-val'
147+
});
152148
const resJson = await res.json();
153149
expect(resJson.name)
154150
.toBe('some-val');
@@ -162,15 +158,19 @@ describe('http-support', () => {
162158
return {echo: msg};
163159
})
164160
.awaitRegistration();
165-
const res : Response = await fetch(`http://localhost:${port}/api/test-sub-2/123`,
166-
{
167-
headers: {
168-
'content-type': 'application/json'
169-
},
170-
method: 'post',
171-
body: '{}'
172-
});
161+
const res : Response = await sendHttp(`${port}/api/test-sub-2/123`, {});
173162
expect(res.status)
174163
.toBe(400);
175164
});
176165
});
166+
167+
function sendHttp(path : string, body : any) {
168+
return fetch(`http://localhost:${path}`,
169+
{
170+
headers: {
171+
'content-type': 'application/json'
172+
},
173+
method: 'post',
174+
body: JSON.stringify(body)
175+
});
176+
}

src/backends/http/http-support.ts

Lines changed: 24 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,11 @@
11
import {
2-
HttpMessage,
2+
HttpMessageHeader,
33
MeshBackend,
44
MeshBackendBase,
55
MeshBackendProvider,
66
MeshBackendProvision,
77
MeshVoidResponse,
8+
SubjectMessage,
89
SubjectMessageEnvelope,
910
SubjectMessageOptions,
1011
toMeshBackendProvision
@@ -19,6 +20,11 @@ import * as normalizeUrl from 'normalize-url';
1920
const log : debug.Debugger = debug('meshage')
2021
.extend('http');
2122

23+
interface PreparedHttpMessage {
24+
message: SubjectMessage;
25+
headerData: HttpMessageHeader;
26+
}
27+
2228
class HttpMeshBackend extends MeshBackendBase {
2329

2430
private app : express.Express;
@@ -43,7 +49,7 @@ class HttpMeshBackend extends MeshBackendBase {
4349
}, {});
4450
}
4551

46-
private static prepareHttpMessage<T>(req : express.Request) : HttpMessage<T> {
52+
private static prepareHttpMessage<T>(req : express.Request) : PreparedHttpMessage {
4753
// tslint:disable-next-line:no-any
4854
let reqUrl : string;
4955
if (process.env.PUBLIC_URL) {
@@ -65,9 +71,8 @@ class HttpMeshBackend extends MeshBackendBase {
6571
// tslint:disable-next-line:no-unsafe-any
6672
const messageName : string = query.messageName ? `${query.messageName}` : req.body.name;
6773
return {
68-
name: messageName,
69-
payload: {...req.body},
70-
http: {
74+
message: {...req.body, name: messageName},
75+
headerData: {
7176
headers: req.headers,
7277
url: req.url,
7378
publicUrl: reqUrl,
@@ -90,7 +95,7 @@ class HttpMeshBackend extends MeshBackendBase {
9095
status = resultToSend.http.status;
9196
}
9297
// tslint:disable-next-line:no-unsafe-any
93-
if (resultToSend.http.header) {
98+
if (resultToSend.http.headers) {
9499
// tslint:disable-next-line:no-unsafe-any
95100
res.set(resultToSend.http.headers);
96101
}
@@ -156,17 +161,18 @@ class HttpMeshBackend extends MeshBackendBase {
156161
this.app.post('/api/broadcast/:subject',
157162
async (req : express.Request, res : express.Response) => {
158163
try {
159-
const httpMessage = HttpMeshBackend.prepareHttpMessage(req);
160-
if (!httpMessage.name) {
164+
const httpMessage : PreparedHttpMessage = HttpMeshBackend.prepareHttpMessage(req);
165+
if (!httpMessage.message.name) {
161166
res.status(400)
162167
.send({error: 'Missing message name'});
163168
} else {
164-
const result = await this.send(httpMessage.http.params.subject,
169+
const result = await this.send(httpMessage.headerData.params.subject,
165170
undefined,
166-
httpMessage,
171+
httpMessage.message,
167172
{
168173
wait: req.query.wait === 'true' || req.query.wait === undefined,
169-
timeout: req.query.timeout === undefined ? undefined : parseInt(`${req.query.timeout}`, 10)
174+
timeout: req.query.timeout === undefined ? undefined : parseInt(`${req.query.timeout}`, 10),
175+
additionalHeaderData: {http: httpMessage.headerData}
170176
}, true);
171177
HttpMeshBackend.prepareHttpResponse(result, res);
172178
}
@@ -178,19 +184,20 @@ class HttpMeshBackend extends MeshBackendBase {
178184
this.app.post('/api/:subject/:partitionKey?',
179185
async (req : express.Request, res : express.Response) => {
180186
try {
181-
const httpMessage = HttpMeshBackend.prepareHttpMessage(req);
182-
if (!httpMessage.name) {
187+
const httpMessage : PreparedHttpMessage = HttpMeshBackend.prepareHttpMessage(req);
188+
if (!httpMessage.message.name) {
183189
res.status(400)
184190
.send({error: 'Missing message name'});
185191
} else {
186192
const result = await this.send(
187-
httpMessage.http.params.subject,
188-
httpMessage.http.params.partitionKey,
189-
httpMessage,
193+
httpMessage.headerData.params.subject,
194+
httpMessage.headerData.params.partitionKey,
195+
httpMessage.message,
190196
{
191197
wait: req.query.wait === 'true' || req.query.wait === undefined,
192198
timeout: req.query.timeout === undefined ? undefined : parseInt(`${req.query.timeout}`, 10),
193-
keepSignals: true
199+
keepSignals: true,
200+
additionalHeaderData: {http: httpMessage.headerData}
194201
},
195202
false);
196203
HttpMeshBackend.prepareHttpResponse(result, res);

src/mesh.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -329,7 +329,10 @@ export abstract class MeshBackendBase implements MeshBackend {
329329
message : SubjectMessage,
330330
options : SubjectMessageOptions,
331331
broadcast : boolean) : Promise<T> {
332+
// tslint:disable-next-line:no-parameter-reassignment
333+
options = options || {};
332334
const messageHeader : SubjectMessageHeader = {
335+
...options.additionalHeaderData,
333336
uid: v4(),
334337
subject,
335338
// tslint:disable-next-line:no-unsafe-any

src/messages.ts

Lines changed: 11 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,14 @@
11
// tslint:disable-next-line:no-any
22
export type ConstructorOf<T> = new (...args: any[]) => T;
33

4+
export interface HttpMessageHeader {
5+
headers : { [key : string] : string | string[] | undefined };
6+
url : string;
7+
publicUrl : string;
8+
params : { [key : string] : string };
9+
query : { [key : string] : string };
10+
}
11+
412
// tslint:disable-next-line:no-any
513
export interface SubjectMessage {
614
// tslint:disable-next-line:no-any
@@ -11,13 +19,16 @@ export interface SubjectMessageOptions {
1119
timeout?: number;
1220
wait?: boolean;
1321
keepSignals?: boolean;
22+
// tslint:disable-next-line:no-any
23+
additionalHeaderData?: any;
1424
}
1525

1626
export interface SubjectMessageHeader {
1727
uid: string;
1828
subject: string;
1929
name: string;
2030
partitionKey?: string;
31+
http?: HttpMessageHeader;
2132
}
2233

2334
export interface SubjectMessageEnvelope {
@@ -27,17 +38,3 @@ export interface SubjectMessageEnvelope {
2738

2839
// tslint:disable-next-line:no-any
2940
export type SubjectMessageHandler<T> = (data? : T, header? : SubjectMessageHeader) => any;
30-
31-
export interface HttpMessageHeader {
32-
headers : { [key : string] : string | string[] | undefined };
33-
url : string;
34-
publicUrl : string;
35-
params : { [key : string] : string };
36-
query : { [key : string] : string };
37-
}
38-
39-
export interface HttpMessage<T> {
40-
name : string;
41-
payload : T;
42-
http : HttpMessageHeader;
43-
}

0 commit comments

Comments
 (0)