«net/url» не может проанализировать URL с помощью фунта

# #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 vs PathEscape . Может ли кто-нибудь подтвердить, что пароль с помощью 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 как и ожидалось.