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

基于NestJS的GraphQL Mutation调用TMDB评分接口返回404错误

解决NestJS中调用TMDB电影评分Patch接口的404错误

问题概述

使用NestJS(Schema First模式)结合GraphQL和TMDB API开发电影网站,实现用户提交电影评分的Patch请求时,遇到GraphQL返回404 Not Found错误。错误详情显示请求URL为https://api.themoviedb.org/3/movie/370172/rating/8/?api_key=_______,TMDB返回状态码34(资源不存在)。

错误分析

  1. URL格式错误:错误地将rating值(如8)拼接到了接口路径中(/rating/8/),同时RESTDataSource的patch方法第一个参数应为相对路径,不应重复拼接baseURL,导致TMDB无法识别请求资源。
  2. 请求体与请求选项混淆:错误地将请求体定义为继承PatchRequest类型,PatchRequest是用于配置请求选项(如headers、params)的类型,而非请求体类型。
  3. 缺少必要请求头:TMDB的评分接口要求请求头包含Content-Type: application/json,否则可能导致接口解析失败。

修复步骤

1. 修正URL路径

移除patch路径中的baseURL,使用相对路径,并通过统一配置传递API key:

  • 已设置baseURL = "https://api.themoviedb.org/3/",因此patch路径只需写movie/${id}/rating
  • 通过willSendRequest方法统一添加API key到请求参数,避免重复拼接

2. 正确区分请求体与请求选项

单独定义请求体类型,将请求选项(如headers、认证参数)作为patch方法的第三个参数传递。

3. 添加必要请求头与认证信息

确保请求头包含Content-Type: application/json;TMDB电影评分接口要求用户会话验证,需传递session_id或guest_session_id(可通过TMDB创建会话接口获取)。

完整代码示例

ratings.service.ts

import { Injectable } from '@nestjs/common';
import { RESTDataSource } from '@apollo/datasource-rest';

// 定义评分请求体类型
interface RatingRequestBody {
  value: number;
}

@Injectable()
export class RatingsService extends RESTDataSource {
  constructor() {
    super();
    this.baseURL = 'https://api.themoviedb.org/3/';
  }

  // 统一添加API key到请求参数
  willSendRequest(request: any) {
    request.params.set('api_key', process.env.API_KEY);
    // 若需用户认证,添加会话ID(示例:从上下文获取用户会话)
    // request.params.set('session_id', this.context.sessionId);
  }

  async addMovieRating(id: string, rating: number) {
    // 验证rating范围(TMDB要求0.5-10,步长0.5)
    if (rating < 0.5 || rating > 10 || rating % 0.5 !== 0) {
      throw new Error('评分必须在0.5-10之间,且为0.5的整数倍');
    }

    const requestBody: RatingRequestBody = {
      value: rating,
    };

    // 发送Patch请求:相对路径 + 请求体 + 请求选项
    const response = await this.patch(
      `movie/${id}/rating`,
      requestBody,
      {
        headers: {
          'Content-Type': 'application/json',
        },
      },
    );

    return response;
  }
}

ratings.resolver.ts

import { Args, Mutation, Resolver } from '@nestjs/graphql';
import { RatingsService } from './ratings.service';

@Resolver()
export class RatingsResolver {
  constructor(private readonly ratingsService: RatingsService) {}

  @Mutation()
  async addMovieRatings(
    @Args('id') id: string,
    @Args('rating') rating: number,
  ) {
    try {
      const tmdbResponse = await this.ratingsService.addMovieRating(id, rating);
      // 转换TMDB返回格式适配GraphQL Schema
      return {
        code: 200,
        success: tmdbResponse.success,
        message: tmdbResponse.status_message || '评分提交成功',
        rating: { id, rating },
      };
    } catch (error) {
      // 捕获错误并返回符合Schema的格式
      return {
        code: error.response?.status || 500,
        success: false,
        message: error.message || '评分提交失败',
        rating: null,
      };
    }
  }
}

schema.graphql

type Rating {
  id: ID!
  rating: Float!
}

type AddMovieRatings {
  code: Int!
  success: Boolean!
  message: String!
  rating: Rating
}

type Mutation {
  addMovieRatings(id: ID!, rating: Float!): AddMovieRatings!
}

额外注意事项

  • 用户认证:TMDB电影评分接口必须验证用户会话,需提前通过TMDB接口获取session_id或guest_session_id并传入请求。
  • 参数校验:严格控制rating值范围,避免因参数无效导致接口返回错误。
  • 错误捕获:在Resolver层统一处理服务端错误,返回友好的错误信息给前端。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.10 10:24:55