You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何用Koa ctx.body实现多响应?登录API 404及ctx.body失效解决

Hey there! Let's figure out why you're hitting that 404 and having trouble with ctx.body not working. I've looked at your code, and there are a few key issues causing these problems—let's break them down and fix them step by step.

Key Issues in Your Code

  • Mixing async/await with callbacks: You're using a callback for ctx.app.pool.query, but since your route handler is an async function, Koa doesn't wait for the callback to finish before sending a response. That's why you get a 404—Koa thinks the request is done before your query and password check complete, so it sends a default 404 because ctx.body was never set in time.
  • Unhandled empty query result: When the email doesn't exist in the database, result is still a valid object (just with an empty rows array), so your else clause for if (result) never runs. This leaves ctx.body unset, leading to a 404.
  • Inconsistent async patterns: You're using await in some places but .then() for bcrypt.compare, which makes it harder to track when the response gets set and can lead to race conditions.

Fixing the Code

Let's rewrite your route handler to use consistent async/await (no callbacks!) and handle all edge cases properly:

router.post('/userLogin', async (ctx) => { 
  const { email, password } = ctx.request.body; 

  // Check for missing fields
  if (!email || !password) { 
    ctx.status = 400; 
    ctx.body = { status: 'error', message: 'Please fill all the fields' };
    return; // Important: stop execution here so we don't run the rest of the code
  } 

  try {
    // Use await for the query (pg's query returns a promise!)
    const result = await ctx.app.pool.query("SELECT * FROM users WHERE email = $1", [email]);

    // Check if any user was found
    if (result.rows.length === 0) {
      ctx.status = 400;
      ctx.body = { status: 'error', message: "Invalid email" };
      return;
    }

    // Use await for bcrypt.compare instead of .then()
    const isPasswordMatch = await bcrypt.compare(password, result.rows[0].password);

    if (isPasswordMatch) {
      ctx.status = 200;
      ctx.body = { 
        status: 'success', 
        message: "User login successfully", 
        data: result.rows[0] 
      };
    } else {
      ctx.status = 400;
      ctx.body = { status: 'error', message: "Incorrect password" };
    }
  } catch (err) {
    console.error(err);
    ctx.status = 500;
    ctx.body = { status: 'error', message: "Server error" };
  }
});

How to Handle Multiple Responses in Koa

Koa only allows one response per request—you can't send multiple responses. Instead, structure your code to cover all possible paths (success, missing fields, invalid credentials, server errors) and set ctx.body + ctx.status in each path. Use return after setting the response to make sure no further code runs that might overwrite the response.

Troubleshooting Steps to Fix 404 & ctx.body Issues

  • Verify route mounting: Make sure you've added the router to your Koa app with:
    app.use(router.routes());
    app.use(router.allowedMethods());
    
  • Check request URL: Ensure you're sending a POST request to exactly /userLogin (case-sensitive!)—a typo like /userlogin or /login will trigger a 404.
  • Log execution paths: Add console.log statements in each branch (e.g., console.log("Missing fields"), console.log("User found")) to confirm which parts of your code are running. This helps you spot if a branch is being skipped.
  • Avoid callback hell: Always use await for async operations (like database queries, bcrypt checks) instead of callbacks. This ensures Koa waits for your logic to finish before sending a response.
  • Handle all edge cases: Make sure every possible scenario (missing fields, invalid email, wrong password, server error) has a ctx.body and ctx.status set. No path should leave ctx.body undefined.

内容的提问来源于stack exchange,提问作者Daniyal Mughees

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.14 09:11:59