| const getTextContentType = (text) => { | ||
| if (isSVGXML(text)) return "image/svg+xml"; | ||
| if (isSVG(text)) return "image/svg"; | ||
| if (isXML(text)) return "application/xml"; | ||
| if (isHTML(text)) return "text/html"; | ||
| else if (/^\s*\/\*.*?\*\/\s*/.test(text)) { | ||
| return "text/css"; | ||
| } else if ( | ||
| /^\s*(var|let|const|function|console|class|if|else|while|for|switch)\b/.test( | ||
| text | ||
| ) | ||
| ) { | ||
| return "text/javascript"; | ||
| } else if ( | ||
| /^\s*\{.*\}\s*$/.test(text) || | ||
| (typeof text === "object" && !Array.isArray(text) && text !== null) | ||
| ) { | ||
| return "application/json"; | ||
| } else { | ||
| return "text/plain"; | ||
| } | ||
| }; | ||
| const isSVGXML = (text) => { | ||
| return /<svg[^>]+xmlns="http:\/\/www\.w3\.org\/2000\/svg"/i.test(text); | ||
| }; | ||
| const isHTML = (text) => { | ||
| if ( | ||
| (/^\s*<!doctype html>/i.test(text) && | ||
| hasMatchingOpeningAndClosingTags( | ||
| text.replace(/<!doctype html>/i, "").trim() | ||
| )) || | ||
| hasMatchingOpeningAndClosingTags(text) | ||
| ) | ||
| return true; | ||
| }; | ||
| const isSVG = (text) => { | ||
| return hasMatchingOpeningAndClosingTags(text, "svg"); | ||
| }; | ||
| const isXML = (text) => { | ||
| const isXMLVE = () => { | ||
| return /^<\?xml\s+version=[^\s]+\s+encoding=[^\s]+\s*\?>/.test(text); | ||
| }; | ||
| if ( | ||
| isXMLVE() && | ||
| hasMatchingOpeningAndClosingTags(text.replace(/<\?xml[^?]+\?>/i, "").trim()) | ||
| ) { | ||
| console.log("came here"); | ||
| console.log(text); | ||
| return true; | ||
| } | ||
| }; | ||
| function hasMatchingOpeningAndClosingTags(str, tagName) { | ||
| const regex = /<(\w+)[^>]*>|<\/(\w+)>/g; | ||
| const tags = str.match(regex); | ||
| if (!tags) { | ||
| return false; // No tags found | ||
| } | ||
| const openingTag = tags[0].slice(1, -1).split(" ")[0]; | ||
| const closingTag = tags[tags.length - 1].slice(2, -1); | ||
| console.log(openingTag); | ||
| console.log(closingTag); | ||
| if (tagName) { | ||
| return ( | ||
| openingTag.toLowerCase() === tagName.toLowerCase() && | ||
| closingTag.toLowerCase() === tagName.toLowerCase() | ||
| ); | ||
| } else { | ||
| return openingTag === closingTag; | ||
| } | ||
| } | ||
| const getFileContentType = (path) => { | ||
| const fileExtension = path.split(".").pop(); | ||
| switch (fileExtension) { | ||
| case "html": | ||
| return "text/html"; | ||
| case "css": | ||
| return "text/css"; | ||
| case "js": | ||
| return "text/javascript"; | ||
| case "json": | ||
| return "application/json"; | ||
| case "jpg": | ||
| return "image/jpg"; | ||
| case "jpeg": | ||
| return "image/jpeg"; | ||
| case "png": | ||
| return "image/png"; | ||
| case "gif": | ||
| return "image/gif"; | ||
| case "pdf": | ||
| return "application/pdf"; | ||
| case "mp4": | ||
| return "video/mp4"; | ||
| case "mp3": | ||
| return "audio/mp3"; | ||
| default: | ||
| return "application/octet-stream"; | ||
| } | ||
| }; | ||
| export { getFileContentType, getTextContentType }; |
| import RestWave from "../src/index.js"; | ||
| import path from "path"; | ||
| import { fileURLToPath } from "url"; | ||
| const __filename = fileURLToPath(import.meta.url); | ||
| const __dirname = path.dirname(__filename); | ||
| const app = new RestWave(); | ||
| app.get("/", (req, res) => { | ||
| res.sendFile(__dirname + "/test-data/png.png"); | ||
| }); | ||
| // app.route("/sike").put((req, res) => { | ||
| // res.json("in put "); | ||
| // }); | ||
| // const router = RestWave.router(); | ||
| // router.route("/r").put((req, res) => { | ||
| // res.json("in route put"); | ||
| // }); | ||
| // app.use(router); | ||
| // app.post("/", (req, res) => { | ||
| // res.json({ name: " adarsh", last: "shahi", age: 21 }, 201); | ||
| // }); | ||
| // app.patch("/", (req, res) => { | ||
| // res.json({ name: " adarsh", last: "shahi", age: 21 }, 203); | ||
| // }); | ||
| // app.delete("/", (req, res) => { | ||
| // res.json({ name: " adarsh", last: "shahi", age: 21 }, 200); | ||
| // }); | ||
| app.printMiddlewares(); | ||
| app.listen(5000, () => { | ||
| console.log("server listening on port 5000"); | ||
| }); |
+2
-2
| { | ||
| "name": "restwave", | ||
| "version": "2.4.2", | ||
| "version": "2.5.2", | ||
| "description": "simplified version of express", | ||
@@ -8,3 +8,3 @@ "main": "./src/index.js", | ||
| "scripts": { | ||
| "dev": "nodemon src/test.js", | ||
| "dev": "nodemon tests/test.js", | ||
| "test": "echo \"Error: no test specified\" && exit 1" | ||
@@ -11,0 +11,0 @@ }, |
+76
-7
| import Methods from "./methods/method.js"; | ||
| import net from "net"; | ||
| import statusCodes from "./utils/statusCodes.js"; | ||
| import { getTextContentType, getFileContentType } from "./utils/contentType.js"; | ||
| import fs from "fs"; | ||
@@ -12,2 +14,3 @@ class RestWave extends Methods { | ||
| #contentLength; | ||
| #responseHeaders = {}; | ||
@@ -68,2 +71,6 @@ constructor() { | ||
| }); | ||
| socket.on("error", (err) => { | ||
| console.log(err); | ||
| }); | ||
| }); | ||
@@ -111,7 +118,7 @@ } | ||
| } else { | ||
| throw new Error("Requested endpoint not handled"); | ||
| // throw new Error("Requested endpoint not handled"); | ||
| } | ||
| } | ||
| } else { | ||
| throw new Error("Requested endpoint not handled"); | ||
| // throw new Error("Requested endpoint not handled"); | ||
| } | ||
@@ -169,9 +176,8 @@ }; | ||
| this.#contentLength += arg.length; | ||
| const content = `${this.#data}\r\n\r\n${arg}`; | ||
| this.#data += content; | ||
| const content = `\r\n\r\n${arg}`; | ||
| return `HTTP/1.1 ${this.#response.statusCode} ${ | ||
| statusCodes[this.#response.statusCode] | ||
| }\r\nAccess-Control-Allow-Origin: *\r\nContent-Type: application/json\r\nContent-Length: ${ | ||
| this.#contentLength | ||
| }${content}`; | ||
| }\r\nAccess-Control-Allow-Origin: *\r\nContent-Type: ${ | ||
| this.#responseHeaders["Content-Type"] | ||
| }\r\nContent-Length: ${this.#contentLength}${content}`; | ||
| }; | ||
@@ -181,2 +187,5 @@ | ||
| statusCode: 200, | ||
| setHeaders: (obj) => { | ||
| this.#responseHeaders = { ...this.#responseHeaders, ...obj }; | ||
| }, | ||
| json: (arg, sc) => { | ||
@@ -196,2 +205,62 @@ if (sc) this.#response.statusCode = sc; | ||
| }, | ||
| send: (arg = "", sc) => { | ||
| if (sc) this.#response.statusCode = sc; | ||
| if (arg) { | ||
| if (!this.#responseHeaders.hasOwnProperty("Content-Type")) { | ||
| const type = getTextContentType(arg); | ||
| if (type === "application/json") { | ||
| arg = JSON.stringify(arg); | ||
| } | ||
| this.#response.setHeaders({ | ||
| "Content-Type": type, | ||
| }); | ||
| } | ||
| } | ||
| const sike = writeResponse(arg); | ||
| this.#socket.write(sike, "utf-8", () => { | ||
| this.#socket.end(); | ||
| }); | ||
| }, | ||
| sendFile: (path) => { | ||
| if (!path) throw new Error("Path name expected."); | ||
| const file = fs.readFileSync(path); | ||
| if (!this.#responseHeaders.hasOwnProperty("Content-Type")) { | ||
| const type = getFileContentType(path); | ||
| this.#response.setHeaders({ | ||
| "Content-Type": type, | ||
| }); | ||
| } | ||
| // Prepare HTTP headers | ||
| const headers = [ | ||
| `HTTP/1.1 ${this.#response.statusCode} ${ | ||
| statusCodes[this.#response.statusCode] | ||
| }`, | ||
| `Content-Type: ${getFileContentType(path)}`, | ||
| `Content-Length: ${file.length}`, | ||
| "Access-Control-Allow-Origin: *", | ||
| "Connection: close", | ||
| "\r\n", | ||
| ].join("\r\n"); | ||
| // Combine headers and video file data | ||
| const httpResponse = Buffer.concat([Buffer.from(headers), file]); | ||
| // Step 4: Send the HTTP response to the client | ||
| // this.#socket.write(writeResponse(file)); | ||
| this.#socket.write(httpResponse); | ||
| this.#socket.end(); | ||
| // const fileReadHandler = await fs.open(path); | ||
| // const stream = fileReadHandler.createReadStream(); | ||
| // this.#response.setHeaders({ "Content-Type": "video/mp4" }); | ||
| // this.#socket.write( | ||
| // `HTTP/1.1 206 ${ | ||
| // statusCodes["206"] | ||
| // }\r\nAccess-Control-Allow-Origin: *\r\nContent-Type: ${ | ||
| // this.#responseHeaders["Content-Type"] | ||
| // }` | ||
| // ); | ||
| // stream.pipe(this.#socket.write); | ||
| }, | ||
| }; | ||
@@ -198,0 +267,0 @@ } |
-31
| import RestWave from "./index.js"; | ||
| const app = new RestWave(); | ||
| app.get("/", (req, res) => { | ||
| res.json({ name: " adarsh", last: "shahi", age: 21 }, 200); | ||
| }); | ||
| app.route("/sike").put((req, res) => { | ||
| res.json("in put "); | ||
| }); | ||
| const router = RestWave.router(); | ||
| router.route("/r").put((req, res) => { | ||
| res.json("in route put"); | ||
| }); | ||
| app.use(router); | ||
| app.post("/", (req, res) => { | ||
| res.json({ name: " adarsh", last: "shahi", age: 21 }, 201); | ||
| }); | ||
| app.patch("/", (req, res) => { | ||
| res.json({ name: " adarsh", last: "shahi", age: 21 }, 203); | ||
| }); | ||
| app.delete("/", (req, res) => { | ||
| res.json({ name: " adarsh", last: "shahi", age: 21 }, 200); | ||
| }); | ||
| app.printMiddlewares(); | ||
| app.listen(5000, () => { | ||
| console.log("server listening on port 5000"); | ||
| }); |
Network access
Supply chain riskThis module accesses the network.
Found 1 instance in 1 package
Filesystem access
Supply chain riskAccesses the file system, and could potentially read sensitive data.
Found 1 instance in 1 package
Network access
Supply chain riskThis module accesses the network.
Found 1 instance in 1 package
24821
24.22%9
12.5%696
31.82%1
Infinity%