Danh sách câu hỏi của đề

Câu hỏi: SDN302 Server-Side development with NodeJS, Express, and MongoDB – Bộ ôn tập cuối kỳ số 2

50 câu trắc nghiệm kèm lời giải của môn Server-Side development with NodeJS, Express, and MongoDB, xếp đúng thứ tự trong đề. Trang 2/3 — câu 21–40.

Danh sách câu hỏi

40/50 câuCòn 10
AGET
BPOST with Content-Type: application/json
CDELETE
DOPTIONS
Lời giải
Đáp án đúng: "POST with Content-Type: application/json". Theo đặc tả CORS, trình duyệt gửi trước một request OPTIONS (preflight, yêu cầu thăm dò) khi request khác nguồn không phải simple request: phương thức ngoài GET, HEAD, POST, hoặc có header tuỳ chỉnh, hoặc Content-Type ngoài application/x-www-form-urlencoded, multipart/form-data, text/plain; POST kèm application/json rơi đúng vào điều kiện Content-Type nên đây là ví dụ preflight quen thuộc nhất. Cần nói thẳng: "DELETE" cũng không phải phương thức đơn giản nên thực tế cũng kích hoạt preflight; câu hỏi chỉ cho chọn một và nhắm vào ví dụ điển hình là POST với application/json, nên lựa chọn đó vẫn được giữ. "GET" là phương thức đơn giản, không kèm header đặc biệt thì được gửi thẳng không cần thăm dò. "OPTIONS" chính là phương thức trình duyệt dùng để gửi preflight, tức là bản thân yêu cầu thăm dò chứ không phải thứ kích hoạt nó.
Mở trang câu hỏi này →
AGET http://localhost:3000/articles/65e98f60982bf2f0d7cf5f26
BPOST http://localhost:3000/articles/65e98f60982bf2f0d7cf5f26
CDELETE http://localhost:3000/articles/65e98f60982bf2f0d7cf5f26
DPUT http://localhost:3000/articles/65e98f60982bf2f0d7cf5f26
Lời giải
Đáp án đúng: "GET http://localhost:3000/articles/65e98f60982bf2f0d7cf5f26". Theo quy ước REST, lấy một tài nguyên cụ thể là thao tác đọc nên dùng phương thức GET, còn đường dẫn /articles/:id chỉ đúng bài viết có _id là ObjectId 65e98f60982bf2f0d7cf5f26; trong Express, route app.get('/articles/:id') sẽ đọc giá trị này qua req.params.id rồi gọi Article.findById. Trong Postman chỉ cần chọn GET, dán URL và gửi, không cần body. "POST http://localhost:3000/articles/65e98f60982bf2f0d7cf5f26" dùng POST, phương thức để tạo tài nguyên mới (thường gửi tới /articles kèm body JSON), không dùng để đọc. "DELETE http://localhost:3000/articles/65e98f60982bf2f0d7cf5f26" sẽ xoá bài viết đó thay vì trả nó về. "PUT http://localhost:3000/articles/65e98f60982bf2f0d7cf5f26" dùng để thay thế toàn bộ bài viết bằng dữ liệu trong body, cũng là thao tác ghi chứ không phải đọc.
Mở trang câu hỏi này →
Anest new service
Bnest generate service
Cnest create service
Dnest add service
Lời giải
Đáp án đúng: "nest generate service". Nest CLI dùng lệnh generate (viết tắt g) để sinh thành phần theo schematic, ví dụ nest generate service users tạo tệp users.service.ts kèm tệp kiểm thử và tự đăng ký service vào mảng providers của module gần nhất. "nest new service" sai vì nest new dùng để khởi tạo cả một dự án NestJS mới, chữ service ở đây sẽ bị hiểu là tên dự án. "nest create service" sai vì Nest CLI không có lệnh create. "nest add service" sai vì nest add dùng để cài và cấu hình một thư viện tương thích Nest (chạy schematic cài đặt của chính gói đó), không sinh service cho ứng dụng.
Mở trang câu hỏi này →
24What is a module in NestJS?4 lựa chọnDễ
AA function that handles HTTP requests
BA file that defines a specific feature of the app
CA global object for managing app state
DA controller for defining routes
Lời giải
Đáp án đúng: "A file that defines a specific feature of the app". Trong NestJS, module là một lớp gắn decorator @Module(), thường nằm trong tệp riêng như users.module.ts, dùng để gom controllers, providers cùng imports và exports của một tính năng; ứng dụng có AppModule gốc rồi ghép các feature module lại, nên mô tả module là đơn vị định nghĩa một tính năng cụ thể là ý sát nhất, dù nói chính xác thì module là một lớp chứ không đơn thuần là tệp. "A function that handles HTTP requests" là vai trò của handler method bên trong controller. "A global object for managing app state" sai vì module không lưu trạng thái; dữ liệu dùng chung thường nằm trong provider hoặc service được tiêm qua dependency injection. "A controller for defining routes" mô tả controller, thành phần được khai báo bên trong module chứ không phải chính module.
Mở trang câu hỏi này →
AValidates after save
BRuns middleware before saving
CPopulates references
DAggregates data
Lời giải
Đáp án đúng: "Runs middleware before saving". schema.pre('save', fn) đăng ký một pre hook (middleware chạy trước) của Mongoose: mỗi lần gọi doc.save() hoặc Model.create(), hàm này chạy trước khi tài liệu được ghi xuống MongoDB, nên thường dùng để băm mật khẩu bằng bcrypt hoặc gán thời điểm cập nhật; trong document middleware, từ khoá this trỏ tới chính tài liệu sắp lưu. "Validates after save" sai hai chỗ: kiểm tra hợp lệ (validation) trong Mongoose chạy trước khi lưu, còn hook chạy sau khi lưu là schema.post('save'). "Populates references" là việc của populate() khi truy vấn, thay ObjectId bằng tài liệu được tham chiếu. "Aggregates data" là việc của Model.aggregate() với pipeline như $match, $group, không liên quan hook save.
Mở trang câu hỏi này →
26How do you create a model in Mongoose?4 lựa chọnTrung bình67% trả lời đúng
Amongoose.define()
Bmongoose.Model()
Cmongoose.create()
Dmongoose.model()
Lời giải
Đáp án đúng: "mongoose.model()". Hàm mongoose.model nhận tên model và một schema, ví dụ mongoose.model('User', userSchema), rồi biên dịch schema thành một lớp Model gắn với collection tương ứng (tên được chuyển sang số nhiều, chữ thường: users). Từ model này mới gọi được find, create, findById hay tạo document bằng new User(). "mongoose.define()" không tồn tại trong Mongoose; kiểu define đó thuộc về ORM SQL như Sequelize. "mongoose.Model()" là lớp cơ sở mà mọi model kế thừa, nó không được gọi trực tiếp để tạo model mới mà hàm model() sẽ sinh lớp con từ nó. "mongoose.create()" cũng không tồn tại; create là phương thức tĩnh trên một model đã có (User.create) dùng để tạo và lưu document, không phải để định nghĩa model.
Mở trang câu hỏi này →
27What is the purpose of the "Authentication" middleware4 lựa chọnTrung bình40% trả lời đúng
ATo validate that the anti-forgery token is present and valid in a form submission.
BTo encrypt sensitive data in web forms.
CTo handle user authentication and establish an identity for the user.
DTo prevent Cross-Site Request Forgery (CSRF) attacks.
Lời giải
Đáp án đúng: "To handle user authentication and establish an identity for the user.". Middleware xác thực (authentication) đứng trong chuỗi xử lý request, đọc thông tin chứng thực như cookie phiên hoặc header Authorization chứa JWT, kiểm tra chúng rồi gắn danh tính người dùng vào request (ví dụ req.user khi dùng Passport) để các middleware và route phía sau biết ai đang gọi. "To validate that the anti-forgery token is present and valid in a form submission." mô tả middleware chống giả mạo (anti-forgery, như csurf), không phải xác thực. "To encrypt sensitive data in web forms." sai vì mã hoá dữ liệu trên đường truyền là việc của HTTPS/TLS, middleware xác thực không mã hoá nội dung form. "To prevent Cross-Site Request Forgery (CSRF) attacks." là mục tiêu của middleware CSRF; xác thực trả lời câu hỏi người dùng là ai, còn chống CSRF trả lời câu hỏi request có thật do người dùng chủ động gửi hay không.
Mở trang câu hỏi này →
28What is two-factor authentication?4 lựa chọn
AA security measure that requires users to enter a username and password.
BA security measure that requires users to enter a password and answer a security question.
CA security measure that requires users to provide two forms of identification, typically a password and a unique code sent to their mobile device or email address.
DA security measure that requires users to complete a CAPTCHA challenge to prove they are human.
Lời giải
Đáp án đúng: "A security measure that requires users to provide two forms of identification, typically a password and a unique code sent to their mobile device or email address.". Xác thực hai yếu tố (two-factor authentication, 2FA) đòi người dùng chứng minh danh tính bằng hai yếu tố thuộc hai nhóm khác nhau: thứ mình biết như mật khẩu, và thứ mình có như điện thoại nhận mã OTP qua SMS, email hoặc ứng dụng tạo mã TOTP; kẻ lấy được mật khẩu vẫn không đăng nhập được nếu không có thiết bị. "A security measure that requires users to enter a username and password." chỉ là đăng nhập một yếu tố, vì tên người dùng không phải bí mật. "A security measure that requires users to enter a password and answer a security question." vẫn là một yếu tố vì cả mật khẩu lẫn câu hỏi bảo mật đều thuộc nhóm thứ mình biết. "A security measure that requires users to complete a CAPTCHA challenge to prove they are human." chống bot tự động chứ không xác minh đúng người sở hữu tài khoản.
Mở trang câu hỏi này →
Acookies
Bcookies-parser
Ccookie-body
Dcookie-value
Lời giải
Đáp án đúng: "cookies-parser". Phương án này gần nhất với middleware thật dùng để phân tích cookie trong Express, nhưng cần nói thẳng rằng tên gói chính xác trên npm là cookie-parser (không có chữ s): cài bằng npm install cookie-parser rồi gắn bằng app.use(cookieParser()), sau đó header Cookie của request được tách thành object req.cookies, và nếu truyền secret thì cookie đã ký nằm ở req.signedCookies. "cookies" chỉ là tên chung của dữ liệu, không phải middleware phân tích cookie của Express. "cookie-body" không tồn tại, nó trộn tên cookie với body-parser vốn để phân tích phần thân request. "cookie-value" cũng không phải middleware nào, chỉ gợi nhắc giá trị của một cookie.
Mở trang câu hỏi này →
30What does HTTPS stand for?4 lựa chọnTrung bình67% trả lời đúng
AHyperText Transfer Protocol Secure
BHyperText Transfer Protocol Simple
CHyperText Transfer Protocol Standard
DHyperText Transfer Protocol Script
Lời giải
Đáp án đúng: "HyperText Transfer Protocol Secure". HTTPS là HTTP chạy bên trong một kết nối được mã hoá bằng TLS (trước đây là SSL); chữ S cuối là Secure, nghĩa là an toàn: dữ liệu giữa trình duyệt và máy chủ được mã hoá, máy chủ chứng minh danh tính bằng chứng chỉ số, và nội dung không bị sửa lén trên đường truyền. Cổng mặc định của HTTPS là 443, của HTTP là 80. Trong Node.js có thể dựng máy chủ HTTPS bằng module https với khoá và chứng chỉ. "HyperText Transfer Protocol Simple" sai vì HTTPS không phải bản rút gọn của HTTP mà là HTTP cộng thêm lớp bảo mật. "HyperText Transfer Protocol Standard" sai vì HTTP vốn đã là giao thức chuẩn, chữ S không mang nghĩa chuẩn hoá. "HyperText Transfer Protocol Script" sai vì giao thức này không liên quan tới ngôn ngữ kịch bản nào.
Mở trang câu hỏi này →
Aapp.get('/logout', (req, res) => { req.session.destroy((err) => { if (err) { console.log(err); } else { res.redirect('/login'); } }); });
Bapp.get('/logout', (req, res) => { req.session.delete(); res.redirect('/login'); });
Capp.get('/logout', (req, res) => { req.session.remove(); res.redirect('/login'); });
Dapp.get('/logout', (req, res) => { req.session.invalidate(); res.redirect('/login'); });
Lời giải

