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:
parent
a225d2d79a
commit
e003d74506
@ -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)
|
||||||
|
}
|
||||||
|
@ -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 {
|
||||||
|
@ -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"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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{
|
||||||
|
@ -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 {
|
||||||
|
@ -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)
|
||||||
|
@ -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;
|
||||||
|
@ -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);
|
||||||
};
|
};
|
||||||
|
@ -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',
|
||||||
|
@ -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: '短標簽支持',
|
||||||
|
@ -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: '短标签支持',
|
||||||
|
@ -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);
|
||||||
|
Loading…
x
Reference in New Issue
Block a user