1
0
mirror of https://github.com/1Panel-dev/1Panel.git synced 2025-03-14 01:34:47 +08:00

feat: 网站 HTTPS 逻辑优化 (#6074)

This commit is contained in:
zhengkunwang 2024-08-09 17:05:13 +08:00 committed by GitHub
parent a225d2d79a
commit e003d74506
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
12 changed files with 139 additions and 15 deletions

View File

@ -71,3 +71,25 @@ func (b *BaseApi) GetWebDomains(c *gin.Context) {
} }
helper.SuccessWithData(c, list) helper.SuccessWithData(c, list)
} }
// 写一个 update website domain 的接口
// @Tags Website Domain
// @Summary Update website domain
// @Description 更新网站域名
// @Accept json
// @Param request body request.WebsiteDomainUpdate true "request"
// @Success 200
// @Security ApiKeyAuth
// @Router /websites/domains/update [post]
// @x-panel-log {"bodyKeys":["id"],"paramKeys":[],"BeforeFunctions":[{"input_column":"id","input_value":"id","isList":false,"db":"website_domains","output_column":"domain","output_value":"domain"}],"formatZH":"更新域名 [domain]","formatEN":"Update domain [domain]"}
func (b *BaseApi) UpdateWebDomain(c *gin.Context) {
var req request.WebsiteDomainUpdate
if err := helper.CheckBindAndValidate(&req, c); err != nil {
return
}
if err := websiteService.UpdateWebsiteDomain(req); err != nil {
helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, err)
return
}
helper.SuccessWithOutData(c)
}

View File

