• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

ubccpsc / classy / 47029edf-f331-4b4d-bbff-ed4f07561520

19 Dec 2024 09:55PM UTC coverage: 87.102% (-0.2%) from 87.336%
47029edf-f331-4b4d-bbff-ed4f07561520

push

circleci

web-flow
Merge pull request #466 from ubccpsc310/cs310_24w1

Incorporate 310_24w1 improvements.

1108 of 1350 branches covered (82.07%)

Branch coverage included in aggregate %.

3950 of 4457 relevant lines covered (88.62%)

35.81 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

94.44
packages/portal/backend/src/server/BackendServer.ts
1
/**
2
 * Created by rtholmes on 2018-02-23.
3
 */
4
import * as fs from "fs";
1✔
5
import * as restify from "restify";
1✔
6

7
import Config, {ConfigKey} from "@common/Config";
1✔
8
import Log from "@common/Log";
1✔
9

10
import {Factory} from "../Factory";
1✔
11
import AdminRoutes from "./common/AdminRoutes";
1✔
12
import {AuthRoutes} from "./common/AuthRoutes";
1✔
13
import {AutoTestRoutes} from "./common/AutoTestRoutes";
1✔
14
import GeneralRoutes from "./common/GeneralRoutes";
1✔
15
import {GitHubController} from "@backend/controllers/GitHubController";
1✔
16
import {GitHubActions} from "@backend/controllers/GitHubActions";
1✔
17

18
/**
19
 * This configures the REST endpoints for the server.
20
 */
