1 |
|
2 | var debug = require('debug')('plugin:cloud-foundry-route-service');
|
3 | var https = require('https');
|
4 | /*
|
5 | * Copyright 2016 Apigee Corporation
|
6 | *
|
7 | * Licensed under the Apache License, Version 2.0 (the "License");
|
8 | * you may not use this file except in compliance with the License.
|
9 | * You may obtain a copy of the License at
|
10 | *
|
11 | * http://www.apache.org/licenses/LICENSE-2.0
|
12 | *
|
13 | * Unless required by applicable law or agreed to in writing, software
|
14 | * distributed under the License is distributed on an "AS IS" BASIS,
|
15 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
16 | * See the License for the specific language governing permissions and
|
17 | * limitations under the License.
|
18 | */
|
19 |
|
20 | var pathOnly = false;
|
21 |
|
22 | /**
|
23 | * Changes target host/path according to Cloud Foundry "magic header".
|
24 | *
|
25 | * @module
|
26 | */
|
27 |
|
28 | function retarget (req, res, next) {
|
29 | const cfurl = req.headers['x-cf-forwarded-url']
|
30 | if (! cfurl) {
|
31 | next()
|
32 | return
|
33 | }
|
34 |
|
35 | let h = cfurl.indexOf('://')
|
36 | if (h >= 0) {
|
37 | h += 3
|
38 | }
|
39 | else {
|
40 | h = 0
|
41 | }
|
42 |
|
43 | let p = cfurl.indexOf('/', h)
|
44 | if (p < 0) {
|
45 | p = cfurl.length
|
46 | }
|
47 |
|
48 | const cfHostname = cfurl.slice(h, p)
|
49 | const cfPath = cfurl.slice(p) || '/'
|
50 |
|
51 | debug('x-cf-forwarded-url: ' + cfurl);
|
52 | debug('old targetHostname: '+req.targetHostname);
|
53 | debug('old targetPath: ' + req.targetPath);
|
54 |
|
55 | if (cfHostname && !pathOnly) {
|
56 | req.targetHostname = cfHostname
|
57 | }
|
58 | req.targetPath = cfPath
|
59 |
|
60 | debug('new targetHostname: '+req.targetHostname);
|
61 | debug('new targetPath: ' + req.targetPath);
|
62 |
|
63 | next()
|
64 | }
|
65 |
|
66 | module.exports.init = function (config, logger, stats) {
|
67 | //this variable will allow the override of only the targetPath
|
68 | //why is this useful?: it is possible for a cf app to have multiple
|
69 | //routes (ex: an internal route available only from within the
|
70 | //corp network vs. an external route available from the internet).
|
71 | //the hostname that is set during the route-bind-services cmd maybe
|
72 | //external route. however, MG need not use that route the request.
|
73 | //it can optimize and use an internal route (which the developer can
|
74 | //specify in as the target endpoint in the API Proxy). In short,
|
75 | //external consumers will still access the app from the external route
|
76 | //but instead of MG forwardinf the request back to the external route,
|
77 | //it will use an internal route (if the proxy endpoint had such a target)
|
78 | pathOnly = config['pathOnly'] || false;
|
79 |
|
80 | return {
|
81 | onrequest: retarget
|
82 | }
|
83 | }
|