@ -127,10 +127,15 @@ type WebsiteDomainCreate struct {
Domains []WebsiteDomain `json:"domains" validate:"required"` Domains []WebsiteDomain `json:"domains" validate:"required"`
} }
type WebsiteDomainUpdate struct {
ID uint `json:"id" validate:"required"`
SSL bool `json:"ssl"`
}
type WebsiteDomain struct { type WebsiteDomain struct {
Domain string `json:"domain" validate:"required"` Domain string `json:"domain" validate:"required"`
Port int `json:"port"` Port int `json:"port"`
SSL bool `json:"SSL"` SSL bool `json:"ssl"`
} }
type WebsiteDomainDelete struct { type WebsiteDomainDelete struct {

View File

@ -4,7 +4,7 @@ type WebsiteDomain struct {
BaseModel BaseModel
WebsiteID uint `gorm:"column:website_id;type:varchar(64);not null;" json:"websiteId"` WebsiteID uint `gorm:"column:website_id;type:varchar(64);not null;" json:"websiteId"`
Domain string `gorm:"type:varchar(256);not null" json:"domain"` Domain string `gorm:"type:varchar(256);not null" json:"domain"`
SSL bool `json:"SSL"` SSL bool `json:"ssl"`
Port int `gorm:"type:integer" json:"port"` Port int `gorm:"type:integer" json:"port"`
} }

View File

@ -67,6 +67,7 @@ type IWebsiteService interface {
CreateWebsiteDomain(create request.WebsiteDomainCreate) ([]model.WebsiteDomain, error) CreateWebsiteDomain(create request.WebsiteDomainCreate) ([]model.WebsiteDomain, error)
GetWebsiteDomain(websiteId uint) ([]model.WebsiteDomain, error) GetWebsiteDomain(websiteId uint) ([]model.WebsiteDomain, error)
DeleteWebsiteDomain(domainId uint) error DeleteWebsiteDomain(domainId uint) error
UpdateWebsiteDomain(req request.WebsiteDomainUpdate) error
GetNginxConfigByScope(req request.NginxScopeReq) (*response.WebsiteNginxConfig, error) GetNginxConfigByScope(req request.NginxScopeReq) (*response.WebsiteNginxConfig, error)
UpdateNginxConfigByScope(req request.NginxConfigUpdate) error UpdateNginxConfigByScope(req request.NginxConfigUpdate) error
@ -594,6 +595,42 @@ func (w WebsiteService) DeleteWebsite(req request.WebsiteDelete) error {
return nil return nil
} }
func (w WebsiteService) UpdateWebsiteDomain(req request.WebsiteDomainUpdate) error {
domain, err := websiteDomainRepo.GetFirst(commonRepo.WithByID(req.ID))
if err != nil {
return err
}
domain.SSL = req.SSL
website, err := websiteRepo.GetFirst(commonRepo.WithByID(domain.WebsiteID))
if err != nil {
return err
}
if website.Protocol == constant.ProtocolHTTPS {
nginxFull, err := getNginxFull(&website)
if err != nil {
return nil
}
nginxConfig := nginxFull.SiteConfig
config := nginxFull.SiteConfig.Config
server := config.FindServers()[0]
var params []string
if domain.SSL {
params = append(params, "ssl", "http2")
}
server.UpdateListen(strconv.Itoa(domain.Port), false, params...)
if website.IPV6 {
server.UpdateListen("[::]:"+strconv.Itoa(domain.Port), false, params...)
}
if err = nginx.WriteConfig(config, nginx.IndentedStyle); err != nil {
return err
}
if err = nginxCheckAndReload(nginxConfig.OldContent, nginxConfig.FilePath, nginxFull.Install.ContainerName); err != nil {
return err
}
}
return websiteDomainRepo.Save(context.TODO(), &domain)
}
func (w WebsiteService) CreateWebsiteDomain(create request.WebsiteDomainCreate) ([]model.WebsiteDomain, error) { func (w WebsiteService) CreateWebsiteDomain(create request.WebsiteDomainCreate) ([]model.WebsiteDomain, error) {
var ( var (
domainModels []model.WebsiteDomain domainModels []model.WebsiteDomain
@ -929,17 +966,25 @@ func (w WebsiteService) OpWebsiteHTTPS(ctx context.Context, req request.WebsiteH
if !req.Enable { if !req.Enable {
website.Protocol = constant.ProtocolHTTP website.Protocol = constant.ProtocolHTTP
website.WebsiteSSLID = 0 website.WebsiteSSLID = 0
//httpsPort := req.HttpsPort
//if len(httpsPort) == 0 { httpsPorts, err := getHttpsPort(&website)
// _, httpsPort, err = getAppInstallPort(constant.AppOpenresty) if err != nil {
// if err != nil { return nil, err
// return nil, err }
// } if len(httpsPorts) == 1 && httpsPorts[0] == nginxInstall.HttpsPort {
//} httpsPortStr := strconv.Itoa(httpsPorts[0])
//httpsPortStr := strconv.Itoa(httpsPort) if err = deleteListenAndServerName(website, []string{httpsPortStr, "[::]:" + httpsPortStr}, []string{}); err != nil {
//if err = deleteListenAndServerName(website, []string{httpsPortStr, "[::]:" + httpsPortStr}, []string{}); err != nil { return nil, err
// return nil, err }
//} } else {
for _, port := range httpsPorts {
httpsPortStr := strconv.Itoa(port)
if err = removeSSLListen(website, []string{httpsPortStr}); err != nil {
return nil, err
}
}
}
nginxParams := getNginxParamsFromStaticFile(dto.SSL, nil) nginxParams := getNginxParamsFromStaticFile(dto.SSL, nil)
nginxParams = append(nginxParams, nginxParams = append(nginxParams,
dto.NginxParam{ dto.NginxParam{

View File

@ -460,7 +460,7 @@ func addListenAndServerName(website model.Website, domains []model.WebsiteDomain
if website.Protocol == constant.ProtocolHTTPS && domain.SSL { if website.Protocol == constant.ProtocolHTTPS && domain.SSL {
params = append(params, "ssl", "http2") params = append(params, "ssl", "http2")
} }
server.AddListen(strconv.Itoa(domain.Port), false, params...) server.UpdateListen(strconv.Itoa(domain.Port), false, params...)
if website.IPV6 { if website.IPV6 {
server.UpdateListen("[::]:"+strconv.Itoa(domain.Port), false, params...) server.UpdateListen("[::]:"+strconv.Itoa(domain.Port), false, params...)
} }
@ -495,6 +495,26 @@ func deleteListenAndServerName(website model.Website, binds []string, domains []
return nginxCheckAndReload(nginxConfig.OldContent, nginxConfig.FilePath, nginxFull.Install.ContainerName) return nginxCheckAndReload(nginxConfig.OldContent, nginxConfig.FilePath, nginxFull.Install.ContainerName)
} }
func removeSSLListen(website model.Website, binds []string) error {
nginxFull, err := getNginxFull(&website)
if err != nil {
return nil
}
nginxConfig := nginxFull.SiteConfig
config := nginxFull.SiteConfig.Config
server := config.FindServers()[0]
for _, bind := range binds {
server.UpdateListen(bind, false)
if website.IPV6 {
server.UpdateListen("[::]:"+bind, false)
}
}
if err := nginx.WriteConfig(config, nginx.IndentedStyle); err != nil {
return err
}
return nginxCheckAndReload(nginxConfig.OldContent, nginxConfig.FilePath, nginxFull.Install.ContainerName)
}
func createPemFile(website model.Website, websiteSSL model.WebsiteSSL) error { func createPemFile(website model.Website, websiteSSL model.WebsiteSSL) error {
nginxApp, err := appRepo.GetFirst(appRepo.WithKey(constant.AppOpenresty)) nginxApp, err := appRepo.GetFirst(appRepo.WithKey(constant.AppOpenresty))
if err != nil { if err != nil {

View File

@ -28,6 +28,7 @@ func (a *WebsiteRouter) InitRouter(Router *gin.RouterGroup) {
websiteRouter.GET("/domains/:websiteId", baseApi.GetWebDomains) websiteRouter.GET("/domains/:websiteId", baseApi.GetWebDomains)
websiteRouter.POST("/domains/del", baseApi.DeleteWebDomain) websiteRouter.POST("/domains/del", baseApi.DeleteWebDomain)
websiteRouter.POST("/domains", baseApi.CreateWebDomain) websiteRouter.POST("/domains", baseApi.CreateWebDomain)
websiteRouter.POST("/domains/update", baseApi.UpdateWebDomain)
websiteRouter.GET("/:id/config/:type", baseApi.GetWebsiteNginx) websiteRouter.GET("/:id/config/:type", baseApi.GetWebsiteNginx)
websiteRouter.POST("/config", baseApi.GetNginxConfig) websiteRouter.POST("/config", baseApi.GetNginxConfig)

View File

@ -123,6 +123,7 @@ export namespace Website {
port: number; port: number;
id: number; id: number;
domain: string; domain: string;
ssl: boolean;
} }
export interface DomainCreate { export interface DomainCreate {
@ -130,6 +131,11 @@ export namespace Website {
domains: SubDomain[]; domains: SubDomain[];
} }
export interface DomainUpdate {
id: number;
ssl: boolean;
}
interface SubDomain { interface SubDomain {
domain: string; domain: string;
port: number; port: number;

View File

@ -62,6 +62,10 @@ export const CreateDomain = (req: Website.DomainCreate) => {
return http.post<any>(`/websites/domains`, req); return http.post<any>(`/websites/domains`, req);
}; };
export const UpdateDomain = (req: Website.DomainUpdate) => {
return http.post<any>(`/websites/domains/update`, req);
};
export const GetNginxConfig = (req: Website.NginxScopeReq) => { export const GetNginxConfig = (req: Website.NginxScopeReq) => {
return http.post<Website.NginxScopeConfig>(`/websites/config`, req); return http.post<Website.NginxScopeConfig>(`/websites/config`, req);
}; };

View File

@ -2132,6 +2132,8 @@ const message = {
enableSSLHelper: 'Failure to enable will not affect the creation of the website', enableSSLHelper: 'Failure to enable will not affect the creation of the website',
batchAdd: 'Batch Add Domains', batchAdd: 'Batch Add Domains',
generateDomain: 'Generate', generateDomain: 'Generate',
domainSSLHelper:
'Enabling SSL on a non-443 port will cause the 443 port to stop listening. If you need the 443 port to continue listening, please add the domain:443',
}, },
php: { php: {
short_open_tag: 'Short tag support', short_open_tag: 'Short tag support',

View File

@ -1982,6 +1982,7 @@ const message = {
enableSSLHelper: '開啟失敗不會影響網站創建', enableSSLHelper: '開啟失敗不會影響網站創建',
batchAdd: '批量添加域名', batchAdd: '批量添加域名',
generateDomain: '生成', generateDomain: '生成',
domainSSLHelper: ' 443 端口開啟 SSL 會導致 443 端口移除監聽如需 443 端口繼續監聽請添加域名:443',
}, },
php: { php: {
short_open_tag: '短標簽支持', short_open_tag: '短標簽支持',

View File

@ -1984,6 +1984,7 @@ const message = {
enableSSLHelper: '开启失败不会影响网站创建', enableSSLHelper: '开启失败不会影响网站创建',
batchAdd: '批量添加域名', batchAdd: '批量添加域名',
generateDomain: '生成', generateDomain: '生成',
domainSSLHelper: ' 443 端口开启 SSL 会导致 443 端口去掉监听如需 443 端口继续监听请添加域名:443',
}, },
php: { php: {
short_open_tag: '短标签支持', short_open_tag: '短标签支持',

View File

@ -2,6 +2,7 @@
<ComplexTable :data="data" @search="search" v-loading="loading" :heightDiff="400"> <ComplexTable :data="data" @search="search" v-loading="loading" :heightDiff="400">
<template #toolbar> <template #toolbar>
<el-button type="primary" plain @click="openCreate">{{ $t('website.addDomain') }}</el-button> <el-button type="primary" plain @click="openCreate">{{ $t('website.addDomain') }}</el-button>
<el-text type="info" class="!ml-2">{{ $t('website.domainSSLHelper') }}</el-text>
</template> </template>
<el-table-column width="30px"> <el-table-column width="30px">
<template #default="{ row }"> <template #default="{ row }">
@ -10,6 +11,11 @@
</el-table-column> </el-table-column>
<el-table-column :label="$t('website.domain')" prop="domain"></el-table-column> <el-table-column :label="$t('website.domain')" prop="domain"></el-table-column>
<el-table-column :label="$t('commons.table.port')" prop="port"></el-table-column> <el-table-column :label="$t('commons.table.port')" prop="port"></el-table-column>
<el-table-column :label="'SSL'" prop="ssl">
<template #default="{ row }">
<el-switch v-model="row.ssl" @change="update(row)" :disabled="row.port == 80" />
</template>
</el-table-column>
<fu-table-operations <fu-table-operations
:ellipsis="1" :ellipsis="1"
:buttons="buttons" :buttons="buttons"
@ -25,12 +31,13 @@
<script lang="ts" setup> <script lang="ts" setup>
import Domain from './create/index.vue'; import Domain from './create/index.vue';
import { Website } from '@/api/interface/website'; import { Website } from '@/api/interface/website';
import { DeleteDomain, GetWebsite, ListDomains } from '@/api/modules/website'; import { DeleteDomain, GetWebsite, ListDomains, UpdateDomain } from '@/api/modules/website';
import { computed, onMounted, ref } from 'vue'; import { computed, onMounted, ref } from 'vue';
import i18n from '@/lang'; import i18n from '@/lang';
import { Promotion } from '@element-plus/icons-vue'; import { Promotion } from '@element-plus/icons-vue';
import { GlobalStore } from '@/store'; import { GlobalStore } from '@/store';
import { CheckAppInstalled } from '@/api/modules/app'; import { CheckAppInstalled } from '@/api/modules/app';
import { MsgSuccess } from '@/utils/message';
const globalStore = GlobalStore(); const globalStore = GlobalStore();
const props = defineProps({ const props = defineProps({
@ -126,6 +133,16 @@ const onCheck = async () => {
.catch(() => {}); .catch(() => {});
}; };
const update = async (row: Website.Domain) => {
try {
await UpdateDomain({
id: row.id,
ssl: row.ssl,
});
MsgSuccess(i18n.global.t('commons.msg.updateSuccess'));
} catch {}
};
onMounted(() => { onMounted(() => {
search(id.value); search(id.value);
getWebsite(id.value); getWebsite(id.value);