前端访问后端,肯定会遇到跨域问题,可以很多种方式解决,比较常见的如nginx。但由于某些限制,可能并不好使用Nginx来解决,那就可以考虑让前端访问自己的A服务,再通过A服务访问目标接口,由A服务来进行转发请求。
const val PROXY_PREFIX = "/gitlab/proxy/"
@RestController
class GitlabProxyController {
@RequestMapping(value = ["$PROXY_PREFIX**"])
fun proxy(request: ServletRequest, response: ServletResponse) {
val req = request as HttpServletRequest
val resp = response as HttpServletResponse
val uri = URI(request.requestURI)
val query = request.queryString
var target: String = uri.path.replace(PROXY_PREFIX, "")
if (query != null && query != "" && query != "null") {
target = "$target?$query"
}
val targetPath = URI(target)
// 请求类型
val method = req.method
val httpMethod = HttpMethod.resolve(method) //method
// 请求头
val headers = parseRequestHeader(req) //header
// 请求体
val body = parseRequestBody(req)
// 封装发singhttp请求
val requestEntity: RequestEntity<*> =
RequestEntity<Any?>(body, headers, httpMethod, URI.create(API_URL + targetPath))
val restTemplate = RestTemplate()
// 编码格式转换
restTemplate.messageConverters[1] = StringHttpMessageConverter(StandardCharsets.UTF_8)
val result = restTemplate.exchange(requestEntity, String::class.java)
// 将转发请求得到的结果和响应头返回客户端
val resultBody = result.body
val resultHeaders = result.headers
val contentType = resultHeaders.contentType
if (contentType != null) {
resp.contentType = contentType.toString()
}
resp.characterEncoding = "UTF-8" // 在getWriterz之前执行,否则不生效
val writer = resp.writer
writer.write(resultBody)
writer.flush()
}
private fun parseRequestHeader(request: HttpServletRequest): MultiValueMap<String, String> {
val httpHeaders = HttpHeaders()
val headerNames: List<String> = Collections.list(request.headerNames)
for (headerName in headerNames) {
val headerValues: List<String> = Collections.list(request.getHeaders(headerName))
for (headerValue in headerValues) {
httpHeaders.add(headerName, headerValue)
}
}
return httpHeaders
}
/**
* request body
*
* @param request
* @return
* @throws IOException
*/
@Throws(IOException::class)
private fun parseRequestBody(request: HttpServletRequest): ByteArray {
val inputStream: InputStream = request.inputStream
return StreamUtils.copyToByteArray(inputStream)
}
}