Skip to content

Commit

Permalink
Improve kernel API authentication (#9702)
Browse files Browse the repository at this point in the history
* 🎨 Add API `/api/network/echo`

* 🎨 Improve localhost checking

* 🎨 Add `model.CheckReadonly` for some APIs

/api/storage/setLocalStorage
/api/storage/setLocalStorageVal
/api/notebook/openNotebook
/api/notebook/removeNotebook
/api/search/removeTemplate
/api/attr/setBlockAttrs
/api/sync/importSyncProviderS3
/api/sync/importSyncProviderWebDAV
/api/riff/resetRiffCards
/api/snippet/setSnippet
/api/av/setAttributeViewBlockAttr
/api/archive/zip
/api/archive/unzip

* 🎨 Remove `model.CheckReadonly` for some APIs

/api/history/searchHistory
/api/history/getHistoryItems
/api/search/findReplace
/api/block/getParentNextChildID
/api/file/readDir
/api/sync/listCloudSyncDir
/api/asset/getDocImageAssets
/api/template/renderSprig
/api/ai/chatGPT
/api/ai/chatGPTWithAction

* 🎨 improve API `/api/network/echo`
  • Loading branch information
Zuoqiu-Yingyi authored Nov 21, 2023
1 parent 70b3406 commit cb016aa
Show file tree
Hide file tree
Showing 5 changed files with 110 additions and 51 deletions.
12 changes: 7 additions & 5 deletions app/src/protyle/util/compatibility.ts
Original file line number Diff line number Diff line change
Expand Up @@ -263,11 +263,13 @@ export const getLocalStorage = (cb: () => void) => {
});
cb();

// 数据兼容,移除历史数据,3.8.4 移除
fetchPost("/api/storage/removeLocalStorageVals", {
app: Constants.SIYUAN_APPID,
keys: ["leftColumn", "local-searchkey", "local-searchedata", "local-searchekeys", "local-searchetabdata", "rightColumn", "topBar"]
});
if (!window.siyuan.config.readonly) {
// 数据兼容,移除历史数据,3.8.4 移除
fetchPost("/api/storage/removeLocalStorageVals", {
app: Constants.SIYUAN_APPID,
keys: ["leftColumn", "local-searchkey", "local-searchedata", "local-searchekeys", "local-searchetabdata", "rightColumn", "topBar"]
});
}
});
};

Expand Down
65 changes: 65 additions & 0 deletions kernel/api/network.go
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,71 @@ import (
"github.com/siyuan-note/siyuan/kernel/util"
)

func echo(c *gin.Context) {
ret := gulu.Ret.NewResult()
defer c.JSON(http.StatusOK, ret)

password, passwordSet := c.Request.URL.User.Password()

var rawData any
if data, err := c.GetRawData(); nil == err {
rawData = base64.StdEncoding.EncodeToString(data)
} else {
rawData = nil
}

ret.Data = map[string]interface{}{
"Context": map[string]interface{}{
"Params": c.Params,
"HandlerNames": c.HandlerNames(),
"FullPath": c.FullPath(),
"ClientIP": c.ClientIP(),
"RemoteIP": c.RemoteIP(),
"ContentType": c.ContentType(),
"IsWebsocket": c.IsWebsocket(),
"RawData": rawData,
},
"Request": map[string]interface{}{
"Method": c.Request.Method,
"URL": c.Request.URL,
"Proto": c.Request.Proto,
"ProtoMajor": c.Request.ProtoMajor,
"ProtoMinor": c.Request.ProtoMinor,
"Header": c.Request.Header,
"ContentLength": c.Request.ContentLength,
"TransferEncoding": c.Request.TransferEncoding,
"Close": c.Request.Close,
"Host": c.Request.Host,
"Form": c.Request.Form,
"PostForm": c.Request.PostForm,
"MultipartForm": c.Request.MultipartForm,
"Trailer": c.Request.Trailer,
"RemoteAddr": c.Request.RemoteAddr,
"TLS": c.Request.TLS,
"UserAgent": c.Request.UserAgent(),
"Cookies": c.Request.Cookies(),
"Referer": c.Request.Referer(),
},
"URL": map[string]interface{}{
"EscapedPath": c.Request.URL.EscapedPath(),
"EscapedFragment": c.Request.URL.EscapedFragment(),
"String": c.Request.URL.String(),
"Redacted": c.Request.URL.Redacted(),
"IsAbs": c.Request.URL.IsAbs(),
"Query": c.Request.URL.Query(),
"RequestURI": c.Request.URL.RequestURI(),
"Hostname": c.Request.URL.Hostname(),
"Port": c.Request.URL.Port(),
},
"User": map[string]interface{}{
"Username": c.Request.URL.User.Username(),
"Password": password,
"PasswordSet": passwordSet,
"String": c.Request.URL.User.String(),
},
}
}

