package com.ard.web.controller.sample.media; import io.swagger.annotations.Api; import io.swagger.annotations.ApiOperation; import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Value; import org.springframework.http.*; import org.springframework.util.StreamUtils; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; import org.springframework.web.client.RestTemplate; import javax.servlet.http.HttpServletRequest; import java.io.IOException; import java.net.URI; import java.net.URLDecoder; import java.nio.charset.StandardCharsets; import java.util.Collections; import java.util.Enumeration; @Slf4j @Api(tags = "机场上传minio") @RestController @RequestMapping("/minioTransfer") public class MinioGeneralProxyController { @Value("${oss.endpoint}") private String minioServerEndpoint; private final RestTemplate restTemplate; private static final String BASE_PREFIX = "/minioTransfer"; public MinioGeneralProxyController(RestTemplate restTemplate) { this.restTemplate = restTemplate; } @ApiOperation("MinIO原生接口代理(无感中转)") @RequestMapping(value = "/**") public ResponseEntity proxyAllRequest(HttpServletRequest request) { try { // 1. 解析请求基础信息 String methodStr = request.getMethod(); String rawUri = URLDecoder.decode(request.getRequestURI(), StandardCharsets.UTF_8); String queryString = request.getQueryString(); log.info("转发请求 | 方法:{} | URI:{} | 参数:{}", methodStr, rawUri, queryString); // 2. 构建MinIO目标地址 String targetPath = rawUri.substring(BASE_PREFIX.length()); StringBuilder targetUrl = new StringBuilder(minioServerEndpoint); targetUrl.append(targetPath); if (queryString != null && !queryString.isBlank()) { targetUrl.append("?").append(queryString); } URI uri = URI.create(targetUrl.toString()); // 3. 转换为Spring标准HttpMethod(核心修复点) HttpMethod httpMethod = HttpMethod.valueOf(methodStr); // 4. 复制请求头+请求体 HttpHeaders headers = copyRequestHeaders(request); byte[] requestBody = extractRequestBody(request); HttpEntity requestEntity = new HttpEntity<>(requestBody, headers); // 5. 修复exchange方法调用,匹配Spring官方重载方法 ResponseEntity response = restTemplate.exchange( uri, httpMethod, requestEntity, byte[].class ); log.info("转发成功 | 目标地址:{} | 状态码:{}", targetUrl, response.getStatusCode()); // 原样回传所有响应信息 return new ResponseEntity<>( response.getBody(), response.getHeaders(), response.getStatusCode() ); } catch (Exception e) { log.error("代理转发执行异常", e); return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR) .body(("代理服务异常:" + e.getMessage()).getBytes(StandardCharsets.UTF_8)); } } /** * 透传所有请求头 */ private HttpHeaders copyRequestHeaders(HttpServletRequest request) { HttpHeaders headers = new HttpHeaders(); Enumeration headerNames = request.getHeaderNames(); if (headerNames == null) { return headers; } while (headerNames.hasMoreElements()) { String name = headerNames.nextElement(); Enumeration values = request.getHeaders(name); headers.addAll(name, Collections.list(values)); } // 移除Host头,避免转发地址冲突 headers.remove(HttpHeaders.HOST); return headers; } /** * 读取请求体数据 */ private byte[] extractRequestBody(HttpServletRequest request) { try { return StreamUtils.copyToByteArray(request.getInputStream()); } catch (IOException e) { log.warn("读取请求体失败", e); return new byte[0]; } } }