UNPKG

5.83 kBJavaScriptView Raw
1/*jshint -W086 */
2
3"use strict";
4
5// NOTE: Brackets doesn't fully support browsers yet and we need some workarounds. Workarounds will be marked with "HACK:" label.
6
7var http = require("http"),
8 https = require("https"),
9 path = require("path"),
10 send = require("send"),
11 util = require("util"),
12 files = require("./files"),
13 domains = require("./domains/socket"),
14 socket = require("socket.io"),
15 brckDist = {root: path.join(__dirname, "..", "brackets-dist")},
16 zipped = { ".js": "application/javascript", ".css": "text/css"},
17 defaultPort = 6800;
18
19require("./shim");
20
21function removeTrailingSlash(path) {
22 return path[path.length - 1] === "/" ? path.substr(0, path.length - 1) : path;
23}
24
25function createHttpServer(inst, port) {
26 inst.httpServer = http.createServer(function (req, res) {
27 if (req.url === "/") {
28 res.writeHead(302, {Location: inst.httpRoot + "/"});
29 res.end();
30 } else {
31 res.writeHead(304);
32 res.end("Not found");
33 }
34 });
35 inst.io = socket(inst.httpServer);
36 inst.httpServer.listen(port);
37 console.log(util.format("\n listening on port %d\n", port));
38}
39
40function attachStatic(inst) {
41 var srv = inst.httpServer,
42 root = inst.httpRoot,
43 evs = srv.listeners("request").slice(0),
44 extDir = { root: path.join(inst.supportDir, "extensions")} ;
45
46 srv.removeAllListeners("request");
47 srv.on("request", function(req, res) {
48 if (req.url.startsWith(root)) {
49 var url = req.url.substr(root.length);
50
51 if (url === "") {
52 res.writeHead(301, {Location: inst.httpRoot + "/"});
53 res.end();
54 return;
55 }
56
57 if (url === "/") {
58 url = "/index.html";
59 }
60
61 if (url.startsWith("/s3.amazonaws.com/")) {
62 var options = {
63 hostname: "s3.amazonaws.com",
64 port: 443,
65 path: url.substr(17),
66 method: "GET"
67 };
68
69 req.pause();
70 var connector = https.request(options, function(_res) {
71 _res.pause();
72 res.writeHead(_res.statusCode, _res.headers);
73 _res.pipe(res);
74 _res.resume();
75 });
76 req.pipe(connector);
77 req.resume();
78 return;
79 }
80
81 var cntType = zipped[path.extname(url)];
82 if (cntType) {
83 send(req, url + ".gz", brckDist)
84 .on("headers", function (_res) {
85 _res.setHeader("Content-Encoding", "gzip");
86 _res.setHeader("Content-Type", cntType);
87 })
88 .pipe(res);
89 return;
90 }
91
92 send(req, url, brckDist).pipe(res);
93 } else if (req.url.startsWith("/support/extensions/")) {
94 try {
95 return send(req, req.url.substr("/support/extensions".length), extDir).pipe(res);
96 } catch (e) {
97 res.writeHead(500, {
98 "Content-Length": e.message.length,
99 "Content-Type": "text/plain"
100 });
101 res.end(e.message);
102 }
103 } else {
104 for (var i = 0; i < evs.length; i++) {
105 evs[i].call(srv, req, res);
106 }
107 }
108 });
109}
110
111function Server(srv, opts) {
112 if (!(this instanceof Server)) {
113 return new Server(srv, opts);
114 }
115
116 switch (typeof srv) {
117 case "undefined":
118 case "null":
119 createHttpServer(this, defaultPort);
120 break;
121 case "object":
122 if (srv instanceof socket) {
123 this.io = srv;
124 this.httpServer = srv.httpServer;
125 } else if (srv instanceof http.Server) {
126 this.httpServer = srv;
127 this.io = socket(this.httpServer);
128 } else {
129 opts = srv;
130 srv = null;
131 createHttpServer(this, defaultPort);
132 }
133 break;
134 case "number":
135 case "string":
136 createHttpServer(this, Number(srv));
137 break;
138 default:
139 throw "Invalid argument – srv.";
140 }
141
142 opts = opts || {};
143
144 this.httpRoot = removeTrailingSlash(opts.httpRoot || "/brackets");
145 this.defaultExtensions = path.join(brckDist.root, "extensions");
146 this.supportDir = removeTrailingSlash(opts.supportDir || path.resolve("./brackets"));
147 this.projectsDir = removeTrailingSlash(opts.projectsDir || path.resolve("./projects"));
148 this.samplesDir = removeTrailingSlash(opts.samplesDir || path.join(brckDist.root, "samples"));
149 this.allowUserDomains = opts.allowUserDomains || false;
150
151 switch (typeof opts.fileSystem) {
152 case "string":
153 // Reserved for future build-in providers.
154 this.fileSystem = require("./file-sys/" + opts.fileSystem);
155 break;
156 case "object":
157 this.fileSystem = opts.fileSystem;
158 break;
159 case "undefined":
160 case "null":
161 this.fileSystem = require("./file-sys/native");
162 break;
163 default:
164 throw new Error("Invalid fileSystem option.");
165 }
166
167 var that = this;
168 this.fileSystem.mkdir(this.projectsDir, function (err) {
169 if (err.code !== "EEXIST") {
170 throw err;
171 }
172
173 attachStatic(that);
174
175 // Attach file system methods to socket.io.
176 files.init(that);
177
178 // Attach Brackets domians.
179 domains.init(that);
180 });
181}
182
183module.exports = Server;