func forwardProxy(c *gin.Context) {
ret := gulu.Ret.NewResult()
defer c.JSON(http.StatusOK, ret)
Expand Down
56 changes: 29 additions & 27 deletions kernel/api/router.go
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,9 @@ func ServeAPI(ginServer *gin.Engine) {
ginServer.Handle("POST", "/api/system/loginAuth", model.LoginAuth)
ginServer.Handle("POST", "/api/system/logoutAuth", model.LogoutAuth)
ginServer.Handle("GET", "/api/system/getCaptcha", model.GetCaptcha)
ginServer.Handle("POST", "/api/system/setUILayout", setUILayout) // 这里不加鉴权 After modifying the access authentication code on the browser side, the other side does not refresh https://github.com/siyuan-note/siyuan/issues/8028

ginServer.Handle("GET", "/snippets/*filepath", serveSnippets)

// 需要鉴权

Expand All @@ -56,15 +59,14 @@ func ServeAPI(ginServer *gin.Engine) {
ginServer.Handle("POST", "/api/system/setAppearanceMode", model.CheckAuth, setAppearanceMode)
ginServer.Handle("POST", "/api/system/getSysFonts", model.CheckAuth, getSysFonts)
ginServer.Handle("POST", "/api/system/exit", model.CheckAuth, exit)
ginServer.Handle("POST", "/api/system/setUILayout", setUILayout) // 这里不加鉴权 After modifying the access authentication code on the browser side, the other side does not refresh https://github.com/siyuan-note/siyuan/issues/8028
ginServer.Handle("POST", "/api/system/getConf", model.CheckAuth, getConf)
ginServer.Handle("POST", "/api/system/checkUpdate", model.CheckAuth, checkUpdate)
ginServer.Handle("POST", "/api/system/exportLog", model.CheckAuth, exportLog)
ginServer.Handle("POST", "/api/system/getChangelog", model.CheckAuth, getChangelog)

ginServer.Handle("POST", "/api/storage/setLocalStorage", model.CheckAuth, setLocalStorage)
ginServer.Handle("POST", "/api/storage/setLocalStorage", model.CheckAuth, model.CheckReadonly, setLocalStorage)
ginServer.Handle("POST", "/api/storage/getLocalStorage", model.CheckAuth, getLocalStorage)
ginServer.Handle("POST", "/api/storage/setLocalStorageVal", model.CheckAuth, setLocalStorageVal)
ginServer.Handle("POST", "/api/storage/setLocalStorageVal", model.CheckAuth, model.CheckReadonly, setLocalStorageVal)
ginServer.Handle("POST", "/api/storage/removeLocalStorageVals", model.CheckAuth, model.CheckReadonly, removeLocalStorageVals)
ginServer.Handle("POST", "/api/storage/setCriterion", model.CheckAuth, model.CheckReadonly, setCriterion)
ginServer.Handle("POST", "/api/storage/getCriteria", model.CheckAuth, getCriteria)
Expand All @@ -78,12 +80,12 @@ func ServeAPI(ginServer *gin.Engine) {
ginServer.Handle("POST", "/api/account/startFreeTrial", model.CheckAuth, model.CheckReadonly, startFreeTrial)

ginServer.Handle("POST", "/api/notebook/lsNotebooks", model.CheckAuth, lsNotebooks)
ginServer.Handle("POST", "/api/notebook/openNotebook", model.CheckAuth, openNotebook)
ginServer.Handle("POST", "/api/notebook/openNotebook", model.CheckAuth, model.CheckReadonly, openNotebook)
ginServer.Handle("POST", "/api/notebook/closeNotebook", model.CheckAuth, model.CheckReadonly, closeNotebook)
ginServer.Handle("POST", "/api/notebook/getNotebookConf", model.CheckAuth, getNotebookConf)
ginServer.Handle("POST", "/api/notebook/setNotebookConf", model.CheckAuth, model.CheckReadonly, setNotebookConf)
ginServer.Handle("POST", "/api/notebook/createNotebook", model.CheckAuth, model.CheckReadonly, createNotebook)
ginServer.Handle("POST", "/api/notebook/removeNotebook", model.CheckAuth, removeNotebook)
ginServer.Handle("POST", "/api/notebook/removeNotebook", model.CheckAuth, model.CheckReadonly, removeNotebook)
ginServer.Handle("POST", "/api/notebook/renameNotebook", model.CheckAuth, model.CheckReadonly, renameNotebook)
ginServer.Handle("POST", "/api/notebook/changeSortNotebook", model.CheckAuth, model.CheckReadonly, changeSortNotebook)
ginServer.Handle("POST", "/api/notebook/setNotebookIcon", model.CheckAuth, model.CheckReadonly, setNotebookIcon)
Expand Down Expand Up @@ -122,8 +124,8 @@ func ServeAPI(ginServer *gin.Engine) {
ginServer.Handle("POST", "/api/history/rollbackDocHistory", model.CheckAuth, model.CheckReadonly, rollbackDocHistory)
ginServer.Handle("POST", "/api/history/clearWorkspaceHistory", model.CheckAuth, model.CheckReadonly, clearWorkspaceHistory)
ginServer.Handle("POST", "/api/history/reindexHistory", model.CheckAuth, model.CheckReadonly, reindexHistory)
ginServer.Handle("POST", "/api/history/searchHistory", model.CheckAuth, model.CheckReadonly, searchHistory)
ginServer.Handle("POST", "/api/history/getHistoryItems", model.CheckAuth, model.CheckReadonly, getHistoryItems)
ginServer.Handle("POST", "/api/history/searchHistory", model.CheckAuth, searchHistory)
ginServer.Handle("POST", "/api/history/getHistoryItems", model.CheckAuth, getHistoryItems)

ginServer.Handle("POST", "/api/outline/getDocOutline", model.CheckAuth, getDocOutline)
ginServer.Handle("POST", "/api/bookmark/getBookmark", model.CheckAuth, getBookmark)
Expand All @@ -141,14 +143,14 @@ func ServeAPI(ginServer *gin.Engine) {

ginServer.Handle("POST", "/api/search/searchTag", model.CheckAuth, searchTag)
ginServer.Handle("POST", "/api/search/searchTemplate", model.CheckAuth, searchTemplate)
ginServer.Handle("POST", "/api/search/removeTemplate", model.CheckAuth, removeTemplate)
ginServer.Handle("POST", "/api/search/removeTemplate", model.CheckAuth, model.CheckReadonly, removeTemplate)
ginServer.Handle("POST", "/api/search/searchWidget", model.CheckAuth, searchWidget)
ginServer.Handle("POST", "/api/search/searchRefBlock", model.CheckAuth, searchRefBlock)
ginServer.Handle("POST", "/api/search/searchEmbedBlock", model.CheckAuth, searchEmbedBlock)
ginServer.Handle("POST", "/api/search/getEmbedBlock", model.CheckAuth, getEmbedBlock)
ginServer.Handle("POST", "/api/search/fullTextSearchBlock", model.CheckAuth, fullTextSearchBlock)
ginServer.Handle("POST", "/api/search/searchAsset", model.CheckAuth, searchAsset)
ginServer.Handle("POST", "/api/search/findReplace", model.CheckAuth, model.CheckReadonly, findReplace)
ginServer.Handle("POST", "/api/search/findReplace", model.CheckAuth, findReplace)
ginServer.Handle("POST", "/api/search/fullTextSearchAssetContent", model.CheckAuth, fullTextSearchAssetContent)
ginServer.Handle("POST", "/api/search/getAssetContent", model.CheckAuth, getAssetContent)

Expand Down Expand Up @@ -183,14 +185,14 @@ func ServeAPI(ginServer *gin.Engine) {
ginServer.Handle("POST", "/api/block/getHeadingChildrenDOM", model.CheckAuth, getHeadingChildrenDOM)
ginServer.Handle("POST", "/api/block/swapBlockRef", model.CheckAuth, model.CheckReadonly, swapBlockRef)
ginServer.Handle("POST", "/api/block/transferBlockRef", model.CheckAuth, model.CheckReadonly, transferBlockRef)
ginServer.Handle("POST", "/api/block/getParentNextChildID", model.CheckAuth, model.CheckReadonly, getParentNextChildID)
ginServer.Handle("POST", "/api/block/getParentNextChildID", model.CheckAuth, getParentNextChildID)

ginServer.Handle("POST", "/api/file/getFile", model.CheckAuth, getFile)
ginServer.Handle("POST", "/api/file/putFile", model.CheckAuth, model.CheckReadonly, putFile)
ginServer.Handle("POST", "/api/file/copyFile", model.CheckAuth, model.CheckReadonly, copyFile)
ginServer.Handle("POST", "/api/file/removeFile", model.CheckAuth, model.CheckReadonly, removeFile)
ginServer.Handle("POST", "/api/file/renameFile", model.CheckAuth, model.CheckReadonly, renameFile)
ginServer.Handle("POST", "/api/file/readDir", model.CheckAuth, model.CheckReadonly, readDir)
ginServer.Handle("POST", "/api/file/readDir", model.CheckAuth, readDir)

ginServer.Handle("POST", "/api/ref/refreshBacklink", model.CheckAuth, refreshBacklink)
ginServer.Handle("POST", "/api/ref/getBacklink", model.CheckAuth, getBacklink)
Expand All @@ -200,7 +202,7 @@ func ServeAPI(ginServer *gin.Engine) {

ginServer.Handle("POST", "/api/attr/getBookmarkLabels", model.CheckAuth, getBookmarkLabels)
ginServer.Handle("POST", "/api/attr/resetBlockAttrs", model.CheckAuth, model.CheckReadonly, resetBlockAttrs)
ginServer.Handle("POST", "/api/attr/setBlockAttrs", model.CheckAuth, setBlockAttrs)
ginServer.Handle("POST", "/api/attr/setBlockAttrs", model.CheckAuth, model.CheckReadonly, setBlockAttrs)
ginServer.Handle("POST", "/api/attr/getBlockAttrs", model.CheckAuth, getBlockAttrs)

ginServer.Handle("POST", "/api/cloud/getCloudSpace", model.CheckAuth, getCloudSpace)
Expand All @@ -215,15 +217,15 @@ func ServeAPI(ginServer *gin.Engine) {
ginServer.Handle("POST", "/api/sync/setCloudSyncDir", model.CheckAuth, model.CheckReadonly, setCloudSyncDir)
ginServer.Handle("POST", "/api/sync/createCloudSyncDir", model.CheckAuth, model.CheckReadonly, createCloudSyncDir)
ginServer.Handle("POST", "/api/sync/removeCloudSyncDir", model.CheckAuth, model.CheckReadonly, removeCloudSyncDir)
ginServer.Handle("POST", "/api/sync/listCloudSyncDir", model.CheckAuth, model.CheckReadonly, listCloudSyncDir)
ginServer.Handle("POST", "/api/sync/listCloudSyncDir", model.CheckAuth, listCloudSyncDir)
ginServer.Handle("POST", "/api/sync/performSync", model.CheckAuth, model.CheckReadonly, performSync)
ginServer.Handle("POST", "/api/sync/performBootSync", model.CheckAuth, model.CheckReadonly, performBootSync)
ginServer.Handle("POST", "/api/sync/getBootSync", model.CheckAuth, getBootSync)
ginServer.Handle("POST", "/api/sync/getSyncInfo", model.CheckAuth, getSyncInfo)
ginServer.Handle("POST", "/api/sync/exportSyncProviderS3", model.CheckAuth, exportSyncProviderS3)
ginServer.Handle("POST", "/api/sync/importSyncProviderS3", model.CheckAuth, importSyncProviderS3)
ginServer.Handle("POST", "/api/sync/importSyncProviderS3", model.CheckAuth, model.CheckReadonly, importSyncProviderS3)
ginServer.Handle("POST", "/api/sync/exportSyncProviderWebDAV", model.CheckAuth, exportSyncProviderWebDAV)
ginServer.Handle("POST", "/api/sync/importSyncProviderWebDAV", model.CheckAuth, importSyncProviderWebDAV)
ginServer.Handle("POST", "/api/sync/importSyncProviderWebDAV", model.CheckAuth, model.CheckReadonly, importSyncProviderWebDAV)

ginServer.Handle("POST", "/api/inbox/getShorthands", model.CheckAuth, getShorthands)
ginServer.Handle("POST", "/api/inbox/getShorthand", model.CheckAuth, getShorthand)
Expand All @@ -243,7 +245,7 @@ func ServeAPI(ginServer *gin.Engine) {
ginServer.Handle("POST", "/api/asset/getMissingAssets", model.CheckAuth, getMissingAssets)
ginServer.Handle("POST", "/api/asset/removeUnusedAsset", model.CheckAuth, model.CheckReadonly, removeUnusedAsset)
ginServer.Handle("POST", "/api/asset/removeUnusedAssets", model.CheckAuth, model.CheckReadonly, removeUnusedAssets)
ginServer.Handle("POST", "/api/asset/getDocImageAssets", model.CheckAuth, model.CheckReadonly, getDocImageAssets)
ginServer.Handle("POST", "/api/asset/getDocImageAssets", model.CheckAuth, getDocImageAssets)
ginServer.Handle("POST", "/api/asset/renameAsset", model.CheckAuth, model.CheckReadonly, renameAsset)
ginServer.Handle("POST", "/api/asset/getImageOCRText", model.CheckAuth, model.CheckReadonly, getImageOCRText)
ginServer.Handle("POST", "/api/asset/setImageOCRText", model.CheckAuth, model.CheckReadonly, setImageOCRText)
Expand Down Expand Up @@ -284,7 +286,7 @@ func ServeAPI(ginServer *gin.Engine) {

ginServer.Handle("POST", "/api/template/render", model.CheckAuth, renderTemplate)
ginServer.Handle("POST", "/api/template/docSaveAsTemplate", model.CheckAuth, model.CheckReadonly, docSaveAsTemplate)
ginServer.Handle("POST", "/api/template/renderSprig", model.CheckAuth, model.CheckReadonly, renderSprig)
ginServer.Handle("POST", "/api/template/renderSprig", model.CheckAuth, renderSprig)

ginServer.Handle("POST", "/api/transactions", model.CheckAuth, model.CheckReadonly, performTransactions)

Expand Down Expand Up @@ -363,33 +365,33 @@ func ServeAPI(ginServer *gin.Engine) {
ginServer.Handle("POST", "/api/riff/getRiffCards", model.CheckAuth, getRiffCards)
ginServer.Handle("POST", "/api/riff/getTreeRiffCards", model.CheckAuth, getTreeRiffCards)
ginServer.Handle("POST", "/api/riff/getNotebookRiffCards", model.CheckAuth, getNotebookRiffCards)
ginServer.Handle("POST", "/api/riff/resetRiffCards", model.CheckAuth, resetRiffCards)
ginServer.Handle("POST", "/api/riff/resetRiffCards", model.CheckAuth, model.CheckReadonly, resetRiffCards)

ginServer.Handle("POST", "/api/notification/pushMsg", model.CheckAuth, pushMsg)
ginServer.Handle("POST", "/api/notification/pushErrMsg", model.CheckAuth, pushErrMsg)

ginServer.Handle("POST", "/api/snippet/getSnippet", model.CheckAuth, getSnippet)
ginServer.Handle("POST", "/api/snippet/setSnippet", model.CheckAuth, setSnippet)
ginServer.Handle("POST", "/api/snippet/setSnippet", model.CheckAuth, model.CheckReadonly, setSnippet)
ginServer.Handle("POST", "/api/snippet/removeSnippet", model.CheckAuth, model.CheckReadonly, removeSnippet)
ginServer.Handle("GET", "/snippets/*filepath", serveSnippets)

ginServer.Handle("POST", "/api/av/renderAttributeView", model.CheckAuth, renderAttributeView)
ginServer.Handle("POST", "/api/av/getAttributeViewKeys", model.CheckAuth, getAttributeViewKeys)
ginServer.Handle("POST", "/api/av/setAttributeViewBlockAttr", model.CheckAuth, setAttributeViewBlockAttr)
ginServer.Handle("POST", "/api/av/setAttributeViewBlockAttr", model.CheckAuth, model.CheckReadonly, setAttributeViewBlockAttr)

ginServer.Handle("POST", "/api/ai/chatGPT", model.CheckAuth, model.CheckReadonly, chatGPT)
ginServer.Handle("POST", "/api/ai/chatGPTWithAction", model.CheckAuth, model.CheckReadonly, chatGPTWithAction)
ginServer.Handle("POST", "/api/ai/chatGPT", model.CheckAuth, chatGPT)
ginServer.Handle("POST", "/api/ai/chatGPTWithAction", model.CheckAuth, chatGPTWithAction)

ginServer.Handle("POST", "/api/petal/loadPetals", model.CheckAuth, loadPetals)
ginServer.Handle("POST", "/api/petal/setPetalEnabled", model.CheckAuth, model.CheckReadonly, setPetalEnabled)

ginServer.Handle("POST", "/api/network/forwardProxy", model.CheckAuth, model.CheckReadonly, forwardProxy)
ginServer.Any("/api/network/echo", model.CheckAuth, echo)
ginServer.Handle("POST", "/api/network/forwardProxy", model.CheckAuth, forwardProxy)

ginServer.Handle("GET", "/ws/broadcast", model.CheckAuth, broadcast)
ginServer.Handle("GET", "/api/broadcast/channels", model.CheckAuth, getChannels)
ginServer.Handle("POST", "/api/broadcast/postMessage", model.CheckAuth, postMessage)
ginServer.Handle("POST", "/api/broadcast/getChannels", model.CheckAuth, getChannels)
ginServer.Handle("POST", "/api/broadcast/getChannelInfo", model.CheckAuth, getChannelInfo)

ginServer.Handle("POST", "/api/archive/zip", model.CheckAuth, zip)
ginServer.Handle("POST", "/api/archive/unzip", model.CheckAuth, unzip)
ginServer.Handle("POST", "/api/archive/zip", model.CheckAuth, model.CheckReadonly, zip)
ginServer.Handle("POST", "/api/archive/unzip", model.CheckAuth, model.CheckReadonly, unzip)
}
4 changes: 3 additions & 1 deletion kernel/model/session.go
Original file line number Diff line number Diff line change
Expand Up @@ -163,10 +163,12 @@ func CheckAuth(c *gin.Context) {
// 未设置访问授权码
if "" == Conf.AccessAuthCode {
// Authenticate requests with the Origin header other than 127.0.0.1 https://github.com/siyuan-note/siyuan/issues/9180
clientIP := c.ClientIP()
host := c.GetHeader("Host")
origin := c.GetHeader("Origin")
forwardedHost := c.GetHeader("X-Forwarded-Host")
if !localhost ||
("" != clientIP && !util.IsLocalHostname(clientIP)) ||
("" != host && !util.IsLocalHost(host)) ||
("" != origin && !util.IsLocalOrigin(origin) && !strings.HasPrefix(origin, "chrome-extension://")) ||
("" != forwardedHost && !util.IsLocalHost(forwardedHost)) {
Expand Down Expand Up @@ -243,7 +245,7 @@ func CheckAuth(c *gin.Context) {
if workspaceSession.AccessAuthCode != Conf.AccessAuthCode {
userAgentHeader := c.GetHeader("User-Agent")
if strings.HasPrefix(userAgentHeader, "SiYuan/") || strings.HasPrefix(userAgentHeader, "Mozilla/") {
if "GET" != c.Request.Method {
if "GET" != c.Request.Method || c.IsWebsocket() {
c.JSON(http.StatusUnauthorized, map[string]interface{}{"code": -1, "msg": Conf.Language(156)})
c.Abort()
return
Expand Down
24 changes: 6 additions & 18 deletions kernel/util/net.go
Original file line number Diff line number Diff line change
Expand Up @@ -47,23 +47,8 @@ func ValidOptionalPort(port string) bool {
return true
}

func SplitHost(host string) (hostname, port string) {
hostname = host

colon := strings.LastIndexByte(hostname, ':')
if colon != -1 && ValidOptionalPort(hostname[colon:]) {
hostname, port = hostname[:colon], hostname[colon+1:]
}

if strings.HasPrefix(hostname, "[") && strings.HasSuffix(hostname, "]") {
hostname = hostname[1 : len(hostname)-1]
}

return
}

func IsLocalHostname(hostname string) bool {
if "localhost" == hostname {
if "localhost" == hostname || strings.HasSuffix(hostname, ".localhost") {
return true
}
if ip := net.ParseIP(hostname); nil != ip {
Expand All @@ -73,8 +58,11 @@ func IsLocalHostname(hostname string) bool {
}

func IsLocalHost(host string) bool {
hostname, _ := SplitHost(host)
return IsLocalHostname(hostname)
if hostname, _, err := net.SplitHostPort(strings.TrimSpace(host)); nil != err {
return false
} else {
return IsLocalHostname(hostname)
}
}

func IsLocalOrigin(origin string) bool {
Expand Down

0 comments on commit cb016aa

Please sign in to comment.