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

Laravel Lighthouse如何在启用EnsureXHR中间件时实现文件上传?

保留EnsureXHR中间件实现Lighthouse GraphQL文件上传的解决方案

问题背景

按照Lighthouse v6官方文档配置GraphQL文件上传:

  1. 定义上传Mutation:
type Mutation { upload(file: Upload!): String }
  1. 编写Upload解析类:
final readonly class Upload
{
    /** @param  array{}  $args */
    public function __invoke(null $_, array $args)
    {
        dd($args);
    }
}
  1. 编写测试用例使用multipartGraphQL方法发送请求时,被EnsureXHR中间件拦截,抛出异常:
Content-Type multipart/form-data; is forbidden

该中间件默认禁止multipart/form-data等表单类型Content-Type,但关闭中间件并非期望方案。

解决方案

方案1:修改EnsureXHR中间件,允许GraphQL文件上传的multipart请求

在EnsureXHR中间件中添加例外逻辑,仅放行符合GraphQL文件上传规范的multipart/form-data请求:

public const FORM_CONTENT_TYPES = [
   'application/x-www-form-urlencoded',
   'text/plain',
];

public function handle(Request $request, Closure $next)
{
    $contentType = $request->header('Content-Type');

    // 判断是否为GraphQL文件上传的multipart请求
    $isGraphqlMultipartUpload = $request->is('graphql') // 匹配你的GraphQL路由路径
        && Str::startsWith($contentType, 'multipart/form-data')
        && $request->has('operations')
        && $request->has('map');

    // 仅拦截非GraphQL上传的表单类型请求
    if (! $isGraphqlMultipartUpload && Str::startsWith($contentType, static::FORM_CONTENT_TYPES)) {
        throw new BadRequestHttpException("Content-Type {$contentType} is forbidden");
    }

    return $next($request);
}

此方案既保留了中间件对普通表单请求的拦截,又允许合法的GraphQL文件上传请求。

方案2:给GraphQL路由单独排除EnsureXHR中间件

如果你的GraphQL路由独立配置,可以在路由定义中移除该中间件,仅针对GraphQL请求放行:

// 假设你的GraphQL路由定义如下
Route::post('/graphql', [GraphQLController::class, 'query'])
    ->middleware(
        array_filter(
            $yourMiddlewareArray, // 替换为实际使用的中间件数组
            fn ($middleware) => $middleware !== EnsureXHR::class
        )
    );

此方案更简洁,但会让所有GraphQL请求跳过EnsureXHR拦截,适合确认GraphQL路由本身已做其他安全校验的场景。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.08 13:34:51