21
export default class BackendServer {
1✔
22

23
    private rest: restify.Server;
24
    private config: Config = null;
4✔
25
    private useHttps = false;
4✔
26

27
    constructor(useHttps = true) {
×
28
        Log.info("BackendServer::<init> - start");
4✔
29
        this.config = Config.getInstance();
4✔
30
        this.useHttps = useHttps;
4✔
31
    }
32

33
    /**
34
     * Used in tests.
35
     *
36
     * @returns {Server}
37
     */
38
    public getServer(): restify.Server {
39
        Log.trace("BackendServer::getServer()");
4✔
40
        return this.rest;
4✔
41
    }
42

43
    /**
44
     * Stops the server. Returns a promise so that we know when the connections
45
     * have actually been fully closed and the port has been released.
46
     *
47
     * @returns {Promise<boolean>}
48
     */
49
    public stop(): Promise<boolean> {
50
        Log.info("BackendServer::stop() - start");
4✔
51
        const that = this;
4✔
52
        return new Promise(function (fulfill) {
4✔
53
            that.rest.close(function () {
4✔
54
                Log.info("BackendServer::stop() - done");
4✔
55
                fulfill(true);
4✔
56
            });
57
        });
58
    }
59

60
    /**
61
     * Starts the server. Returns a promise with a boolean value. Promises are used
62
     * here because starting the server takes some time, and we want to know when it
63
     * is done (and if it worked).
64
     *
65
     * @returns {Promise<boolean>}
66
     */
67
    public start(): Promise<boolean> {
68
        Log.info("BackendServer::start() - start");
4✔
69

70
        const that = this;
4✔
71
        return new Promise(function (fulfill, reject) {
4✔
72

73
            // noinspection TsLint
74
            const httpsOptions: any = {
4✔
75
                name: "backend"
76
            };
77

78
            /* istanbul ignore else */
79
            if (that.useHttps === false) {
4✔
80
                // test only
81
                Log.warn("BackendServer::start() - disabling HTTPS; should only be used in testing!");
4✔
82
            } else {
83
                // prod only
84
                httpsOptions["key"] = fs.readFileSync(that.config.getProp(ConfigKey.sslKeyPath));
85
                httpsOptions["certificate"] = fs.readFileSync(that.config.getProp(ConfigKey.sslCertPath));
86
            }
87

88
            that.rest = restify.createServer(httpsOptions);
4✔
89
            that.rest.use(restify.plugins.queryParser());
4✔
90
            that.rest.use(restify.plugins.bodyParser({mapParams: true}));
4✔
91

92
            that.rest.use(function crossOrigin(req, res, next) {
4✔
93
                res.header("Access-Control-Allow-Origin", "*");
133✔
94
                res.header("Access-Control-Allow-Headers", "X-Requested-With Content-Type token user org");
133✔
95
                return next();
133✔
96
            });
97

98
            // prevent caching, overrides cache headers in html files
99
            that.rest.use(function(req, res, next) {
4✔
100
                res.header("Last-Modified", new Date());
133✔
101
                res.header("Cache-Control", "no-cache, no-store, must-revalidate, max-age=0");
133✔
102
                return next();
133✔
103
            });
104

105
            // Register handlers common between all classy instances
106
            Log.info("BackendServer::start() - Registering common handlers");
4✔
107

108
            // authentication
109
            new AuthRoutes().registerRoutes(that.rest);
4✔
110

111
            // autotest
112
            new AutoTestRoutes().registerRoutes(that.rest);
4✔
113

114
            // general
115
            new GeneralRoutes().registerRoutes(that.rest);
4✔
116

117
            // admin
118
            new AdminRoutes().registerRoutes(that.rest);
4✔
119

120
            Log.info("BackendServer::start() - Registering common handlers; done");
4✔
121

122
            // Register custom route handler for specific classy instance
123
            Log.info("BackendServer::start() - Registering custom handlers");
4✔
124

125
            Log.info("BackendServer::start() - Loading custom course controller");
4✔
126
            // We do not need a Custom Course Controller here, but this is a good place
127
            // to make sure that the CustomCourseController loads up as expected
128
            // alongside the CustomRouteHandler.
129
            Factory.getCourseController(new GitHubController(GitHubActions.getInstance())).then(function (cc) {
4✔
130
                Log.info("BackendServer::start() - CustomCourseController loaded");
4✔
131
            }).catch(function (err) {
132
                Log.error("BackendServer::start() - Unable to load CustomCourseController: " + err);
×
133
            });
134

135
            Log.info("BackendServer::start() - Loading custom route handler");
4✔
136
            Factory.getCustomRouteHandler().then(function (handler) {
4✔
137
                Log.info("BackendServer::start() - CustomRouteHandler loaded");
4✔
138
                handler.registerRoutes(that.rest);
4✔
139
                Log.info("BackendServer::start() - CustomRouteHandler registered");
4✔
140

141
                // serve up the static frontend resources
142
                const frontendHTML = __dirname + "/../../../frontend/html";
4✔
143
                Log.info("BackendServer::start() - Serving static from: " + frontendHTML);
4✔
144
                that.rest.get("/*", restify.plugins.serveStatic({
4✔
145
                    directory: frontendHTML,
146
                    default: "index.html"
147
                }));
148

149
                const port = that.config.getProp(ConfigKey.backendPort);
4✔
150
                that.rest.listen(port, function () {
4✔
151
                    Log.info("BackendServer::start() - restify listening: " + that.rest.url + "; on port: " + port);
4✔
152

153
                    // after the Classy backend is up, check AutoTest
154
                    // (Docker should load AutoTest first, but the delay should not hurt)
155
                    setTimeout(() => {
4✔
156
                        AutoTestRoutes.checkATStatus().then(function (_result) {
3✔
157
                            Log.trace("BackendServer::start() - AT status: success");
×
158
                        }).catch(function (err) {
159
                            Log.trace("BackendServer::start() - AT status: failure; ERROR: " + err.message);
3✔
160
                        });
161
                    }, 500);
162

163
                    fulfill(true);
4✔
164
                });
165

166
                /* istanbul ignore next */
167
                that.rest.on("error", function (err: string) {
168
                    // catches errors in restify start; unusual syntax due to internal node not using normal exceptions here
169
                    Log.error("BackendServer::start() - restify ERROR: " + err);
170
                    reject(err);
171
                });
172
            }).catch(function (err) {
173
                Log.error("BackendServer::start() - Registering custom ERROR: " + err);
×
174
            });
175

176
        });
177
    }
178
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc