Laravel Lighthouse如何在启用EnsureXHR中间件时实现文件上传?
保留EnsureXHR中间件实现Lighthouse GraphQL文件上传的解决方案
问题背景
按照Lighthouse v6官方文档配置GraphQL文件上传:
- 定义上传Mutation:
type Mutation { upload(file: Upload!): String }
- 编写
Upload解析类:
final readonly class Upload { /** @param array{} $args */ public function __invoke(null $_, array $args) { dd($args); } }
- 编写测试用例使用
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
相关产品推荐
相关产品推荐