Đáp án đúng: "

Lời giải
app.get('/logout', (req, res) => {
  req.session.destroy((err) => {
    if (err) {
      console.log(err);
    }
    else {
      res.redirect('/login');
    }
  }
  );
}

);". Gói express-session gắn vào req.session một đối tượng Session có phương thức destroy(callback): nó xoá dữ liệu phiên khỏi store, bỏ req.session rồi mới gọi callback. Lần theo đoạn đúng: route GET /logout gọi destroy, chờ trong callback, nếu có err thì ghi log, nếu không mới chạy res.redirect('/login'), nên việc chuyển hướng chỉ xảy ra khi phiên đã thật sự bị huỷ. Đoạn gọi "req.session.delete()" sai vì Session của express-session không có phương thức delete, lệnh này ném TypeError trước khi kịp chuyển hướng. Đoạn gọi "req.session.remove()" cũng sai vì remove không nằm trong API của Session, kết quả là lỗi không phải hàm như trên. Đoạn gọi "req.session.invalidate()" mượn cách viết của HttpSession trong Java Servlet, mang sang Express thì không tồn tại; hơn nữa nó gọi res.redirect ngay mà không chờ store xoá xong.

Mở trang câu hỏi này →
A200
B404
C201
D500
Lời giải
Đáp án đúng: "201". Mã 201 Created báo yêu cầu đã thành công và tạo ra một tài nguyên mới, thường là phản hồi cho POST tạo bản ghi; API REST chuẩn còn kèm header Location trỏ tới tài nguyên mới hoặc trả chính tài nguyên trong body, trong Express viết res.status(201).json(doc). "200" là OK chung cho yêu cầu thành công, dùng được nhưng không nói rõ đã có tài nguyên mới được tạo. "404" là Not Found, tức tài nguyên được yêu cầu không tồn tại trên máy chủ. "500" là Internal Server Error, máy chủ gặp lỗi ngoài dự kiến khi xử lý, ví dụ một ngoại lệ chưa được bắt trong route handler.
Mở trang câu hỏi này →
Aexpress.static
Bexpress.json
Cexpress.session
Dexpress.urlencoded
Lời giải
Đáp án đúng: "express.session". Từ Express 4, các middleware dựng sẵn chỉ còn express.static (phục vụ tệp tĩnh), express.json và express.urlencoded (phân tích body JSON và form, có từ bản 4.16), cùng express.raw và express.text; quản lý phiên (session) đã được tách thành gói riêng express-session phải cài thêm và nạp qua require('express-session'), nên express.session không tồn tại. "express.static" là middleware có sẵn, phục vụ ảnh, CSS, JavaScript từ một thư mục. "express.json" là middleware có sẵn, đọc body có Content-Type application/json và gán vào req.body. "express.urlencoded" là middleware có sẵn, phân tích dữ liệu form dạng application/x-www-form-urlencoded. Cả express.static, express.json và express.urlencoded đều tích hợp sẵn nên không được chọn trong câu hỏi phủ định này.
Mở trang câu hỏi này →
34Which of the following Mongoose schema configurations enable validation of values?4 lựa chọnTrung bình67% trả lời đúng
Adefault: 18
Brequired: true
Cvalidate: {}
Dimmutable: true
Lời giải
Đáp án đúng: "validate: {}". Câu hỏi nói về kiểm tra giá trị: khai báo validate trong một trường của schema cho phép gắn hàm kiểm tra tuỳ ý, ví dụ validate với validator là hàm trả về true khi số điện thoại đúng định dạng và message là thông báo lỗi; Mongoose chạy hàm này trước khi save và từ chối document nếu giá trị không đạt. Cũng nên nói thẳng: "required: true" cũng là một validator dựng sẵn của Mongoose nên có người chọn nó, nhưng nó chỉ kiểm tra trường có giá trị hay không chứ không xét giá trị đó đúng hay sai, còn validate mới là cấu hình dành cho việc kiểm tra nội dung giá trị. "default: 18" chỉ gán giá trị mặc định khi trường bị bỏ trống, không kiểm tra gì. "immutable: true" khoá trường để không bị sửa sau khi document được tạo, đó là ràng buộc thay đổi chứ không phải kiểm tra tính hợp lệ của giá trị.
Mở trang câu hỏi này →
35What is Mongoose in Node.js?4 lựa chọnDễ
AA database
BA MongoDB object modeling tool
CAn HTTP client
DA web server framework
Lời giải
Đáp án đúng: "A MongoDB object modeling tool". Mongoose là thư viện ODM (Object Data Modeling, mô hình hoá dữ liệu dạng đối tượng) cho MongoDB trên Node.js: định nghĩa Schema có kiểu, ràng buộc, giá trị mặc định, rồi biên dịch thành Model với các hàm find, save, populate, kèm kiểm tra hợp lệ (validation) và middleware (hook). "A database" sai vì Mongoose không tự lưu dữ liệu; nó chỉ là lớp trung gian gửi lệnh tới máy chủ MongoDB thật. "An HTTP client" sai vì gửi request HTTP là việc của axios hay fetch; Mongoose nói chuyện với MongoDB qua driver và giao thức riêng của MongoDB. "A web server framework" sai vì dựng máy chủ web và định tuyến là việc của Express, NestJS hay Hono; Mongoose chỉ phụ trách tầng dữ liệu.
Mở trang câu hỏi này →
A[String]
B{ type: String }
C{ type: Schema.Types.ObjectId, ref: 'SubDoc' }
D[Schema.Types.Mixed]
Lời giải
Đáp án đúng: "{ type: Schema.Types.ObjectId, ref: 'SubDoc' }". Muốn một trường trỏ tới tài liệu ở collection khác, Mongoose lưu giá trị _id của tài liệu đó với kiểu Schema.Types.ObjectId và khai báo ref là tên model được tham chiếu, ở đây là SubDoc; nhờ ref, populate() biết phải truy vấn model nào để thay ObjectId bằng tài liệu đầy đủ. "[String]" khai báo một mảng chuỗi thường, không có liên kết tới model nào. "{ type: String }" là một trường chuỗi đơn, có thể chứa id dạng văn bản nhưng không có ref nên populate không dùng được. "[Schema.Types.Mixed]" là mảng giá trị tuỳ ý, Mongoose không kiểm tra kiểu và không biết trỏ tới model nào. Lưu ý cách gọi reference subdocument trong câu hỏi thực chất là tham chiếu, khác với subdocument nhúng trực tiếp bằng một schema con.
Mở trang câu hỏi này →
Adefault: 18
Brequired: true
Cvalidate: {}
Dimmutable: true
Lời giải
Đáp án đúng: "default: 18". Trong định nghĩa schema Mongoose, tuỳ chọn default gán giá trị mặc định cho trường khi tài liệu mới được tạo mà không cung cấp trường đó, ví dụ age: { type: Number, default: 18 } làm mọi người dùng mới thiếu age có age bằng 18; default còn nhận một hàm như Date.now để tính lúc tạo. "required: true" là validator bắt buộc phải có giá trị, thiếu thì save() báo lỗi chứ không tự điền. "validate: {}" khai báo hàm kiểm tra tuỳ chỉnh để chấp nhận hay từ chối giá trị, không sinh giá trị nào. "immutable: true" khiến trường không đổi được sau khi tài liệu đã lưu lần đầu, cũng không đặt giá trị mặc định.
Mở trang câu hỏi này →
APopulation is used to join data from multiple collections.
BPopulation is used to update multiple documents.
CPopulation can be done using the populate() method in a query.
DPopulation requires the use of schemas only.
Lời giải
Đáp án đúng gồm hai ý: "Population is used to join data from multiple collections." và "Population can be done using the populate() method in a query.". Population là cơ chế Mongoose thay một trường lưu ObjectId tham chiếu (khai báo kiểu ObjectId kèm ref tới model khác) bằng chính document được tham chiếu. Ví dụ Post.find().populate('author') trả về bài viết kèm cả đối tượng người dùng thay vì chỉ id; Mongoose thực hiện bằng truy vấn phụ tới collection kia rồi ghép kết quả, nên về tác dụng nó giống phép join dữ liệu giữa nhiều collection. "Population is used to update multiple documents." sai vì populate chỉ đọc và ghép dữ liệu khi truy vấn; cập nhật nhiều document là việc của updateMany(). "Population requires the use of schemas only." sai vì thứ populate cần là một trường tham chiếu và biết model đích; thông tin đó thường đặt trong schema bằng ref, nhưng cũng có thể truyền trực tiếp qua tuỳ chọn model khi gọi populate(), nên không phải cứ có schema là đủ hay chỉ có schema mới làm được.
Mở trang câu hỏi này →
AfindJoin()
Bpopulate()
CjoinWith()
DrefFetch()
Lời giải
Đáp án đúng: "populate()". Khi schema khai báo một trường kiểu Schema.Types.ObjectId kèm ref trỏ tới model User, truy vấn như Post.find().populate('author') sẽ chạy thêm truy vấn vào collection users và thay mỗi ObjectId bằng tài liệu tương ứng; đây là cách Mongoose nạp tài liệu được tham chiếu. "findJoin()" không có trong API Mongoose, tên này chỉ ghép từ find với JOIN của SQL. "joinWith()" cũng không tồn tại; muốn nối ngay ở phía máy chủ MongoDB thì dùng stage $lookup trong aggregate(), không phải hàm này. "refFetch()" được ghép từ chữ ref của khai báo schema, Mongoose không có hàm nào mang tên đó, gọi nó sẽ báo lỗi không phải hàm.
Mở trang câu hỏi này →
40Which statements correctly describe the benefits of Mongoose population?4 lựa chọnTrung bình67% trả lời đúng
APopulation makes the code cleaner and more intuitive when dealing with related data.
BPopulation makes it harder to read and understand the code.
CPopulation reduces the need for multiple round trips to the database.
DPopulation can only be used with single-level documents.
Lời giải
Đáp án đúng gồm hai ý: "Population makes the code cleaner and more intuitive when dealing with related data." và "Population reduces the need for multiple round trips to the database.". Population là cơ chế Mongoose tự thay các ObjectId có ref bằng tài liệu được tham chiếu, nên chỉ cần một dòng như Post.find().populate('author') thay vì tự viết vòng lặp lấy từng tác giả, mã ngắn và dễ hiểu hơn. Cần nói thẳng: populate không phải phép join trong một truy vấn, phía sau Mongoose vẫn chạy thêm truy vấn phụ, nhưng nó gom mọi id cần lấy vào một truy vấn dạng $in cho mỗi đường dẫn, nên số lượt đi về ít hơn hẳn so với tự truy vấn từng tài liệu bằng tay; theo nghĩa đó ý giảm round trip vẫn đúng. "Population makes it harder to read and understand the code." ngược với lợi ích vừa nêu. "Population can only be used with single-level documents." sai vì Mongoose hỗ trợ populate nhiều cấp bằng tuỳ chọn populate lồng nhau, ví dụ điền cả author lẫn bạn bè của author.
Mở trang câu hỏi này →