| New file |
| | |
| | | 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<byte[]> 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<byte[]> requestEntity = new HttpEntity<>(requestBody, headers); |
| | | |
| | | // 5. 修复exchange方法调用,匹配Spring官方重载方法 |
| | | ResponseEntity<byte[]> 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<String> headerNames = request.getHeaderNames(); |
| | | if (headerNames == null) { |
| | | return headers; |
| | | } |
| | | while (headerNames.hasMoreElements()) { |
| | | String name = headerNames.nextElement(); |
| | | Enumeration<String> 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]; |
| | | } |
| | | } |
| | | } |