# #go
Вопрос:
У меня есть следующий код.
главное.вперед:
package main
import "fmt"
import "net/url"
func main() {
connString := "postgresql://postgres:password@192.168.1.10:5432/postgres"
parsedUrl, err := url.Parse(connString)
if err != nil {
fmt.Println(err)
}
fmt.Println("=")
fmt.Println(parsedUrl.User)
fmt.Println("=")
}
Исполнение:
$ go run main.go
=
postgres:password
=
Пока все хорошо, вы могли видеть, что мы успешно справляемся parsedUrl.User
postgres:password
. Проблемы возникают, когда я меняю пароль, к password#
которому привязан.
connString := "postgresql://postgres:password#@192.168.1.10:5432/postgres"
Затем запустите его снова, он отобразится следующим образом:
=
=
Вы могли видеть, что код не может быть извлечен postgres:password#
. Это выглядит #
в html как якорь, это основная причина?
Подводя итог, мой вопрос таков: как я мог бы исправить свой код, чтобы справиться с ситуацией, которая у меня есть #
в пароле?
Ответ №1:
Да, #
указывает на фрагмент.
Способ решить эту проблему состоял бы в том, чтобы сбежать от #
персонажа:
connString := fmt.Sprintf("postgresql://postgres:password%s@192.168.1.10:5432/postgres", url.PathEscape("#"))
parsedUrl, _ := url.Parse(connString)
fmt.Println(url.PathUnescape(parsedUrl.User.String()))
И на выходе:
postgres:password# <nil>
Комментарии:
1. Другой ответ предполагает использование
QueryEscape()
. Какой из них правильный?2. Внешность
PathEscape
идентична, заQueryEscape
исключением того , чтоPathEscape
будет кодировать пространство, в то время
QueryEscape
как будет кодировать пространство.
QueryEscape
возникнет проблема приparsedUrl.User.Password()
последующем звонке, если в моем пароле также есть место, напримерpass word#
. Поэтому на этот раз я выбираю вPathEscape
качестве своего перфера, так как, похоже, встречается больше разных паролей, хотя немного странно, чтоPathUnescape
их нельзя найти в моем локальном(golang 1.12), но это не большая проблема.3. url.PathUnescape был введен в
go 1.8
— он должен быть доступен вgo 1.12
4. Хотя
url.PathUnescape
это не мой вопрос, но @colm.anseo Спасибо за напоминание, ДА, моя вина вurl.Parse(connString)
том, что я снова присвоил возвращаемое значениеurl
,url.PathUnescape
действительно работает.
Ответ №2:
Вы можете использовать url.QueryEscape()
Пример
package main
import (
"fmt"
"net/url"
)
func main() {
connString := `postgresql://postgres:` url.QueryEscape(`password#`) `@192.168.1.10:5432/postgres`
xurl, err := url.Parse(connString)
if err != nil {
fmt.Println(err)
}
fmt.Println("=")
fmt.Println(xurl.User.Username())
fmt.Println(xurl.User.Password())
fmt.Println("=")
}
Комментарии:
1. Мне нравится
xurl.User.Password()
здесь, как это работает, не вызывая никаких неэскейпов, это волшебно и наводит на мысли, поэтому я тоже поддерживаю это, спасибо, не могу понять, почему ребята будут отвергать это без каких-либо объяснений.2. Я поддерживаю высокую оценку .
url.User..Password()
Возможно, понижение, которое мы наблюдаем, связано с различиями в бегстве отQueryEscape
vsPathEscape
. Может ли кто-нибудь подтвердить, что пароль с помощьюspace : # amp; /
postgres работает или нет, используя любую экранированную строку подключения?3.@colm.anseo, я сделал этот пример: play.golang.org/p/pNuBsWf-U_i с
PathEscape
space : # amp; /
работами. но не тот же результат при использовании.QueryEscape
…. я в замешательстве. // вывод примера: ` пароль :=#:/password # / :
` = путь = postgres #:/пароль # / : истина = ===================== = QueryEscape = postgres #:/пароль # / : true =4. Это все решает.
PathEscape
работает с этим методомurl.User.Password()
извлечения — но нетQueryEscape
. Вы можете увидеть разницу в кодировке этих двух методов здесь . Я также хотел бы убедиться, что сервер postgres с установленным паролем принимает этот тип строки подключения.5. К вашему сведению, я только что подтвердил
postgresql 13
, что сервер, заданный паролем с множеством специальных символов, принимаетurl. PathEscape
экранирование и завершается неудачей,url.QueryEscape
как и ожидалось.