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

Postman中PUT请求正常,Deno TypeScript的Fetch请求失败

问题:Postman可正常发送PUT请求,Deno Fresh应用中Fetch发起的同请求失败

我在Postman中发送PUT请求可以成功,但在Deno Fresh应用里用Fetch发起完全相同的PUT请求却失败了。已确认请求体中的key、wallet_address和signature都是非空字符串,但请求依旧失败。

前端Fetch请求代码

async function sendSignature() {
        const signer = provider.getSigner();
        const nonce = "asdf123492fd";
        const signatureSigned = await signer.signMessage(nonce);
        const headers = new Headers({
            'Content-Type': 'application/json'
          });
        const opts = {
            method: 'PUT',
            headers: headers,
            body: JSON.stringify({
                key: props.singleUser,
                wallet_address: walletAddrs,
                signature: signatureSigned
          })
        }
        console.log(opts.body);
        const rawPosts = await fetch('http://localhost:4000/users/kythis1', opts);
        console.log(rawPosts);
    }

后端相关代码

入口文件(Oak框架)

import { Application } from "https://deno.land/x/oak/mod.ts";
import { APP_HOST, APP_PORT } from "./config.js";
import router from "./routes.js";
import _404 from "./controllers/404.js";
import errorHandler from "./controllers/errorHandler.js";
import { oakCors } from "https://deno.land/x/cors/mod.ts";

const app = new Application();

app.use(oakCors()); // Enable CORS for All Routes
app.use(errorHandler);
app.use(router.routes());
app.use(router.allowedMethods());
app.use(_404);

console.log(`Listening on port:${APP_PORT}...`);

await app.listen(`${APP_HOST}:${APP_PORT}`);

PUT请求控制器

import User from "../db/database.js";

export default async ({ request, response }) => {
  if (!request.hasBody) {
    response.status = 400;
    response.body = { msg: "Invalid user data" };
    return;
  }

  const body = request.body();
  const {
    key, wallet_address, signature
  } = JSON.parse(await body.value);

  console.log(signature);

  if (!key) {
    response.status = 422;
    response.body = { msg: "Incorrect user data. Email and key are required" };
    return;
  }

  const foundUser = await User.where('key', '=', key).first();
  if (!foundUser) {
    response.status = 404;
    response.body = { msg: `User with key ${key} not found` };
    return;
  }
  foundUser.wallet_address = wallet_address;
  foundUser.updated_at = new Date();
  const updatedResp = await foundUser.update();

  response.body = { msg: "User updated", updatedResp };
};

路由配置

import { Router } from "https://deno.land/x/oak/mod.ts";

import getUsers from "./controllers/getUsers.js";
import getUserDetails from "./controllers/getUserDetails.js";
import createUser from "./controllers/createUser.js";
import updateUser from "./controllers/updateUser.js";
//import deleteUser from "./controllers/deleteUser.js";

const router = new Router();

router
  .get("/users", getUsers)
  .get("/users/:key", getUserDetails)
  .post("/users", createUser)
  .put("/users/:key", updateUser);
  
  //.delete("/users/:id", deleteUser);

export default router;

排查方向与解决方法

1. 路由参数与请求体key不匹配

后端PUT路由定义为/users/:key,意味着应该从URL参数获取用户标识,但当前控制器是从请求体读取key。Postman请求可能是将正确的key放在URL参数中,而前端Fetch的URL参数kythis1与请求体props.singleUser的值不一致,导致查询用户失败。

修正方案:
修改控制器,从路由参数获取key:

export default async ({ request, response }) => {
  if (!request.hasBody) {
    response.status = 400;
    response.body = { msg: "Invalid user data" };
    return;
  }

  // 从URL路由参数获取key
  const key = request.params.key;
  const body = request.body();
  // 仅从请求体读取其他字段
  const { wallet_address, signature } = JSON.parse(await body.value);

  console.log(signature);

  if (!key) {
    response.status = 422;
    response.body = { msg: "Incorrect user data. Key is required" };
    return;
  }

  const foundUser = await User.where('key', '=', key).first();
  if (!foundUser) {
    response.status = 404;
    response.body = { msg: `User with key ${key} not found` };
    return;
  }
  foundUser.wallet_address = wallet_address;
  foundUser.updated_at = new Date();
  const updatedResp = await foundUser.update();

  response.body = { msg: "User updated", updatedResp };
};

2. CORS预检请求未正确处理

虽然启用了oakCors(),但默认配置可能未允许PUT方法的预检请求。显式配置CORS规则:

app.use(oakCors({
  origin: "http://localhost:3000", // 替换为你的Deno Fresh应用地址
  methods: ["GET", "POST", "PUT", "DELETE", "OPTIONS"],
  allowedHeaders: ["Content-Type"],
}));

3. Fetch未处理HTTP错误状态码

Fetch API仅在网络错误时触发reject,HTTP错误状态码(如400、404)不会抛出异常,只会返回ok: false的响应。添加错误处理逻辑:

const rawPosts = await fetch('http://localhost:4000/users/kythis1', opts);
if (!rawPosts.ok) {
  const errorInfo = await rawPosts.json();
  console.error('请求失败:', rawPosts.status, errorInfo);
  return;
}
const responseData = await rawPosts.json();
console.log('请求成功:', responseData);

4. 请求体JSON解析异常

在后端控制器添加JSON解析错误捕获,避免因请求体格式问题导致失败:

const body = request.body();
let parsedBody;
try {
  parsedBody = JSON.parse(await body.value);
} catch (err) {
  response.status = 400;
  response.body = { msg: "Invalid JSON format in request body" };
  return;
}
const { wallet_address, signature } = parsedBody;

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.19 14:45:33