-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathindex.js
146 lines (124 loc) · 4.48 KB
/
index.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
let fs = require('fs')
let path = require('path')
let express = require('express')
let nodeify = require('bluebird-nodeify')
let morgan = require('morgan')
let mime = require('mime-types')
let rimraf = require('rimraf')
let mkdirp = require('mkdirp')
let argv = require('yargs').argv
let net = require('net')
let JsonSocket = require('json-socket')
// songbird works during runtime. Hence, not assigning it to a variable
require('songbird')
const NODE_ENV = process.env.NODE_ENV; //gets the env
const PORT = process.env.PORT || 8000;
// need a root directory for the file system api implementation
const ROOT_DIR = argv.dir ? path.resolve(argv.dir) : path.resolve(process.cwd());
// setting up the express app
let app = express()
// use() method is for adding the middleware
app.use(morgan('dev'))
app.listen(PORT,() => console.log(`HTTP Server listening @ http://127.0.0.1:${PORT}`))
// HEADERS
app.head('*', setFileMeta, sendHeaders,(req, res) => res.end())
// GET
app.get('*', setFileMeta, sendHeaders,(req, res) => {
if (res.body) {
res.json(res.body)
return
}
fs.createReadStream(req.filePath).pipe(res)
})
// DELETE
app.delete('*', setFileMeta,(req, res, next) => {
async() => {
if (!req.stat) return res.send(400, 'Invalid Path')
if (req.stat.isDirectory()) {
await rimraf.promise(req.filePath)
} else await fs.promise.unlink(req.filePath)
res.end()
} ().catch(next)
})
// PUT
app.put('*', setFileMeta, setDirDetails,(req, res, next) => {
async() => {
if (req.stat) return res.send(405, 'File Exists')
await mkdirp.promise(req.dirPath)
if (!req.isDir) req.pipe(fs.createWriteStream(req.filePath))
res.end()
} ().catch(next)
})
// POST
app.post('*', setFileMeta, setDirDetails,(req, res, next) => {
async() => {
if (!req.stat) return res.send(405, 'File does not exist')
if (req.isDir) return res.send(405, 'Path is a directory')
await fs.promise.truncate(req.filePath, 0)
if (!req.isDir) req.pipe(fs.createWriteStream(req.filePath))
res.end()
} ().catch(next)
})
function setDirDetails(req, res, next) {
let filePath = req.filePath
let endsWithSlash = filePath.charAt(filePath.length - 1) === path.sep
let hasExt = path.extname(filePath) !== ''
req.isDir = endsWithSlash || !hasExt
req.dirPath = req.isDir ? filePath : path.dirname(filePath)
next()
}
/* rather than splitting into separate functions, the
calls are split into middlewares and then called*/
function setFileMeta(req, res, next) {
// ROOT_DIR and __dirname are the same
// resolve() resolves the path of any '.' characters
req.filePath = path.resolve(path.join(ROOT_DIR, req.url))
if (req.filePath.indexOf(ROOT_DIR) !== 0) {
res.send(400, 'Invalid Path')
return
}
// Way to call nodeify on a promise; check for async function too
fs.promise.stat(req.filePath)
.then(stat => req.stat = stat,() => req.stat = null)
.nodeify(next)
}
function sendHeaders(req, res, next) {
// promise is connected to the next callback (use of nodeify)
// nodeify calls next even if it succeeds or fails
nodeify(async() => {
// If the path is a directory, return the contents
if(req.stat.isDirectory()) {
let files = await fs.promise.readdir(req.filePath)
res.body = JSON.stringify(files)
res.setHeader('Content-Length', res.body.length)
res.setHeader('Content-Type', 'application/json')
return
}
res.setHeader('Content-Length', req.stat.size)
let contentType = mime.contentType(path.extname(req.filePath))
res.setHeader('Content-Type', contentType)
}(), next)
//.catch(next) //next is called only if this promise results in an error
}
// TCP Functionality
let TCP_PORT = `8001`
let server = net.createServer()
server.listen(TCP_PORT)
console.log(`TCP Server listening @ http://127.0.0.1:${TCP_PORT}`)
server.on('connection', function (socket) {
socket = new JsonSocket(socket);
socket.on('message', function(message) {
let serverFileLocation = path.join(process.cwd(), message.fileName)
let clientFileLocation = path.join(message.location, message.fileName)
if (message.action === 'write') {
fs.promise.writeFile(serverFileLocation, message.contents)
.then(console.log(`file created at ${serverFileLocation}`))
fs.promise.writeFile(clientFileLocation, message.contents)
.then(socket.sendMessage(`file created at ${clientFileLocation}`))
// console.log(message.updated)
// console.log(path)
}
else if (message.action === 'delete') {
}
})
})