|
| 1 | +import logger from '../../../common/logger'; |
| 2 | +import { |
| 3 | + MessageDescriptor, |
| 4 | + MessageFromProviderWithMetadata, |
| 5 | + MessageProvider, |
| 6 | +} from '../../message'; |
| 7 | +import express from 'express'; |
| 8 | +import bodyParser from 'body-parser'; |
| 9 | +import { encode as encodeBase64 } from 'js-base64'; |
| 10 | +import { ProxyOptions } from './types'; |
| 11 | + |
| 12 | +// Find a provider message handler, and invoke it |
| 13 | +export const findMessageHandler = ( |
| 14 | + message: MessageDescriptor, |
| 15 | + config: ProxyOptions |
| 16 | +): Promise<MessageProvider> => { |
| 17 | + const handler = config.messageProviders |
| 18 | + ? config.messageProviders[message.description] |
| 19 | + : undefined; |
| 20 | + |
| 21 | + if (!handler) { |
| 22 | + logger.error(`no handler found for message ${message.description}`); |
| 23 | + |
| 24 | + return Promise.reject( |
| 25 | + new Error( |
| 26 | + `No handler found for message "${message.description}". |
| 27 | + Check your "handlers" configuration` |
| 28 | + ) |
| 29 | + ); |
| 30 | + } |
| 31 | + |
| 32 | + return Promise.resolve(handler); |
| 33 | +}; |
| 34 | + |
| 35 | +// Get the Express app that will run on the HTTP Proxy |
| 36 | +export const setupMessageProxyApplication = ( |
| 37 | + config: ProxyOptions |
| 38 | +): express.Express => { |
| 39 | + const app = express(); |
| 40 | + |
| 41 | + app.use(bodyParser.json()); |
| 42 | + app.use(bodyParser.urlencoded({ extended: true })); |
| 43 | + app.use((_, res, next) => { |
| 44 | + // TODO: this seems to override the metadata for content-type |
| 45 | + res.header('Content-Type', 'application/json; charset=utf-8'); |
| 46 | + next(); |
| 47 | + }); |
| 48 | + |
| 49 | + // Proxy server will respond to Verifier process |
| 50 | + app.all('/*', createProxyMessageHandler(config)); |
| 51 | + |
| 52 | + return app; |
| 53 | +}; |
| 54 | + |
| 55 | +// Get the API handler for the verification CLI process to invoke on POST /* |
| 56 | +export const createProxyMessageHandler = ( |
| 57 | + config: ProxyOptions |
| 58 | +): ((req: express.Request, res: express.Response) => void) => { |
| 59 | + return (req, res) => { |
| 60 | + const message: MessageDescriptor = req.body; |
| 61 | + |
| 62 | + // Invoke the handler, and return the JSON response body |
| 63 | + // wrapped in a Message |
| 64 | + findMessageHandler(message, config) |
| 65 | + .then((handler) => handler(message)) |
| 66 | + .then((messageFromHandler) => { |
| 67 | + if (hasMetadata(messageFromHandler)) { |
| 68 | + const metadata = encodeBase64( |
| 69 | + JSON.stringify(messageFromHandler.__pactMessageMetadata) |
| 70 | + ); |
| 71 | + res.header('Pact-Message-Metadata', metadata); |
| 72 | + res.header('PACT_MESSAGE_METADATA', metadata); |
| 73 | + |
| 74 | + return res.json(messageFromHandler.message); |
| 75 | + } |
| 76 | + return res.json(messageFromHandler); |
| 77 | + }) |
| 78 | + .catch((e) => res.status(500).send(e)); |
| 79 | + }; |
| 80 | +}; |
| 81 | + |
| 82 | +// // Get the Proxy we'll pass to the CLI for verification |
| 83 | +// export const setupProxyServer = ( |
| 84 | +// app: (request: http.IncomingMessage, response: http.ServerResponse) => void |
| 85 | +// ): http.Server => http.createServer(app).listen(); |
| 86 | + |
| 87 | +const hasMetadata = ( |
| 88 | + o: unknown | MessageFromProviderWithMetadata |
| 89 | +): o is MessageFromProviderWithMetadata => |
| 90 | + Boolean((o as MessageFromProviderWithMetadata).__pactMessageMetadata); |
| 91 | + |
| 92 | +export const providerWithMetadata = |
| 93 | + ( |
| 94 | + provider: MessageProvider, |
| 95 | + metadata: Record<string, string> |
| 96 | + ): MessageProvider => |
| 97 | + (descriptor: MessageDescriptor) => |
| 98 | + Promise.resolve(provider(descriptor)).then((message) => |
| 99 | + hasMetadata(message) |
| 100 | + ? { |
| 101 | + __pactMessageMetadata: { |
| 102 | + ...message.__pactMessageMetadata, |
| 103 | + ...metadata, |
| 104 | + }, |
| 105 | + message, |
| 106 | + } |
| 107 | + : { __pactMessageMetadata: metadata, message } |
| 108 | + ); |
0 commit comments