From 1cf8cb975594aef9a16dd088fd56a1bc9cd7ad00 Mon Sep 17 00:00:00 2001 From: kunlongli <16629885+cnlkl@users.noreply.github.com> Date: Thu, 7 Dec 2023 18:04:16 +0800 Subject: [PATCH] =?UTF-8?q?feat:=20=E6=8F=90=E9=AB=98SVN-PROXY=E8=B6=85?= =?UTF-8?q?=E6=97=B6=E6=97=B6=E9=97=B4=20#1535=20(#1536)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../service/util/proxy/HttpProxyUtil.kt | 75 ++++++++++--------- .../git/interceptor/ProxyInterceptor.kt | 10 ++- .../bkrepo/lfs/service/ObjectService.kt | 2 +- .../interceptor/ChangeAncestorProxyHandler.kt | 2 +- .../svn/interceptor/ProxyInterceptor.kt | 10 ++- 5 files changed, 57 insertions(+), 42 deletions(-) diff --git a/src/backend/common/common-service/src/main/kotlin/com/tencent/bkrepo/common/service/util/proxy/HttpProxyUtil.kt b/src/backend/common/common-service/src/main/kotlin/com/tencent/bkrepo/common/service/util/proxy/HttpProxyUtil.kt index 9558352105..e7f7189f2d 100644 --- a/src/backend/common/common-service/src/main/kotlin/com/tencent/bkrepo/common/service/util/proxy/HttpProxyUtil.kt +++ b/src/backend/common/common-service/src/main/kotlin/com/tencent/bkrepo/common/service/util/proxy/HttpProxyUtil.kt @@ -6,6 +6,7 @@ import com.tencent.bkrepo.common.api.util.BasicAuthUtils import com.tencent.bkrepo.common.service.util.okhttp.HttpClientBuilderFactory import okhttp3.MediaType import okhttp3.MediaType.Companion.toMediaTypeOrNull +import okhttp3.OkHttpClient import okhttp3.Request import okhttp3.RequestBody import okhttp3.Response @@ -15,10 +16,10 @@ import org.slf4j.LoggerFactory import javax.servlet.http.HttpServletRequest import javax.servlet.http.HttpServletResponse -object HttpProxyUtil { - private val logger = LoggerFactory.getLogger(HttpProxyUtil::class.java) - private val client = HttpClientBuilderFactory.create().build() - private val defaultProxyCallHandler = DefaultProxyCallHandler() +class HttpProxyUtil( + private val client: OkHttpClient = HttpClientBuilderFactory.create().build(), + private val defaultProxyCallHandler: ProxyCallHandler = DefaultProxyCallHandler() +) { fun proxy( proxyRequest: HttpServletRequest, proxyResponse: HttpServletResponse, @@ -46,37 +47,6 @@ object HttpProxyUtil { proxyCallHandler.after(proxyRequest, proxyResponse, newResponse) } - fun HttpServletRequest.headers(): Map { - val headers = mutableMapOf() - val headerNames = this.headerNames - while (headerNames.hasMoreElements()) { - val headerName = headerNames.nextElement() - headers[headerName] = this.getHeader(headerName) - } - return headers - } - - fun HttpServletRequest.body(): RequestBody? { - val isChunked = headers()[HttpHeaders.TRANSFER_ENCODING] == "chunked" - if (this.contentLengthLong <= 0 && !isChunked) { - return null - } - val mediaType = this.contentType?.toMediaTypeOrNull() - val inputStream = this.inputStream - val contentLength = this.contentLengthLong - return object : RequestBody() { - override fun contentType(): MediaType? = mediaType - - override fun contentLength(): Long = contentLength - - override fun writeTo(sink: BufferedSink) { - inputStream.source().use { - sink.writeAll(it) - } - } - } - } - private fun HttpServletRequest.accessLog(upRes: Response) { var user = "-" if (getHeader(HttpHeaders.AUTHORIZATION).orEmpty().startsWith(BASIC_AUTH_PREFIX)) { @@ -92,4 +62,39 @@ object HttpProxyUtil { "user:$user up_status: ${upRes.code} ms:$requestTime up:$url agent:$httpUserAgent $requestBodyBytes", ) } + + companion object { + private val logger = LoggerFactory.getLogger(HttpProxyUtil::class.java) + + fun HttpServletRequest.headers(): Map { + val headers = mutableMapOf() + val headerNames = this.headerNames + while (headerNames.hasMoreElements()) { + val headerName = headerNames.nextElement() + headers[headerName] = this.getHeader(headerName) + } + return headers + } + + fun HttpServletRequest.body(): RequestBody? { + val isChunked = headers()[HttpHeaders.TRANSFER_ENCODING] == "chunked" + if (this.contentLengthLong <= 0 && !isChunked) { + return null + } + val mediaType = this.contentType?.toMediaTypeOrNull() + val inputStream = this.inputStream + val contentLength = this.contentLengthLong + return object : RequestBody() { + override fun contentType(): MediaType? = mediaType + + override fun contentLength(): Long = contentLength + + override fun writeTo(sink: BufferedSink) { + inputStream.source().use { + sink.writeAll(it) + } + } + } + } + } } diff --git a/src/backend/git/biz-git/src/main/kotlin/com/tencent/bkrepo/git/interceptor/ProxyInterceptor.kt b/src/backend/git/biz-git/src/main/kotlin/com/tencent/bkrepo/git/interceptor/ProxyInterceptor.kt index 633f10f057..4d9ff434e6 100644 --- a/src/backend/git/biz-git/src/main/kotlin/com/tencent/bkrepo/git/interceptor/ProxyInterceptor.kt +++ b/src/backend/git/biz-git/src/main/kotlin/com/tencent/bkrepo/git/interceptor/ProxyInterceptor.kt @@ -9,15 +9,17 @@ import com.tencent.bkrepo.common.artifact.pojo.configuration.proxy.ProxyConfigur import com.tencent.bkrepo.common.artifact.repository.context.ArtifactContextHolder import com.tencent.bkrepo.common.service.util.proxy.DefaultProxyCallHandler import com.tencent.bkrepo.common.service.util.proxy.HttpProxyUtil +import okhttp3.Response +import org.slf4j.LoggerFactory import org.springframework.web.servlet.HandlerInterceptor import org.springframework.web.servlet.HandlerMapping import javax.servlet.http.HttpServletRequest import javax.servlet.http.HttpServletResponse -import okhttp3.Response -import org.slf4j.LoggerFactory class ProxyInterceptor : HandlerInterceptor { private val lfsProxyHandler = LfsProxyHandler() + private val httpProxyUtil = HttpProxyUtil() + override fun preHandle(request: HttpServletRequest, response: HttpServletResponse, handler: Any): Boolean { request.getAttribute(HandlerMapping.URI_TEMPLATE_VARIABLES_ATTRIBUTE) ?: return false val repo = ArtifactContextHolder.getRepoDetail()!! @@ -31,9 +33,9 @@ class ProxyInterceptor : HandlerInterceptor { val configuration = repo.configuration as ProxyConfiguration val proxyUrl = configuration.proxy.url if (request.requestURI.endsWith(LFS_BATCH_URI)) { - HttpProxyUtil.proxy(request, response, proxyUrl, gitRepoKey, lfsProxyHandler) + httpProxyUtil.proxy(request, response, proxyUrl, gitRepoKey, lfsProxyHandler) } else { - HttpProxyUtil.proxy(request, response, proxyUrl, gitRepoKey) + httpProxyUtil.proxy(request, response, proxyUrl, gitRepoKey) } return false diff --git a/src/backend/lfs/biz-lfs/src/main/kotlin/com/tencent/bkrepo/lfs/service/ObjectService.kt b/src/backend/lfs/biz-lfs/src/main/kotlin/com/tencent/bkrepo/lfs/service/ObjectService.kt index 1b082ba2ca..ef9af25b09 100644 --- a/src/backend/lfs/biz-lfs/src/main/kotlin/com/tencent/bkrepo/lfs/service/ObjectService.kt +++ b/src/backend/lfs/biz-lfs/src/main/kotlin/com/tencent/bkrepo/lfs/service/ObjectService.kt @@ -53,7 +53,7 @@ import com.tencent.bkrepo.common.security.util.SecurityUtils import com.tencent.bkrepo.common.service.util.HeaderUtils import com.tencent.bkrepo.common.service.util.HttpContextHolder import com.tencent.bkrepo.common.service.util.okhttp.HttpClientBuilderFactory -import com.tencent.bkrepo.common.service.util.proxy.HttpProxyUtil.headers +import com.tencent.bkrepo.common.service.util.proxy.HttpProxyUtil.Companion.headers import com.tencent.bkrepo.common.storage.innercos.http.toRequestBody import com.tencent.bkrepo.lfs.artifact.LfsArtifactInfo import com.tencent.bkrepo.lfs.artifact.LfsProperties diff --git a/src/backend/svn/biz-svn/src/main/kotlin/com/tencent/bkrepo/svn/interceptor/ChangeAncestorProxyHandler.kt b/src/backend/svn/biz-svn/src/main/kotlin/com/tencent/bkrepo/svn/interceptor/ChangeAncestorProxyHandler.kt index 620f91a5e7..a4423be299 100644 --- a/src/backend/svn/biz-svn/src/main/kotlin/com/tencent/bkrepo/svn/interceptor/ChangeAncestorProxyHandler.kt +++ b/src/backend/svn/biz-svn/src/main/kotlin/com/tencent/bkrepo/svn/interceptor/ChangeAncestorProxyHandler.kt @@ -30,7 +30,7 @@ package com.tencent.bkrepo.svn.interceptor import com.tencent.bkrepo.common.api.constant.HttpHeaders import com.tencent.bkrepo.common.api.constant.ensurePrefix import com.tencent.bkrepo.common.service.util.proxy.DefaultProxyCallHandler -import com.tencent.bkrepo.common.service.util.proxy.HttpProxyUtil.headers +import com.tencent.bkrepo.common.service.util.proxy.HttpProxyUtil.Companion.headers import com.tencent.bkrepo.svn.config.SvnProperties import okhttp3.HttpUrl import okhttp3.MediaType.Companion.toMediaType diff --git a/src/backend/svn/biz-svn/src/main/kotlin/com/tencent/bkrepo/svn/interceptor/ProxyInterceptor.kt b/src/backend/svn/biz-svn/src/main/kotlin/com/tencent/bkrepo/svn/interceptor/ProxyInterceptor.kt index 5a625e914a..12d3fc0595 100644 --- a/src/backend/svn/biz-svn/src/main/kotlin/com/tencent/bkrepo/svn/interceptor/ProxyInterceptor.kt +++ b/src/backend/svn/biz-svn/src/main/kotlin/com/tencent/bkrepo/svn/interceptor/ProxyInterceptor.kt @@ -31,14 +31,22 @@ import com.tencent.bkrepo.common.artifact.pojo.RepositoryCategory import com.tencent.bkrepo.common.artifact.pojo.configuration.proxy.ProxyConfiguration import com.tencent.bkrepo.common.artifact.repository.context.ArtifactContextHolder import com.tencent.bkrepo.common.service.util.HttpContextHolder +import com.tencent.bkrepo.common.service.util.okhttp.HttpClientBuilderFactory import com.tencent.bkrepo.common.service.util.proxy.HttpProxyUtil import com.tencent.bkrepo.common.service.util.proxy.ProxyCallHandler import com.tencent.bkrepo.svn.utils.SvnProxyHelper.getRepoId import org.springframework.web.servlet.HandlerInterceptor +import java.util.concurrent.TimeUnit import javax.servlet.http.HttpServletRequest import javax.servlet.http.HttpServletResponse class ProxyInterceptor(private val proxyHandler: ProxyCallHandler) : HandlerInterceptor { + private val client = HttpClientBuilderFactory.create() + .readTimeout(15, TimeUnit.MINUTES) + .writeTimeout(15, TimeUnit.MINUTES) + .build() + private val httpProxyUtil = HttpProxyUtil(client) + override fun preHandle(request: HttpServletRequest, response: HttpServletResponse, handler: Any): Boolean { val repositoryId = getRepoId(request) ?: return false val repo = ArtifactContextHolder.getRepoDetail(repositoryId) @@ -50,7 +58,7 @@ class ProxyInterceptor(private val proxyHandler: ProxyCallHandler) : HandlerInte val configuration = repo.configuration as ProxyConfiguration val proxyUrl = configuration.proxy.url val prefix = "/${repo.projectId}/${repo.name}" - HttpProxyUtil.proxy( + httpProxyUtil.proxy( HttpContextHolder.getRequest(), HttpContextHolder.getResponse(), proxyUrl,