From 4dfcd96d8778e99f386a87ed99b6fe9ca6ee5b5c Mon Sep 17 00:00:00 2001 From: yaoxuwan Date: Wed, 21 Aug 2024 16:36:40 +0800 Subject: [PATCH] =?UTF-8?q?feat:=20=E6=94=AF=E6=8C=81websocket=20#2494?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/backend/build.gradle.kts | 1 + .../CustomMetricsPushAutoConfiguration.kt | 4 +- .../bkrepo/common/redis/RedisOperation.kt | 4 +- .../config/boot-config/build.gradle.kts | 1 + src/backend/settings.gradle.kts | 1 + .../websocket/biz-websocket/build.gradle.kts | 40 ++++++ .../websocket/config/WebSocketConfigurer.kt | 48 +++++++ .../websocket/config/WebSocketProperties.kt | 37 +++++ .../config/WebsocketConfiguration.kt | 116 ++++++++++++++++ .../WsThreadPoolTaskExeccutorConfiguration.kt | 65 +++++++++ .../websocket/constant/WebsocketKeys.kt | 33 +++++ .../controller/ClipboardController.kt | 52 +++++++ .../bkrepo/websocket/dispatch/Dispatcher.kt | 36 +++++ .../websocket/dispatch/TransferDispatch.kt | 54 ++++++++ .../dispatch/push/CopyPDUTransferPush.kt | 37 +++++ .../dispatch/push/PastePDUTransferPush.kt | 37 +++++ .../websocket/dispatch/push/TransferPush.kt | 33 +++++ .../exception/WebsocketExceptionHandler.kt | 48 +++++++ .../websocket/handler/SessionHandler.kt | 131 ++++++++++++++++++ ...SessionWebSocketHandlerDecoratorFactory.kt | 45 ++++++ .../listener/TransferPushListener.kt | 51 +++++++ .../bkrepo/websocket/pojo/fs/CopyPDU.kt | 40 ++++++ .../bkrepo/websocket/pojo/fs/PastePDU.kt | 36 +++++ .../websocket/service/ClipboardService.kt | 58 ++++++++ .../websocket/service/WebsocketService.kt | 63 +++++++++ .../bkrepo/websocket/util/HostUtils.kt | 84 +++++++++++ .../websocket/boot-websocket/build.gradle.kts | 34 +++++ .../bkrepo/websocket/WebsocketApplication.kt | 41 ++++++ .../src/main/resources/bootstrap.yml | 4 + src/backend/websocket/build.gradle.kts | 30 ++++ src/gateway/lua/router_srv.lua | 2 +- src/gateway/vhosts/bkrepo.websocket.conf | 46 ++++++ .../gateway#vhosts#bkrepo.server.conf | 3 + 33 files changed, 1310 insertions(+), 5 deletions(-) create mode 100644 src/backend/websocket/biz-websocket/build.gradle.kts create mode 100644 src/backend/websocket/biz-websocket/src/main/kotlin/com/tencent/bkrepo/websocket/config/WebSocketConfigurer.kt create mode 100644 src/backend/websocket/biz-websocket/src/main/kotlin/com/tencent/bkrepo/websocket/config/WebSocketProperties.kt create mode 100644 src/backend/websocket/biz-websocket/src/main/kotlin/com/tencent/bkrepo/websocket/config/WebsocketConfiguration.kt create mode 100644 src/backend/websocket/biz-websocket/src/main/kotlin/com/tencent/bkrepo/websocket/config/WsThreadPoolTaskExeccutorConfiguration.kt create mode 100644 src/backend/websocket/biz-websocket/src/main/kotlin/com/tencent/bkrepo/websocket/constant/WebsocketKeys.kt create mode 100644 src/backend/websocket/biz-websocket/src/main/kotlin/com/tencent/bkrepo/websocket/controller/ClipboardController.kt create mode 100644 src/backend/websocket/biz-websocket/src/main/kotlin/com/tencent/bkrepo/websocket/dispatch/Dispatcher.kt create mode 100644 src/backend/websocket/biz-websocket/src/main/kotlin/com/tencent/bkrepo/websocket/dispatch/TransferDispatch.kt create mode 100644 src/backend/websocket/biz-websocket/src/main/kotlin/com/tencent/bkrepo/websocket/dispatch/push/CopyPDUTransferPush.kt create mode 100644 src/backend/websocket/biz-websocket/src/main/kotlin/com/tencent/bkrepo/websocket/dispatch/push/PastePDUTransferPush.kt create mode 100644 src/backend/websocket/biz-websocket/src/main/kotlin/com/tencent/bkrepo/websocket/dispatch/push/TransferPush.kt create mode 100644 src/backend/websocket/biz-websocket/src/main/kotlin/com/tencent/bkrepo/websocket/exception/WebsocketExceptionHandler.kt create mode 100644 src/backend/websocket/biz-websocket/src/main/kotlin/com/tencent/bkrepo/websocket/handler/SessionHandler.kt create mode 100644 src/backend/websocket/biz-websocket/src/main/kotlin/com/tencent/bkrepo/websocket/handler/SessionWebSocketHandlerDecoratorFactory.kt create mode 100644 src/backend/websocket/biz-websocket/src/main/kotlin/com/tencent/bkrepo/websocket/listener/TransferPushListener.kt create mode 100644 src/backend/websocket/biz-websocket/src/main/kotlin/com/tencent/bkrepo/websocket/pojo/fs/CopyPDU.kt create mode 100644 src/backend/websocket/biz-websocket/src/main/kotlin/com/tencent/bkrepo/websocket/pojo/fs/PastePDU.kt create mode 100644 src/backend/websocket/biz-websocket/src/main/kotlin/com/tencent/bkrepo/websocket/service/ClipboardService.kt create mode 100644 src/backend/websocket/biz-websocket/src/main/kotlin/com/tencent/bkrepo/websocket/service/WebsocketService.kt create mode 100644 src/backend/websocket/biz-websocket/src/main/kotlin/com/tencent/bkrepo/websocket/util/HostUtils.kt create mode 100644 src/backend/websocket/boot-websocket/build.gradle.kts create mode 100644 src/backend/websocket/boot-websocket/src/main/kotlin/com/tencent/bkrepo/websocket/WebsocketApplication.kt create mode 100644 src/backend/websocket/boot-websocket/src/main/resources/bootstrap.yml create mode 100644 src/backend/websocket/build.gradle.kts create mode 100644 src/gateway/vhosts/bkrepo.websocket.conf diff --git a/src/backend/build.gradle.kts b/src/backend/build.gradle.kts index cc4a29f7a9..630ddcf8ef 100644 --- a/src/backend/build.gradle.kts +++ b/src/backend/build.gradle.kts @@ -88,6 +88,7 @@ allprojects { exclude(group = "log4j", module = "log4j") exclude(group = "org.slf4j", module = "slf4j-log4j12") exclude(group = "commons-logging", module = "commons-logging") + exclude(group = "org.springframework.boot", module = "spring-boot-starter-tomcat") } tasks.withType { diff --git a/src/backend/common/common-metrics-push/src/main/kotlin/com/tencent/bkrepo/common/metrics/CustomMetricsPushAutoConfiguration.kt b/src/backend/common/common-metrics-push/src/main/kotlin/com/tencent/bkrepo/common/metrics/CustomMetricsPushAutoConfiguration.kt index 9b001532fd..4b30537e63 100644 --- a/src/backend/common/common-metrics-push/src/main/kotlin/com/tencent/bkrepo/common/metrics/CustomMetricsPushAutoConfiguration.kt +++ b/src/backend/common/common-metrics-push/src/main/kotlin/com/tencent/bkrepo/common/metrics/CustomMetricsPushAutoConfiguration.kt @@ -101,10 +101,10 @@ class CustomMetricsPushAutoConfiguration { fun customMetricsExporter( drive: PrometheusDrive, prometheusProperties: PrometheusProperties, - scheduler: ThreadPoolTaskScheduler, + taskScheduler: ThreadPoolTaskScheduler, customPushConfig: CustomPushConfig, ): CustomMetricsExporter { - return CustomMetricsExporter(customPushConfig, CollectorRegistry(), drive, prometheusProperties, scheduler) + return CustomMetricsExporter(customPushConfig, CollectorRegistry(), drive, prometheusProperties, taskScheduler) } diff --git a/src/backend/common/common-redis/src/main/kotlin/com/tencent/bkrepo/common/redis/RedisOperation.kt b/src/backend/common/common-redis/src/main/kotlin/com/tencent/bkrepo/common/redis/RedisOperation.kt index e851e8475b..de21b92aa1 100644 --- a/src/backend/common/common-redis/src/main/kotlin/com/tencent/bkrepo/common/redis/RedisOperation.kt +++ b/src/backend/common/common-redis/src/main/kotlin/com/tencent/bkrepo/common/redis/RedisOperation.kt @@ -63,8 +63,8 @@ class RedisOperation(private val redisTemplate: RedisTemplate) { } } - fun delete(key: String) { - redisTemplate.delete(key) + fun delete(key: String): Boolean { + return redisTemplate.delete(key) } fun delete(keys: Collection) { diff --git a/src/backend/config/boot-config/build.gradle.kts b/src/backend/config/boot-config/build.gradle.kts index 01bbf7507b..516184f9fb 100644 --- a/src/backend/config/boot-config/build.gradle.kts +++ b/src/backend/config/boot-config/build.gradle.kts @@ -32,4 +32,5 @@ dependencies { implementation("org.springframework.cloud:spring-cloud-config-server:3.1.6") implementation("org.springframework.cloud:spring-cloud-starter-bootstrap:3.1.6") + implementation("io.undertow:undertow-servlet") } diff --git a/src/backend/settings.gradle.kts b/src/backend/settings.gradle.kts index 8792746a34..bbcf5dbafc 100644 --- a/src/backend/settings.gradle.kts +++ b/src/backend/settings.gradle.kts @@ -92,3 +92,4 @@ includeAll(":router-controller") includeAll(":media") includeAll(":common:common-metadata") includeAll(":common:common-service") +includeAll(":websocket") diff --git a/src/backend/websocket/biz-websocket/build.gradle.kts b/src/backend/websocket/biz-websocket/build.gradle.kts new file mode 100644 index 0000000000..8e10e0a113 --- /dev/null +++ b/src/backend/websocket/biz-websocket/build.gradle.kts @@ -0,0 +1,40 @@ +/* + * Tencent is pleased to support the open source community by making BK-CI 蓝鲸持续集成平台 available. + * + * Copyright (C) 2024 THL A29 Limited, a Tencent company. All rights reserved. + * + * BK-CI 蓝鲸持续集成平台 is licensed under the MIT license. + * + * A copy of the MIT License is included in this file. + * + * + * Terms of the MIT License: + * --------------------------------------------------- + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED " AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +dependencies { + api(project(":common:common-stream")) + api(project(":common:common-service")) + api(project(":common:common-artifact:artifact-service")) + implementation("org.springframework.boot:spring-boot-starter-websocket") + implementation("javax.websocket:javax.websocket-api") + implementation("io.undertow:undertow-servlet") + implementation("io.undertow:undertow-websockets-jsr") +} diff --git a/src/backend/websocket/biz-websocket/src/main/kotlin/com/tencent/bkrepo/websocket/config/WebSocketConfigurer.kt b/src/backend/websocket/biz-websocket/src/main/kotlin/com/tencent/bkrepo/websocket/config/WebSocketConfigurer.kt new file mode 100644 index 0000000000..892cb634f9 --- /dev/null +++ b/src/backend/websocket/biz-websocket/src/main/kotlin/com/tencent/bkrepo/websocket/config/WebSocketConfigurer.kt @@ -0,0 +1,48 @@ +/* + * Tencent is pleased to support the open source community by making BK-CI 蓝鲸持续集成平台 available. + * + * Copyright (C) 2024 THL A29 Limited, a Tencent company. All rights reserved. + * + * BK-CI 蓝鲸持续集成平台 is licensed under the MIT license. + * + * A copy of the MIT License is included in this file. + * + * + * Terms of the MIT License: + * --------------------------------------------------- + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated + * documentation files (the "Software"), to deal in the Software without restriction, including without limitation the + * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all copies or substantial portions of + * the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT + * LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN + * NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +package com.tencent.bkrepo.websocket.config + +import com.tencent.bkrepo.common.artifact.config.ArtifactConfigurerSupport +import com.tencent.bkrepo.common.artifact.pojo.RepositoryType +import com.tencent.bkrepo.common.artifact.repository.local.LocalRepository +import com.tencent.bkrepo.common.artifact.repository.remote.RemoteRepository +import com.tencent.bkrepo.common.artifact.repository.virtual.VirtualRepository +import com.tencent.bkrepo.common.security.http.core.HttpAuthSecurityCustomizer +import org.springframework.context.annotation.Configuration + +@Configuration +class WebSocketConfigurer : ArtifactConfigurerSupport() { + + override fun getRepositoryType() = RepositoryType.NONE + override fun getLocalRepository(): LocalRepository = object : LocalRepository() {} + override fun getRemoteRepository(): RemoteRepository = object : RemoteRepository() {} + override fun getVirtualRepository(): VirtualRepository = object : VirtualRepository() {} + + override fun getAuthSecurityCustomizer() = + HttpAuthSecurityCustomizer { httpAuthSecurity -> httpAuthSecurity.withPrefix("/websocket") } +} diff --git a/src/backend/websocket/biz-websocket/src/main/kotlin/com/tencent/bkrepo/websocket/config/WebSocketProperties.kt b/src/backend/websocket/biz-websocket/src/main/kotlin/com/tencent/bkrepo/websocket/config/WebSocketProperties.kt new file mode 100644 index 0000000000..79fe623d87 --- /dev/null +++ b/src/backend/websocket/biz-websocket/src/main/kotlin/com/tencent/bkrepo/websocket/config/WebSocketProperties.kt @@ -0,0 +1,37 @@ +/* + * Tencent is pleased to support the open source community by making BK-CI 蓝鲸持续集成平台 available. + * + * Copyright (C) 2024 THL A29 Limited, a Tencent company. All rights reserved. + * + * BK-CI 蓝鲸持续集成平台 is licensed under the MIT license. + * + * A copy of the MIT License is included in this file. + * + * + * Terms of the MIT License: + * --------------------------------------------------- + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated + * documentation files (the "Software"), to deal in the Software without restriction, including without limitation the + * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all copies or substantial portions of + * the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT + * LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN + * NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +package com.tencent.bkrepo.websocket.config + +import org.springframework.boot.context.properties.ConfigurationProperties + +@ConfigurationProperties("websocket") +data class WebSocketProperties( + var cacheLimit: Int = 3600, + var minThread: Int = 8, + var transfer: Boolean = false +) diff --git a/src/backend/websocket/biz-websocket/src/main/kotlin/com/tencent/bkrepo/websocket/config/WebsocketConfiguration.kt b/src/backend/websocket/biz-websocket/src/main/kotlin/com/tencent/bkrepo/websocket/config/WebsocketConfiguration.kt new file mode 100644 index 0000000000..4832a58839 --- /dev/null +++ b/src/backend/websocket/biz-websocket/src/main/kotlin/com/tencent/bkrepo/websocket/config/WebsocketConfiguration.kt @@ -0,0 +1,116 @@ +/* + * Tencent is pleased to support the open source community by making BK-CI 蓝鲸持续集成平台 available. + * + * Copyright (C) 2024 THL A29 Limited, a Tencent company. All rights reserved. + * + * BK-CI 蓝鲸持续集成平台 is licensed under the MIT license. + * + * A copy of the MIT License is included in this file. + * + * + * Terms of the MIT License: + * --------------------------------------------------- + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated + * documentation files (the "Software"), to deal in the Software without restriction, including without limitation the + * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all copies or substantial portions of + * the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT + * LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN + * NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +package com.tencent.bkrepo.websocket.config + +import com.tencent.bkrepo.common.security.http.jwt.JwtAuthProperties +import com.tencent.bkrepo.common.security.manager.AuthenticationManager +import com.tencent.bkrepo.websocket.constant.APP_ENDPOINT +import com.tencent.bkrepo.websocket.constant.USER_ENDPOINT +import com.tencent.bkrepo.websocket.dispatch.push.TransferPush +import com.tencent.bkrepo.websocket.handler.SessionWebSocketHandlerDecoratorFactory +import com.tencent.bkrepo.websocket.listener.TransferPushListener +import com.tencent.bkrepo.websocket.service.WebsocketService +import org.springframework.boot.context.properties.EnableConfigurationProperties +import org.springframework.context.annotation.Bean +import org.springframework.context.annotation.Configuration +import org.springframework.messaging.Message +import org.springframework.messaging.simp.config.ChannelRegistration +import org.springframework.messaging.simp.config.MessageBrokerRegistry +import org.springframework.scheduling.concurrent.ThreadPoolTaskScheduler +import org.springframework.web.socket.config.annotation.EnableWebSocketMessageBroker +import org.springframework.web.socket.config.annotation.StompEndpointRegistry +import org.springframework.web.socket.config.annotation.WebSocketMessageBrokerConfigurer +import org.springframework.web.socket.config.annotation.WebSocketTransportRegistration +import java.util.function.Consumer + +@Configuration +@EnableWebSocketMessageBroker +@EnableConfigurationProperties(WebSocketProperties::class) +class WebsocketConfiguration( + private val webSocketProperties: WebSocketProperties, + private val websocketService: WebsocketService, + private val jwtAuthProperties: JwtAuthProperties, + private val authenticationManager: AuthenticationManager, + private val taskScheduler: ThreadPoolTaskScheduler +) : WebSocketMessageBrokerConfigurer { + + override fun configureMessageBroker(config: MessageBrokerRegistry) { + config.setCacheLimit(webSocketProperties.cacheLimit) + config.enableSimpleBroker("/topic") + .setHeartbeatValue(longArrayOf(3000,3000)) + .setTaskScheduler(taskScheduler) + config.setApplicationDestinationPrefixes("/app") + } + + override fun registerStompEndpoints(registry: StompEndpointRegistry) { + registry.addEndpoint(USER_ENDPOINT, APP_ENDPOINT) + .setAllowedOriginPatterns("*") + registry.addEndpoint(USER_ENDPOINT, APP_ENDPOINT) + .setAllowedOriginPatterns("*") + .withSockJS() + } + + @Override + override fun configureClientInboundChannel(registration: ChannelRegistration) { + var defaultCorePoolSize = webSocketProperties.minThread + if (defaultCorePoolSize < Runtime.getRuntime().availableProcessors() * 2) { + defaultCorePoolSize = Runtime.getRuntime().availableProcessors() * 2 + } + registration.taskExecutor().corePoolSize(defaultCorePoolSize) + .maxPoolSize(defaultCorePoolSize * 2) + .keepAliveSeconds(60) + } + + @Override + override fun configureClientOutboundChannel(registration: ChannelRegistration) { + var defaultCorePoolSize = webSocketProperties.minThread + if (defaultCorePoolSize < Runtime.getRuntime().availableProcessors() * 2) { + defaultCorePoolSize = Runtime.getRuntime().availableProcessors() * 2 + } + registration.taskExecutor().corePoolSize(defaultCorePoolSize).maxPoolSize(defaultCorePoolSize * 2) + } + + override fun configureWebSocketTransport(registration: WebSocketTransportRegistration) { + registration.addDecoratorFactory(wsHandlerDecoratorFactory()) + super.configureWebSocketTransport(registration) + } + + @Bean + fun wsHandlerDecoratorFactory(): SessionWebSocketHandlerDecoratorFactory { + return SessionWebSocketHandlerDecoratorFactory( + websocketService = websocketService, + authenticationManager = authenticationManager, + jwtAuthProperties = jwtAuthProperties + ) + } + + @Bean + fun websocketTransferConsumer(transferPushListener: TransferPushListener): Consumer> { + return Consumer { transferPushListener.accept(it) } + } +} diff --git a/src/backend/websocket/biz-websocket/src/main/kotlin/com/tencent/bkrepo/websocket/config/WsThreadPoolTaskExeccutorConfiguration.kt b/src/backend/websocket/biz-websocket/src/main/kotlin/com/tencent/bkrepo/websocket/config/WsThreadPoolTaskExeccutorConfiguration.kt new file mode 100644 index 0000000000..9ac531f7d6 --- /dev/null +++ b/src/backend/websocket/biz-websocket/src/main/kotlin/com/tencent/bkrepo/websocket/config/WsThreadPoolTaskExeccutorConfiguration.kt @@ -0,0 +1,65 @@ +/* + * Tencent is pleased to support the open source community by making BK-CI 蓝鲸持续集成平台 available. + * + * Copyright (C) 2024 THL A29 Limited, a Tencent company. All rights reserved. + * + * BK-CI 蓝鲸持续集成平台 is licensed under the MIT license. + * + * A copy of the MIT License is included in this file. + * + * + * Terms of the MIT License: + * --------------------------------------------------- + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated + * documentation files (the "Software"), to deal in the Software without restriction, including without limitation the + * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all copies or substantial portions of + * the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT + * LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN + * NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +package com.tencent.bkrepo.websocket.config + +import org.springframework.boot.autoconfigure.task.TaskExecutionAutoConfiguration +import org.springframework.boot.task.TaskExecutorBuilder +import org.springframework.context.annotation.Bean +import org.springframework.context.annotation.Configuration +import org.springframework.context.annotation.Lazy +import org.springframework.context.annotation.Primary +import org.springframework.scheduling.annotation.AsyncAnnotationBeanPostProcessor +import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor + +/** + * Websocket会注册自定义的ThreadPoolTaskExecutor + * + * [org.springframework.messaging.simp.config.AbstractMessageBrokerConfiguration.clientInboundChannelExecutor] + * + * [org.springframework.messaging.simp.config.AbstractMessageBrokerConfiguration.clientOutboundChannelExecutor] + * + * [org.springframework.messaging.simp.config.AbstractMessageBrokerConfiguration.brokerChannelExecutor] + * + * 导致默认的ThreadPoolTaskExecutor不会实例化 + * + * [org.springframework.boot.autoconfigure.task.TaskExecutionAutoConfiguration.applicationTaskExecutor] + * + */ +@Configuration +class WsThreadPoolTaskExeccutorConfiguration { + + @Lazy + @Bean(name = [ + TaskExecutionAutoConfiguration.APPLICATION_TASK_EXECUTOR_BEAN_NAME, + AsyncAnnotationBeanPostProcessor.DEFAULT_TASK_EXECUTOR_BEAN_NAME + ]) + @Primary + fun applicationTaskExecutor(builder: TaskExecutorBuilder): ThreadPoolTaskExecutor { + return builder.build() + } +} diff --git a/src/backend/websocket/biz-websocket/src/main/kotlin/com/tencent/bkrepo/websocket/constant/WebsocketKeys.kt b/src/backend/websocket/biz-websocket/src/main/kotlin/com/tencent/bkrepo/websocket/constant/WebsocketKeys.kt new file mode 100644 index 0000000000..42d405be9b --- /dev/null +++ b/src/backend/websocket/biz-websocket/src/main/kotlin/com/tencent/bkrepo/websocket/constant/WebsocketKeys.kt @@ -0,0 +1,33 @@ +/* + * Tencent is pleased to support the open source community by making BK-CI 蓝鲸持续集成平台 available. + * + * Copyright (C) 2019 THL A29 Limited, a Tencent company. All rights reserved. + * + * BK-CI 蓝鲸持续集成平台 is licensed under the MIT license. + * + * A copy of the MIT License is included in this file. + * + * + * Terms of the MIT License: + * --------------------------------------------------- + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated + * documentation files (the "Software"), to deal in the Software without restriction, including without limitation the + * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all copies or substantial portions of + * the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT + * LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN + * NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +package com.tencent.bkrepo.websocket.constant + +const val USER_ENDPOINT = "/ws/user" +const val APP_ENDPOINT = "/ws/app" + +const val SESSION_ID = "sessionId" diff --git a/src/backend/websocket/biz-websocket/src/main/kotlin/com/tencent/bkrepo/websocket/controller/ClipboardController.kt b/src/backend/websocket/biz-websocket/src/main/kotlin/com/tencent/bkrepo/websocket/controller/ClipboardController.kt new file mode 100644 index 0000000000..1f929a99e5 --- /dev/null +++ b/src/backend/websocket/biz-websocket/src/main/kotlin/com/tencent/bkrepo/websocket/controller/ClipboardController.kt @@ -0,0 +1,52 @@ +/* + * Tencent is pleased to support the open source community by making BK-CI 蓝鲸持续集成平台 available. + * + * Copyright (C) 2024 THL A29 Limited, a Tencent company. All rights reserved. + * + * BK-CI 蓝鲸持续集成平台 is licensed under the MIT license. + * + * A copy of the MIT License is included in this file. + * + * + * Terms of the MIT License: + * --------------------------------------------------- + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated + * documentation files (the "Software"), to deal in the Software without restriction, including without limitation the + * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all copies or substantial portions of + * the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT + * LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN + * NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +package com.tencent.bkrepo.websocket.controller + +import com.tencent.bkrepo.websocket.pojo.fs.CopyPDU +import com.tencent.bkrepo.websocket.pojo.fs.PastePDU +import com.tencent.bkrepo.websocket.service.ClipboardService +import org.springframework.messaging.handler.annotation.MessageMapping +import org.springframework.stereotype.Controller + +@Controller +@MessageMapping("/clipboard") +class ClipboardController( + private val clipboardService: ClipboardService +) { + + @MessageMapping("/copy") + fun copy(copyPDU: CopyPDU) { + clipboardService.copy(copyPDU) + } + + @MessageMapping("/paste") + fun paste(pastePDU: PastePDU) { + clipboardService.paste(pastePDU) + } +} + diff --git a/src/backend/websocket/biz-websocket/src/main/kotlin/com/tencent/bkrepo/websocket/dispatch/Dispatcher.kt b/src/backend/websocket/biz-websocket/src/main/kotlin/com/tencent/bkrepo/websocket/dispatch/Dispatcher.kt new file mode 100644 index 0000000000..81c5cb5bd9 --- /dev/null +++ b/src/backend/websocket/biz-websocket/src/main/kotlin/com/tencent/bkrepo/websocket/dispatch/Dispatcher.kt @@ -0,0 +1,36 @@ +/* + * Tencent is pleased to support the open source community by making BK-CI 蓝鲸持续集成平台 available. + * + * Copyright (C) 2019 THL A29 Limited, a Tencent company. All rights reserved. + * + * BK-CI 蓝鲸持续集成平台 is licensed under the MIT license. + * + * A copy of the MIT License is included in this file. + * + * + * Terms of the MIT License: + * --------------------------------------------------- + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated + * documentation files (the "Software"), to deal in the Software without restriction, including without limitation the + * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all copies or substantial portions of + * the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT + * LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN + * NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +package com.tencent.bkrepo.websocket.dispatch + +/** + * 下发接口 + */ +interface Dispatcher { + + fun dispatch(data: T) +} diff --git a/src/backend/websocket/biz-websocket/src/main/kotlin/com/tencent/bkrepo/websocket/dispatch/TransferDispatch.kt b/src/backend/websocket/biz-websocket/src/main/kotlin/com/tencent/bkrepo/websocket/dispatch/TransferDispatch.kt new file mode 100644 index 0000000000..4986de5d81 --- /dev/null +++ b/src/backend/websocket/biz-websocket/src/main/kotlin/com/tencent/bkrepo/websocket/dispatch/TransferDispatch.kt @@ -0,0 +1,54 @@ +/* + * Tencent is pleased to support the open source community by making BK-CI 蓝鲸持续集成平台 available. + * + * Copyright (C) 2024 THL A29 Limited, a Tencent company. All rights reserved. + * + * BK-CI 蓝鲸持续集成平台 is licensed under the MIT license. + * + * A copy of the MIT License is included in this file. + * + * + * Terms of the MIT License: + * --------------------------------------------------- + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated + * documentation files (the "Software"), to deal in the Software without restriction, including without limitation the + * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all copies or substantial portions of + * the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT + * LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN + * NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +package com.tencent.bkrepo.websocket.dispatch + +import com.tencent.bkrepo.common.api.util.toJsonString +import com.tencent.bkrepo.common.stream.event.supplier.MessageSupplier +import com.tencent.bkrepo.websocket.config.WebSocketProperties +import com.tencent.bkrepo.websocket.dispatch.push.TransferPush +import org.springframework.messaging.simp.SimpMessagingTemplate +import org.springframework.stereotype.Component + +@Component +class TransferDispatch( + private val messageSupplier: MessageSupplier, + private val simpMessagingTemplate: SimpMessagingTemplate, + private val webSocketProperties: WebSocketProperties +) : Dispatcher { + override fun dispatch(data: TransferPush) { + if (webSocketProperties.transfer) { + messageSupplier.delegateToSupplier(data, topic = TOPIC) + } else { + simpMessagingTemplate.convertAndSend(data.topic, data.data.toJsonString()) + } + } + + companion object { + private const val TOPIC = "websocket-transfer-out-0" + } +} diff --git a/src/backend/websocket/biz-websocket/src/main/kotlin/com/tencent/bkrepo/websocket/dispatch/push/CopyPDUTransferPush.kt b/src/backend/websocket/biz-websocket/src/main/kotlin/com/tencent/bkrepo/websocket/dispatch/push/CopyPDUTransferPush.kt new file mode 100644 index 0000000000..7ccd8c870a --- /dev/null +++ b/src/backend/websocket/biz-websocket/src/main/kotlin/com/tencent/bkrepo/websocket/dispatch/push/CopyPDUTransferPush.kt @@ -0,0 +1,37 @@ +/* + * Tencent is pleased to support the open source community by making BK-CI 蓝鲸持续集成平台 available. + * + * Copyright (C) 2024 THL A29 Limited, a Tencent company. All rights reserved. + * + * BK-CI 蓝鲸持续集成平台 is licensed under the MIT license. + * + * A copy of the MIT License is included in this file. + * + * + * Terms of the MIT License: + * --------------------------------------------------- + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated + * documentation files (the "Software"), to deal in the Software without restriction, including without limitation the + * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all copies or substantial portions of + * the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT + * LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN + * NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +package com.tencent.bkrepo.websocket.dispatch.push + +import com.tencent.bkrepo.websocket.pojo.fs.CopyPDU + +class CopyPDUTransferPush( + copyPDU: CopyPDU, +) : TransferPush( + topic = "/topic/clipboard/copy/${copyPDU.workspaceName}", + data = copyPDU +) diff --git a/src/backend/websocket/biz-websocket/src/main/kotlin/com/tencent/bkrepo/websocket/dispatch/push/PastePDUTransferPush.kt b/src/backend/websocket/biz-websocket/src/main/kotlin/com/tencent/bkrepo/websocket/dispatch/push/PastePDUTransferPush.kt new file mode 100644 index 0000000000..f6da31f94b --- /dev/null +++ b/src/backend/websocket/biz-websocket/src/main/kotlin/com/tencent/bkrepo/websocket/dispatch/push/PastePDUTransferPush.kt @@ -0,0 +1,37 @@ +/* + * Tencent is pleased to support the open source community by making BK-CI 蓝鲸持续集成平台 available. + * + * Copyright (C) 2024 THL A29 Limited, a Tencent company. All rights reserved. + * + * BK-CI 蓝鲸持续集成平台 is licensed under the MIT license. + * + * A copy of the MIT License is included in this file. + * + * + * Terms of the MIT License: + * --------------------------------------------------- + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated + * documentation files (the "Software"), to deal in the Software without restriction, including without limitation the + * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all copies or substantial portions of + * the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT + * LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN + * NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +package com.tencent.bkrepo.websocket.dispatch.push + +import com.tencent.bkrepo.websocket.pojo.fs.PastePDU + +class PastePDUTransferPush( + pastePDU: PastePDU, +) : TransferPush( + topic = "/topic/clipboard/paste/${pastePDU.workspaceName}", + data = pastePDU +) diff --git a/src/backend/websocket/biz-websocket/src/main/kotlin/com/tencent/bkrepo/websocket/dispatch/push/TransferPush.kt b/src/backend/websocket/biz-websocket/src/main/kotlin/com/tencent/bkrepo/websocket/dispatch/push/TransferPush.kt new file mode 100644 index 0000000000..450654566f --- /dev/null +++ b/src/backend/websocket/biz-websocket/src/main/kotlin/com/tencent/bkrepo/websocket/dispatch/push/TransferPush.kt @@ -0,0 +1,33 @@ +/* + * Tencent is pleased to support the open source community by making BK-CI 蓝鲸持续集成平台 available. + * + * Copyright (C) 2019 THL A29 Limited, a Tencent company. All rights reserved. + * + * BK-CI 蓝鲸持续集成平台 is licensed under the MIT license. + * + * A copy of the MIT License is included in this file. + * + * + * Terms of the MIT License: + * --------------------------------------------------- + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated + * documentation files (the "Software"), to deal in the Software without restriction, including without limitation the + * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all copies or substantial portions of + * the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT + * LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN + * NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +package com.tencent.bkrepo.websocket.dispatch.push + +open class TransferPush( + open val topic: String, + open val data: Any +) diff --git a/src/backend/websocket/biz-websocket/src/main/kotlin/com/tencent/bkrepo/websocket/exception/WebsocketExceptionHandler.kt b/src/backend/websocket/biz-websocket/src/main/kotlin/com/tencent/bkrepo/websocket/exception/WebsocketExceptionHandler.kt new file mode 100644 index 0000000000..60ae6dbb17 --- /dev/null +++ b/src/backend/websocket/biz-websocket/src/main/kotlin/com/tencent/bkrepo/websocket/exception/WebsocketExceptionHandler.kt @@ -0,0 +1,48 @@ +/* + * Tencent is pleased to support the open source community by making BK-CI 蓝鲸持续集成平台 available. + * + * Copyright (C) 2024 THL A29 Limited, a Tencent company. All rights reserved. + * + * BK-CI 蓝鲸持续集成平台 is licensed under the MIT license. + * + * A copy of the MIT License is included in this file. + * + * + * Terms of the MIT License: + * --------------------------------------------------- + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated + * documentation files (the "Software"), to deal in the Software without restriction, including without limitation the + * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all copies or substantial portions of + * the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT + * LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN + * NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +package com.tencent.bkrepo.websocket.exception + +import com.tencent.bkrepo.common.api.exception.ErrorCodeException +import com.tencent.bkrepo.common.api.pojo.Response +import com.tencent.bkrepo.common.service.exception.AbstractExceptionHandler +import org.springframework.messaging.handler.annotation.MessageExceptionHandler +import org.springframework.web.bind.annotation.RestControllerAdvice + +@RestControllerAdvice +class WebsocketExceptionHandler : AbstractExceptionHandler() { + + @MessageExceptionHandler(ErrorCodeException::class) + fun handleException(exception: ErrorCodeException): Response { + return response(exception) + } + + @MessageExceptionHandler(Exception::class) + fun handleException(exception: Exception): Response { + return response(exception) + } +} diff --git a/src/backend/websocket/biz-websocket/src/main/kotlin/com/tencent/bkrepo/websocket/handler/SessionHandler.kt b/src/backend/websocket/biz-websocket/src/main/kotlin/com/tencent/bkrepo/websocket/handler/SessionHandler.kt new file mode 100644 index 0000000000..86e6ed35d5 --- /dev/null +++ b/src/backend/websocket/biz-websocket/src/main/kotlin/com/tencent/bkrepo/websocket/handler/SessionHandler.kt @@ -0,0 +1,131 @@ +/* + * Tencent is pleased to support the open source community by making BK-CI 蓝鲸持续集成平台 available. + * + * Copyright (C) 2019 THL A29 Limited, a Tencent company. All rights reserved. + * + * BK-CI 蓝鲸持续集成平台 is licensed under the MIT license. + * + * A copy of the MIT License is included in this file. + * + * + * Terms of the MIT License: + * --------------------------------------------------- + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated + * documentation files (the "Software"), to deal in the Software without restriction, including without limitation the + * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all copies or substantial portions of + * the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT + * LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN + * NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +package com.tencent.bkrepo.websocket.handler + +import com.tencent.bkrepo.common.api.constant.AUTH_HEADER_UID +import com.tencent.bkrepo.common.api.constant.CharPool.COLON +import com.tencent.bkrepo.common.api.constant.HttpHeaders +import com.tencent.bkrepo.common.api.constant.PLATFORM_AUTH_PREFIX +import com.tencent.bkrepo.common.api.constant.PLATFORM_KEY +import com.tencent.bkrepo.common.api.constant.USER_KEY +import com.tencent.bkrepo.common.artifact.stream.closeQuietly +import com.tencent.bkrepo.common.security.exception.AuthenticationException +import com.tencent.bkrepo.common.security.http.jwt.JwtAuthProperties +import com.tencent.bkrepo.common.security.manager.AuthenticationManager +import com.tencent.bkrepo.common.security.util.JwtUtils +import com.tencent.bkrepo.websocket.constant.APP_ENDPOINT +import com.tencent.bkrepo.websocket.constant.SESSION_ID +import com.tencent.bkrepo.websocket.constant.USER_ENDPOINT +import com.tencent.bkrepo.websocket.service.WebsocketService +import com.tencent.bkrepo.websocket.util.HostUtils +import io.jsonwebtoken.ExpiredJwtException +import io.jsonwebtoken.MalformedJwtException +import io.jsonwebtoken.UnsupportedJwtException +import io.jsonwebtoken.security.SignatureException +import org.slf4j.LoggerFactory +import org.springframework.web.socket.CloseStatus +import org.springframework.web.socket.WebSocketHandler +import org.springframework.web.socket.WebSocketSession +import org.springframework.web.socket.handler.WebSocketHandlerDecorator +import java.util.Base64 + +class SessionHandler( + delegate: WebSocketHandler, + private val websocketService: WebsocketService, + private val authenticationManager: AuthenticationManager, + jwtProperties: JwtAuthProperties +) : WebSocketHandlerDecorator(delegate) { + + private val signingKey = JwtUtils.createSigningKey(jwtProperties.secretKey) + + // 链接关闭记录去除session + override fun afterConnectionClosed(session: WebSocketSession, closeStatus: CloseStatus) { + val uri = session.uri + if (closeStatus.code != CloseStatus.NORMAL.code && closeStatus.code != CloseStatus.PROTOCOL_ERROR.code) { + logger.warn("websocket close abnormal, [$closeStatus] [${session.uri}] [${session.remoteAddress}]") + } + val sessionId = HostUtils.getRealSession(session.uri?.query) + if (sessionId.isNullOrEmpty()) { + logger.warn("connection closed can not find sessionId, $uri| ${session.remoteAddress}") + super.afterConnectionClosed(session, closeStatus) + } + websocketService.removeCacheSession(sessionId!!) + + super.afterConnectionClosed(session, closeStatus) + } + + override fun afterConnectionEstablished(session: WebSocketSession) { + val uri = session.uri + val remoteAddr = session.remoteAddress + val sessionId = HostUtils.getRealSession(uri?.query) + try { + authorization(session) + } catch (e: Exception) { + val authException = e is AuthenticationException || e is ExpiredJwtException || + e is UnsupportedJwtException || e is MalformedJwtException || + e is SignatureException || e is IllegalArgumentException + if (authException) { + logger.info("auth failed: |$sessionId| $uri | $remoteAddr | ${e.message}") + session.closeQuietly() + } else { + throw e + } + } + } + + private fun authorization(session: WebSocketSession) { + val uri = session.uri + val remoteId = session.remoteAddress + val sessionId = HostUtils.getRealSession(uri?.query) + when { + uri == null -> throw AuthenticationException("uri is null") + uri.path.startsWith(USER_ENDPOINT) -> { + val platformToken = session.handshakeHeaders[HttpHeaders.AUTHORIZATION]?.firstOrNull()?.toString() + ?.removePrefix(PLATFORM_AUTH_PREFIX) ?: throw AuthenticationException("platform credential is null") + val (accessKey, secretKey) = String(Base64.getDecoder().decode(platformToken)).split(COLON) + val appId = authenticationManager.checkPlatformAccount(accessKey, secretKey) + session.attributes[PLATFORM_KEY] = appId + session.attributes[USER_KEY] = session.handshakeHeaders[AUTH_HEADER_UID] + } + uri.path.startsWith(APP_ENDPOINT) -> { + val token = session.handshakeHeaders[HttpHeaders.AUTHORIZATION]?.firstOrNull().orEmpty() + val claims = JwtUtils.validateToken(signingKey, token).body + session.attributes[USER_KEY] = claims.subject + } + else -> throw AuthenticationException("invalid uri") + } + websocketService.addCacheSession(sessionId!!) + session.attributes[SESSION_ID] = sessionId + logger.info("connection success: |$sessionId| $uri | $remoteId | ${session.attributes[USER_KEY]} ") + super.afterConnectionEstablished(session) + } + + companion object { + private val logger = LoggerFactory.getLogger(SessionHandler::class.java) + } +} diff --git a/src/backend/websocket/biz-websocket/src/main/kotlin/com/tencent/bkrepo/websocket/handler/SessionWebSocketHandlerDecoratorFactory.kt b/src/backend/websocket/biz-websocket/src/main/kotlin/com/tencent/bkrepo/websocket/handler/SessionWebSocketHandlerDecoratorFactory.kt new file mode 100644 index 0000000000..6b1a45a695 --- /dev/null +++ b/src/backend/websocket/biz-websocket/src/main/kotlin/com/tencent/bkrepo/websocket/handler/SessionWebSocketHandlerDecoratorFactory.kt @@ -0,0 +1,45 @@ +/* + * Tencent is pleased to support the open source community by making BK-CI 蓝鲸持续集成平台 available. + * + * Copyright (C) 2019 THL A29 Limited, a Tencent company. All rights reserved. + * + * BK-CI 蓝鲸持续集成平台 is licensed under the MIT license. + * + * A copy of the MIT License is included in this file. + * + * + * Terms of the MIT License: + * --------------------------------------------------- + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated + * documentation files (the "Software"), to deal in the Software without restriction, including without limitation the + * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all copies or substantial portions of + * the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT + * LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN + * NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +package com.tencent.bkrepo.websocket.handler + +import com.tencent.bkrepo.common.security.http.jwt.JwtAuthProperties +import com.tencent.bkrepo.common.security.manager.AuthenticationManager +import com.tencent.bkrepo.websocket.service.WebsocketService +import org.springframework.web.socket.WebSocketHandler +import org.springframework.web.socket.handler.WebSocketHandlerDecoratorFactory + +class SessionWebSocketHandlerDecoratorFactory ( + private val websocketService: WebsocketService, + private val authenticationManager: AuthenticationManager, + private val jwtAuthProperties: JwtAuthProperties, +) : WebSocketHandlerDecoratorFactory { + + override fun decorate(handler: WebSocketHandler): WebSocketHandler { + return SessionHandler(handler, websocketService, authenticationManager, jwtAuthProperties) + } +} diff --git a/src/backend/websocket/biz-websocket/src/main/kotlin/com/tencent/bkrepo/websocket/listener/TransferPushListener.kt b/src/backend/websocket/biz-websocket/src/main/kotlin/com/tencent/bkrepo/websocket/listener/TransferPushListener.kt new file mode 100644 index 0000000000..1a21c7f3d1 --- /dev/null +++ b/src/backend/websocket/biz-websocket/src/main/kotlin/com/tencent/bkrepo/websocket/listener/TransferPushListener.kt @@ -0,0 +1,51 @@ +/* + * Tencent is pleased to support the open source community by making BK-CI 蓝鲸持续集成平台 available. + * + * Copyright (C) 2024 THL A29 Limited, a Tencent company. All rights reserved. + * + * BK-CI 蓝鲸持续集成平台 is licensed under the MIT license. + * + * A copy of the MIT License is included in this file. + * + * + * Terms of the MIT License: + * --------------------------------------------------- + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated + * documentation files (the "Software"), to deal in the Software without restriction, including without limitation the + * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all copies or substantial portions of + * the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT + * LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN + * NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +package com.tencent.bkrepo.websocket.listener + +import com.tencent.bkrepo.common.api.util.toJsonString +import com.tencent.bkrepo.websocket.dispatch.push.TransferPush +import org.slf4j.LoggerFactory +import org.springframework.messaging.Message +import org.springframework.messaging.simp.SimpMessagingTemplate +import org.springframework.stereotype.Component + +@Component +class TransferPushListener( + private val simpMessagingTemplate: SimpMessagingTemplate +) { + + fun accept(message: Message) { + logger.debug(message.payload.toString()) + val transferPush = message.payload + simpMessagingTemplate.convertAndSend(transferPush.topic, transferPush.data.toJsonString()) + } + + companion object { + private val logger = LoggerFactory.getLogger(TransferPushListener::class.java) + } +} diff --git a/src/backend/websocket/biz-websocket/src/main/kotlin/com/tencent/bkrepo/websocket/pojo/fs/CopyPDU.kt b/src/backend/websocket/biz-websocket/src/main/kotlin/com/tencent/bkrepo/websocket/pojo/fs/CopyPDU.kt new file mode 100644 index 0000000000..01da102c98 --- /dev/null +++ b/src/backend/websocket/biz-websocket/src/main/kotlin/com/tencent/bkrepo/websocket/pojo/fs/CopyPDU.kt @@ -0,0 +1,40 @@ +/* + * Tencent is pleased to support the open source community by making BK-CI 蓝鲸持续集成平台 available. + * + * Copyright (C) 2024 THL A29 Limited, a Tencent company. All rights reserved. + * + * BK-CI 蓝鲸持续集成平台 is licensed under the MIT license. + * + * A copy of the MIT License is included in this file. + * + * + * Terms of the MIT License: + * --------------------------------------------------- + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated + * documentation files (the "Software"), to deal in the Software without restriction, including without limitation the + * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all copies or substantial portions of + * the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT + * LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN + * NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +package com.tencent.bkrepo.websocket.pojo.fs + +/** + * 复制协议数据单元 + */ +data class CopyPDU( + val projectId: String, + val userId: String, + val workspaceName: String, + val files: Map, + val timestamp: Long, + val dstPath: String? = null +) diff --git a/src/backend/websocket/biz-websocket/src/main/kotlin/com/tencent/bkrepo/websocket/pojo/fs/PastePDU.kt b/src/backend/websocket/biz-websocket/src/main/kotlin/com/tencent/bkrepo/websocket/pojo/fs/PastePDU.kt new file mode 100644 index 0000000000..f295772852 --- /dev/null +++ b/src/backend/websocket/biz-websocket/src/main/kotlin/com/tencent/bkrepo/websocket/pojo/fs/PastePDU.kt @@ -0,0 +1,36 @@ +/* + * Tencent is pleased to support the open source community by making BK-CI 蓝鲸持续集成平台 available. + * + * Copyright (C) 2024 THL A29 Limited, a Tencent company. All rights reserved. + * + * BK-CI 蓝鲸持续集成平台 is licensed under the MIT license. + * + * A copy of the MIT License is included in this file. + * + * + * Terms of the MIT License: + * --------------------------------------------------- + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated + * documentation files (the "Software"), to deal in the Software without restriction, including without limitation the + * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all copies or substantial portions of + * the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT + * LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN + * NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +package com.tencent.bkrepo.websocket.pojo.fs + +/** + * 粘贴协议数据单元 + */ +data class PastePDU( + val workspaceName: String, + val timestamp: Long, +) diff --git a/src/backend/websocket/biz-websocket/src/main/kotlin/com/tencent/bkrepo/websocket/service/ClipboardService.kt b/src/backend/websocket/biz-websocket/src/main/kotlin/com/tencent/bkrepo/websocket/service/ClipboardService.kt new file mode 100644 index 0000000000..641c2b68fb --- /dev/null +++ b/src/backend/websocket/biz-websocket/src/main/kotlin/com/tencent/bkrepo/websocket/service/ClipboardService.kt @@ -0,0 +1,58 @@ +/* + * Tencent is pleased to support the open source community by making BK-CI 蓝鲸持续集成平台 available. + * + * Copyright (C) 2024 THL A29 Limited, a Tencent company. All rights reserved. + * + * BK-CI 蓝鲸持续集成平台 is licensed under the MIT license. + * + * A copy of the MIT License is included in this file. + * + * + * Terms of the MIT License: + * --------------------------------------------------- + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated + * documentation files (the "Software"), to deal in the Software without restriction, including without limitation the + * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all copies or substantial portions of + * the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT + * LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN + * NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +package com.tencent.bkrepo.websocket.service + +import com.tencent.bkrepo.websocket.dispatch.TransferDispatch +import com.tencent.bkrepo.websocket.dispatch.push.CopyPDUTransferPush +import com.tencent.bkrepo.websocket.dispatch.push.PastePDUTransferPush +import com.tencent.bkrepo.websocket.pojo.fs.CopyPDU +import com.tencent.bkrepo.websocket.pojo.fs.PastePDU +import org.slf4j.LoggerFactory +import org.springframework.stereotype.Service + +@Service +class ClipboardService( + private val transferDispatch: TransferDispatch +) { + + fun copy(copyPDU: CopyPDU) { + logger.info("CopyPDU: $copyPDU") + val copyPDUTransferPush = CopyPDUTransferPush(copyPDU) + transferDispatch.dispatch(copyPDUTransferPush) + } + + fun paste(pastePDU: PastePDU) { + logger.info("PastePDU: $pastePDU") + val pastePDUTransferPush = PastePDUTransferPush(pastePDU) + transferDispatch.dispatch(pastePDUTransferPush) + } + + companion object { + private val logger = LoggerFactory.getLogger(ClipboardService::class.java) + } +} diff --git a/src/backend/websocket/biz-websocket/src/main/kotlin/com/tencent/bkrepo/websocket/service/WebsocketService.kt b/src/backend/websocket/biz-websocket/src/main/kotlin/com/tencent/bkrepo/websocket/service/WebsocketService.kt new file mode 100644 index 0000000000..559f495445 --- /dev/null +++ b/src/backend/websocket/biz-websocket/src/main/kotlin/com/tencent/bkrepo/websocket/service/WebsocketService.kt @@ -0,0 +1,63 @@ +/* + * Tencent is pleased to support the open source community by making BK-CI 蓝鲸持续集成平台 available. + * + * Copyright (C) 2024 THL A29 Limited, a Tencent company. All rights reserved. + * + * BK-CI 蓝鲸持续集成平台 is licensed under the MIT license. + * + * A copy of the MIT License is included in this file. + * + * + * Terms of the MIT License: + * --------------------------------------------------- + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated + * documentation files (the "Software"), to deal in the Software without restriction, including without limitation the + * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all copies or substantial portions of + * the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT + * LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN + * NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +package com.tencent.bkrepo.websocket.service + +import org.slf4j.LoggerFactory +import org.springframework.stereotype.Service +import java.util.Collections + +@Service +class WebsocketService { + private val cacheSessionList = Collections.synchronizedList(mutableListOf()) + + fun addCacheSession(sessionId: String) { + if (cacheSessionList.contains(sessionId)) { + logger.warn("this session[$sessionId] already in cacheSession") + return + } + cacheSessionList.add(sessionId) + } + + // 清楚实例内部缓存的session + fun removeCacheSession(sessionId: String) { + cacheSessionList.remove(sessionId) + } + + // 判断获取到的session是否由该实例持有 + fun isCacheSession(sessionId: String): Boolean { + if (cacheSessionList.contains(sessionId)) { + logger.debug("sessionId[$sessionId] is in this host") + return true + } + return false + } + + companion object { + private val logger = LoggerFactory.getLogger(WebsocketService::class.java) + } +} diff --git a/src/backend/websocket/biz-websocket/src/main/kotlin/com/tencent/bkrepo/websocket/util/HostUtils.kt b/src/backend/websocket/biz-websocket/src/main/kotlin/com/tencent/bkrepo/websocket/util/HostUtils.kt new file mode 100644 index 0000000000..19a64fdc90 --- /dev/null +++ b/src/backend/websocket/biz-websocket/src/main/kotlin/com/tencent/bkrepo/websocket/util/HostUtils.kt @@ -0,0 +1,84 @@ +/* + * Tencent is pleased to support the open source community by making BK-CI 蓝鲸持续集成平台 available. + * + * Copyright (C) 2024 THL A29 Limited, a Tencent company. All rights reserved. + * + * BK-CI 蓝鲸持续集成平台 is licensed under the MIT license. + * + * A copy of the MIT License is included in this file. + * + * + * Terms of the MIT License: + * --------------------------------------------------- + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated + * documentation files (the "Software"), to deal in the Software without restriction, including without limitation the + * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all copies or substantial portions of + * the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT + * LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN + * NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +package com.tencent.bkrepo.websocket.util + +import org.slf4j.LoggerFactory +import java.net.DatagramSocket +import java.net.InetAddress +import java.net.URL + +object HostUtils { + + fun getHostIp(gateway: String?): String { + try { + val localHost = InetAddress.getLocalHost() + return if (localHost.isLoopbackAddress) { + getFromUDP(gateway) ?: DEFAULT_IP + } else { + localHost.hostAddress + } + } catch (e: Throwable) { + logger.warn("Fail to get local host ip", e) + try { + return getFromUDP(gateway) ?: DEFAULT_IP + } catch (t: Throwable) { + logger.warn("Fail to use socket to get the localhost host") + } + } + return DEFAULT_IP + } + + private fun getFromUDP(gateway: String?): String? { + if (gateway.isNullOrBlank()) { + return null + } + + val gatewayHost = try { + val url = URL(gateway) + url.host + } catch (t: Throwable) { + logger.warn("Fail to get the gateway host", t) + return null + } + + DatagramSocket().use { socket -> + socket.connect(InetAddress.getByName(gatewayHost), 10002) + return socket.localAddress.hostAddress + } + } + + fun getRealSession(query: String?): String? { + if (query.isNullOrEmpty()) { + return null + } + return query.substringAfter("sessionId=").substringBefore("&t=") + } + + private const val DEFAULT_IP = "127.0.0.1" + private val logger = LoggerFactory.getLogger(javaClass) +} diff --git a/src/backend/websocket/boot-websocket/build.gradle.kts b/src/backend/websocket/boot-websocket/build.gradle.kts new file mode 100644 index 0000000000..49bd2145ce --- /dev/null +++ b/src/backend/websocket/boot-websocket/build.gradle.kts @@ -0,0 +1,34 @@ +/* + * Tencent is pleased to support the open source community by making BK-CI 蓝鲸持续集成平台 available. + * + * Copyright (C) 2024 THL A29 Limited, a Tencent company. All rights reserved. + * + * BK-CI 蓝鲸持续集成平台 is licensed under the MIT license. + * + * A copy of the MIT License is included in this file. + * + * + * Terms of the MIT License: + * --------------------------------------------------- + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED " AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +dependencies { + implementation(project(":websocket:biz-websocket")) +} diff --git a/src/backend/websocket/boot-websocket/src/main/kotlin/com/tencent/bkrepo/websocket/WebsocketApplication.kt b/src/backend/websocket/boot-websocket/src/main/kotlin/com/tencent/bkrepo/websocket/WebsocketApplication.kt new file mode 100644 index 0000000000..5a71325d24 --- /dev/null +++ b/src/backend/websocket/boot-websocket/src/main/kotlin/com/tencent/bkrepo/websocket/WebsocketApplication.kt @@ -0,0 +1,41 @@ +/* + * Tencent is pleased to support the open source community by making BK-CI 蓝鲸持续集成平台 available. + * + * Copyright (C) 2024 THL A29 Limited, a Tencent company. All rights reserved. + * + * BK-CI 蓝鲸持续集成平台 is licensed under the MIT license. + * + * A copy of the MIT License is included in this file. + * + * + * Terms of the MIT License: + * --------------------------------------------------- + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated + * documentation files (the "Software"), to deal in the Software without restriction, including without limitation the + * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all copies or substantial portions of + * the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT + * LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN + * NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +package com.tencent.bkrepo.websocket + +import com.tencent.bkrepo.common.service.condition.MicroService +import org.springframework.boot.runApplication + +/** + * Websocket微服务启动类 + */ +@MicroService +class WebsocketApplication + +fun main(args: Array) { + runApplication(*args) +} diff --git a/src/backend/websocket/boot-websocket/src/main/resources/bootstrap.yml b/src/backend/websocket/boot-websocket/src/main/resources/bootstrap.yml new file mode 100644 index 0000000000..1fcf7233d0 --- /dev/null +++ b/src/backend/websocket/boot-websocket/src/main/resources/bootstrap.yml @@ -0,0 +1,4 @@ +spring.application.name: websocket +server.port: 25914 + +group: ${spring.cloud.consul.discovery.instance-id} diff --git a/src/backend/websocket/build.gradle.kts b/src/backend/websocket/build.gradle.kts new file mode 100644 index 0000000000..aa1c8e01b8 --- /dev/null +++ b/src/backend/websocket/build.gradle.kts @@ -0,0 +1,30 @@ +/* + * Tencent is pleased to support the open source community by making BK-CI 蓝鲸持续集成平台 available. + * + * Copyright (C) 2024 THL A29 Limited, a Tencent company. All rights reserved. + * + * BK-CI 蓝鲸持续集成平台 is licensed under the MIT license. + * + * A copy of the MIT License is included in this file. + * + * + * Terms of the MIT License: + * --------------------------------------------------- + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED " AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ diff --git a/src/gateway/lua/router_srv.lua b/src/gateway/lua/router_srv.lua index c9293a8ff9..81adf9764e 100644 --- a/src/gateway/lua/router_srv.lua +++ b/src/gateway/lua/router_srv.lua @@ -20,7 +20,7 @@ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLI -- 访问限制微服务 -- local allow_services = { "auth", "repository", "generic", "docker", "oci", "maven", "job", "helm", "pypi", "opdata", "rpm", "s3", "git", "npm", "fs-server","analyst", - "replication", "git", "nuget", "composer", "media", "ddc", "conan","job-schedule" } + "replication", "git", "nuget", "composer", "media", "ddc", "conan","job-schedule", "websocket" } local service_name = ngx.var.service if not arrayUtil:isInArray(service_name, allow_services) then diff --git a/src/gateway/vhosts/bkrepo.websocket.conf b/src/gateway/vhosts/bkrepo.websocket.conf new file mode 100644 index 0000000000..62886b8b5c --- /dev/null +++ b/src/gateway/vhosts/bkrepo.websocket.conf @@ -0,0 +1,46 @@ +location ~ /websocket/(ws/user.*) { + header_filter_by_lua_file 'conf/lua/cors_filter.lua'; + auth_request /auth/web; + # 设置auth的变量 + auth_request_set $uid $sent_http_x_bkrepo_uid; + auth_request_set $accessToken $sent_http_x_bkrepo_access_token; + auth_request_set $bk_token $sent_http_x_bkrepo_bk_token; + + set $service "websocket"; + set $path $1; + set $target ''; + + access_by_lua_file 'conf/lua/router_srv.lua'; + proxy_set_header X-BKREPO-UID $uid; + proxy_set_header X-DEVOPS-BK-TOKEN $bk_token; + proxy_set_header X-DEVOPS-BK-TICKET $bk_token; + proxy_set_header X-DEVOPS-ACCESS-TOKEN $accessToken; + proxy_set_header authorization "$bkrepo_authorization"; + + proxy_set_header Host $host; + proxy_set_header X-Real-IP $remote_addr; + proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; + + proxy_set_header Upgrade $http_upgrade; + proxy_set_header Connection "Upgrade"; + + proxy_http_version 1.1; + proxy_pass http://$target/$path?$args; +} + +location ~ /websocket/(ws/app.*) { + set $service "websocket"; + set $path $1; + set $target ''; + + access_by_lua_file 'conf/lua/router_srv.lua'; + + proxy_set_header Host $host; + proxy_set_header X-Real-IP $remote_addr; + proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; + + proxy_set_header Upgrade "websocket"; + proxy_set_header Connection "Upgrade"; + proxy_http_version 1.1; + proxy_pass http://$target/$path?$args; +} \ No newline at end of file diff --git a/support-files/templates/gateway#vhosts#bkrepo.server.conf b/support-files/templates/gateway#vhosts#bkrepo.server.conf index e7d1278bc4..d0c1864a47 100644 --- a/support-files/templates/gateway#vhosts#bkrepo.server.conf +++ b/support-files/templates/gateway#vhosts#bkrepo.server.conf @@ -41,6 +41,9 @@ server { # web接口网关路径 include vhosts/bkrepo.web.conf; + # websocket网关路径 + include vhosts/bkrepo.websocket.conf; + # 后台的网关路径 include vhosts/bkrepo.backend.conf; }