1 |
|
2 |
|
3 |
|
4 | 'use strict';
|
5 |
|
6 | const Base = require('../base/Component');
|
7 |
|
8 | module.exports = class Forwarder extends Base {
|
9 |
|
10 | constructor (config) {
|
11 | super({
|
12 | items: {},
|
13 | Url: require('./Url'),
|
14 | ...config
|
15 | });
|
16 | this.clear();
|
17 | }
|
18 |
|
19 | init () {
|
20 | this.createItems();
|
21 | if (!this.isEmpty()) {
|
22 | this.module.addHandler('use', this.forward.bind(this));
|
23 | }
|
24 | }
|
25 |
|
26 | isEmpty () {
|
27 | return this._urls.length === 0;
|
28 | }
|
29 |
|
30 | createItems () {
|
31 | this._urls = [];
|
32 | for (const source of Object.keys(this.items)) {
|
33 | let data = this.items[source];
|
34 | data = data instanceof Object ? data : {target: data};
|
35 | data.source = source;
|
36 | this._urls.push(ClassHelper.spawn(this.Url, data));
|
37 | this.log('trace', `forward ${data.source} to ${data.target}`);
|
38 | }
|
39 | }
|
40 |
|
41 | forward (req, res, next) {
|
42 | const data = this.resolvePath(req.path, req.method);
|
43 | if (!data) {
|
44 | return next();
|
45 | }
|
46 | this.log('trace', `forward ${req.path} to ${data.path}`, data.params);
|
47 | Object.assign(req.query, data.params);
|
48 | req.url = data.path;
|
49 | next();
|
50 | }
|
51 |
|
52 | resolve (url) {
|
53 | let newUrl = this.get(url);
|
54 | if (newUrl) {
|
55 | return newUrl;
|
56 | }
|
57 | newUrl = this.createSourceUrl(UrlHelper.parse(url));
|
58 | if (!newUrl && this.module.parent) {
|
59 | newUrl = this.module.parent.resolveUrl(url);
|
60 | }
|
61 | this.set(url, newUrl);
|
62 | return newUrl;
|
63 | }
|
64 |
|
65 | resolvePath (path, method) {
|
66 | for (const url of this._urls) {
|
67 | const data = url.resolve(path, method);
|
68 | if (data) {
|
69 | return data;
|
70 | }
|
71 | }
|
72 | return null;
|
73 | }
|
74 |
|
75 | createSourceUrl (data) {
|
76 | const index = data.segments.indexOf(this.module.NAME) + 1;
|
77 | data.path = index > 0
|
78 | ? `/${data.segments.slice(index).join('/')}`
|
79 | : `/${data.segments.join('/')}`;
|
80 | for (let url of this._urls) {
|
81 | url = url.createSourceUrl(data);
|
82 | if (url) {
|
83 | return index > 0 ? `/${data.segments.slice(0, index).join('/')}${url}` : url;
|
84 | }
|
85 | }
|
86 | return null;
|
87 | }
|
88 |
|
89 |
|
90 |
|
91 | get (key) {
|
92 | return Object.prototype.hasOwnProperty.call(this._cache, key) ? this._cache[key] : null;
|
93 | }
|
94 |
|
95 | set (key, value) {
|
96 | this._cache[key] = value;
|
97 | }
|
98 |
|
99 | clear () {
|
100 | this._cache = {};
|
101 | }
|
102 | };
|
103 |
|
104 | const ClassHelper = require('../helper/ClassHelper');
|
105 | const UrlHelper = require('../helper/UrlHelper'); |
\ | No newline at end of file |