# [GDSC] NodeJS (2) [TOC] > 我不是 Javascript 專業,講錯歡迎指教 --- ## HTTP Request Method (REST) #### Protocol - HTTP - REST / RESTful #### Dependency - `npm install mongodb mongoose dotenv` - Create database, open [Atlas](https://cloud.mongodb.com/v2#/org/6589537fa4947020c782e44b/) 1. build a project (free plan) with sample data 2. choose `Drivers` option to build connection 3. connection link should be like `mongodb+srv://<username>:<password>@cluster0.c0ikn.mongodb.net/?retryWrites=true&w=majority&appName=Cluster0` 4. Click `Collection` column, a sample database named `sample_mflix` 5. Replace connection link with your username and password, add database name `sample_mflix` behind the base link **(or use `dbName` option with mongoose)** 6. mainly use `user` table in this course #### Load .env File path: `app.js` ```javascript= require('dotenv').config(); const dbLink = process.env.MONGODB_API; ``` #### Connect to database File path: `app.js` ```javascript= // Add dependency const mongoose = require('mongoose'); // Connect to ODM with driver link mongoose.connect(dbLink, { dbName: "sample_mflix", }); // Event listener const db = mongoose.connection; db.on('error', console.error.bind(console, 'MongoDB connection error:')); db.once('open', function () { console.log('Connected to MongoDB'); }); ``` #### Schema File path: `models/user.js` ```javascript= const mongoose = require('mongoose'); const userSchema = new mongoose.Schema({ name: { type: String, required: true }, email: { type: String, required: true, unique: true }, password: { type: String, required: true }, }); // syntax: mongoose.model(modelName, schema) const User = mongoose.model('User', userSchema); module.exports = User; ``` :question: 為什麼知道 schema 長這樣呢? 我又不會通靈 :a: 答案是去 Atlas 看已經建立好的 sample data 樣貌! **API** [`mongoose.Schema()`](https://mongoosejs.com/docs/api/mongoose.html#Mongoose.prototype.Schema()) [`mongoose.model()`](https://mongoosejs.com/docs/api/mongoose.html#Mongoose.prototype.model()) ### GET **用途** 從伺服器 (server) 取得特定資源 **範例** File path: `routes/users.js` Route: `/users` ```javascript= router.get('/', async (req, res) => { try { const users = await User.find(); res.json(users); } catch (error) { res.status(500).json({ message: error.message }); } }); ``` File path: `routes/users.js` Route: `/users/:id` ```javascript= router.get('/:id', async (req, res) => { try { const user = await User.findById(req.params.id); if (!user) { return res.status(404).json({ message: 'User not found' }); } res.json(user); } catch (error) { res.status(500).json({ message: error.message }); } }); ``` **API** [`Model.find()`](https://mongoosejs.com/docs/api/model.html#Model.find()) ### POST **用途** 將數據發送到伺服器 **範例** File path: `routes/users.js` Route: `/users` ```javascript= router.post('/', async (req, res) => { try { const user = new User(req.body); await user.save(); res.status(201).json(user); } catch (error) { res.status(400).json({ message: error.message }); } }); ``` **API** [`Model.prototype.save()`](https://mongoosejs.com/docs/api/model.html#Model.prototype.save()) ### PUT **用途** 更新伺服器中的指定數據,通常是全部更新 > 如果是部分更新,使用 `PATCH` **範例** File path: `routes/users.js` Route: `/users/:id` ```javascript= router.put('/:id', async (req, res) => { try { const user = await User.findByIdAndUpdate(req.params.id, req.body, { new: true }); if (!user) { return res.status(404).json({ message: 'User not found' }); } res.json(user); } catch (error) { res.status(400).json({ message: error.message }); } }); ``` **API** [`Model.findByIdAndUpdate()`](https://mongoosejs.com/docs/api/model.html#Model.findByIdAndUpdate()) ### DELETE **用途** 刪除伺服器中的指定數據 **範例** File path: `routes/users.js` Route: `/users/:id` ```javascript= router.delete('/:id', async (req, res) => { try { const user = await User.findByIdAndDelete(req.params.id); if (!user) { return res.status(404).json({ message: 'User not found' }); } res.json({ message: 'User deleted' }); } catch (error) { res.status(500).json({ message: error.message }); } }); ``` **API** [`Model.findByIdAndDelete()`](https://mongoosejs.com/docs/api/model.html#Model.findByIdAndDelete()) ### OPTIONS **用途** 設定請求資訊, including mehtod, headers, status code... **範例** ```javascript= app.options('/users', (req, res) => { res.setHeader('Allow', 'GET, POST, PUT, DELETE, OPTIONS'); res.status(204).send(); }); ``` **API** GeeksforGeeks - [Node response.setHeader() Method](https://www.geeksforgeeks.org/node-js-response-setheader-method/) > [!Note] More details > - MDN - [HTTP request methods](https://developer.mozilla.org/en-US/docs/Web/HTTP/Methods) > - MDN - [HTTP response status codes](https://developer.mozilla.org/en-US/docs/Web/HTTP/Status) ### Manual Testing #### Prerequisite - Install vscode plugin **Thunder Client** --- ## Websocket 1. 使用 `express-generator` 生成專案後,在 `/bin/www` 設定 ```javascript= /** * Import websocket package */ const WebSocket = require('ws'); /** * Create a websocket instance */ const wss = new WebSocket.Server({ server }); wss.on('connection', function connection(ws) { console.log('A new client connected'); ws.on('message', function incoming(message) { console.log('received: %s', message); ws.send(`Server received: ${message}`); }); ws.on('close', () => { console.log('Client disconnected'); }); ws.send('Welcome to the WebSocket server!'); }); ``` 2. Add a file named `ws-client.html` under `/public/we-client.html` ```html= <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>WebSocket Client</title> </head> <body> <h1>WebSocket Client</h1> <input id="message" type="text" placeholder="Type a message"> <button onclick="sendMessage()">Send</button> <div id="messages"></div> <script> const ws = new WebSocket(`ws://${window.location.host}`); ws.onopen = function() { document.getElementById('messages').innerHTML += '<p>Connected to the server</p>'; }; ws.onmessage = function(event) { document.getElementById('messages').innerHTML += `<p>Server: ${event.data}</p>`; }; ws.onclose = function() { document.getElementById('messages').innerHTML += '<p>Disconnected from the server</p>'; }; function sendMessage() { const message = document.getElementById('message').value; ws.send(message); document.getElementById('messages').innerHTML += `<p>You: ${message}</p>`; } </script> </body> </html> ``` 3. Access `http://localhost:3000/ws-client.html`