UNPKG

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