From 867243935852cea47e4f65848eee4b2f55e4d126 Mon Sep 17 00:00:00 2001 From: Marsell Kukuljevic Date: Sat, 10 Apr 2021 21:14:09 +0200 Subject: [PATCH] Changed how paths are handled by server.js, to more closely match the Angular dev environment. New paths: /api/login: redirects to SSO /api: all calls (other than above) are sent to cloudapi /: static content served from static/ All API calls to cloudapi now pass through server.js's HTTP /api, not /. The static/static path is now gone, since it was causing too much trouble. static/ is now a symlink directly to app/dist, which is where a fresh Angular build appears when app/ is built. --- README.md | 35 ++++++++++++++--------------------- bin/server.js | 38 ++++++++++++++++++++++++-------------- static | 1 + static/index.html | 5 ----- static/static | 1 - 5 files changed, 39 insertions(+), 41 deletions(-) create mode 120000 static delete mode 100644 static/index.html delete mode 120000 static/static diff --git a/README.md b/README.md index dbf0dad..39eb91c 100644 --- a/README.md +++ b/README.md @@ -25,46 +25,39 @@ The SSH key used must be the correct format, e.g. generated with: # Endpoints -## GET /static/* +## GET /* This is where all the front-end code goes. All files will be served as-is as -found in that directory. The default is static/index.html. There is no -authentication; all files are public. +found in that directory (by default a symlink to app/dist). The default is +static/index.html. There is no authentication; all files are public. -## GET /login +## GET /api/login Call this endpoint to begin the login cycle. It will redirect you to the SSO login page: an HTTP 302, with a Location header. -## GET /token +## GET/POST/PUT/DELETE/HEAD /api/* -Upon successful login, the SSO login page will redirect to this endpoint. This -endpoint will return a 204, along with a X-Auth-Token header that must be saved -by the front-end code. All subsequent calls should provide this X-Auth-Token -header. - -## Other - -All other calls will be passed through to cloudapi. For these calls to succeed, -they MUST provide the X-Auth-Token header that the /token endpoint returns. +All calls will be passed through to cloudapi. For these calls to succeed, +they MUST provide an X-Auth-Token header, containing the token returned from +SSO. # Interaction cycle -client --- GET /login --------> this server +client --- GET /api/login --------> this server <-- 302 Location #1 ---- client --- GET --> SSO server - <-- 302 Location #2 ---- - -client --- GET --> this server - <-- 204 X-Auth-Token ---- + <-- 302 with token query arg From now on call this server as if it were a cloudapi server (using [cloudapi paths](https://github.com/joyent/sdc-cloudapi/blob/master/docs/index.md#api-introduction)), -always providing the X-Auth-Token. For example, to retrieve a list of packages: +except prefixing any path with "/api". Also always provide the X-Auth-Token. -client --- GET /my/packages --> this server +For example, to retrieve a list of packages: + +client --- GET /api/my/packages --> this server <-- 200 JSON body ------ The most useful cloudapi endpoints to begin with will be ListPackages, diff --git a/bin/server.js b/bin/server.js index 13a9396..ce5b150 100755 --- a/bin/server.js +++ b/bin/server.js @@ -15,6 +15,10 @@ let CLOUDAPI = {}; let CLOUDAPI_HOST = ''; let SIGNER = {}; +const LOGIN_PATH = '/api/login'; +const API_PATH = '/api'; // all calls here go to cloudapi +const API_RE = new RegExp('^' + API_PATH + '/'); +const STATIC_RE = new RegExp('^/'); // Take any HTTP request that has a token, sign that request with an // HTTP-Signature header, and pass it along to cloudapi. Return any response @@ -40,16 +44,19 @@ function proxy(req, res, cb) { // check the X-Auth-Token is present if (req.header('X-Auth-Token') == undefined) { - res.send({"Error": "X-Auth-Token header missing"}); + res.send({'Error': 'X-Auth-Token header missing'}); res.send(401); return cb(); } + // strip off /api from path before forwarding to cloudapi + let url = req.url.substr(API_PATH.length); + // sign the request before forwarding to cloudapi let headers = req.headers; var rs = mod_sdcauth.requestSigner({ sign: SIGNER }); headers.date = rs.writeDateHeader(); - rs.writeTarget(req.method, req.url); + rs.writeTarget(req.method, url); rs.sign(function signedCb(err, authz) { if (err) { @@ -60,10 +67,12 @@ function proxy(req, res, cb) { headers.authorization = authz; const opts = { - path: req.url, + path: url, headers: headers }; +console.dir(opts); + // make the call to cloudapi switch (req.method) { case 'GET': CLOUDAPI.get(opts, proxyReturn); break; @@ -153,20 +162,21 @@ function main() { server.use(mod_restify.authorizationParser()); server.use(mod_restify.bodyReader()); - // where to server static content from - server.get(/^\/static.*/, mod_restify.plugins.serveStatic({ + // login path is /api/login + server.get(LOGIN_PATH, login); + + // all cloudapi calls are proxied through /api + server.get(API_RE, proxy); + server.put(API_RE, proxy); + server.del(API_RE, proxy); + server.post(API_RE, proxy); + server.head(API_RE, proxy); + + // where to serve static content from + server.get(STATIC_RE, mod_restify.plugins.serveStatic({ directory: 'static', default: 'index.html' })); - - // route HTTP requests to proper functions - server.get('/login', login); - - server.get(/^/, proxy); - server.put(/^/, proxy); - server.del(/^/, proxy); - server.post(/^/, proxy); - server.head(/^/, proxy); // enable HTTP server server.listen(CONFIG.server.port, function listening() { diff --git a/static b/static new file mode 120000 index 0000000..ddac10c --- /dev/null +++ b/static @@ -0,0 +1 @@ +app/dist \ No newline at end of file diff --git a/static/index.html b/static/index.html deleted file mode 100644 index e45adde..0000000 --- a/static/index.html +++ /dev/null @@ -1,5 +0,0 @@ - - - Hi! - - diff --git a/static/static b/static/static deleted file mode 120000 index 945c9b4..0000000 --- a/static/static +++ /dev/null @@ -1 +0,0 @@ -. \ No newline at end of file