Плюс и амперсанд потерялись в URL Go-клиента: как собрать query
Поисковый запрос A&B+C отправили внешнему API склеиванием строк, и сервер получил другие параметры. Символы & и + имеют специальное значение в форме query. Неправильная сборка меняет запрос до того, как его увидит бизнес-логика.
Как разобрать ситуацию
Используйте url.Values и Encode для значений параметров. Это сохраняет разделение между структурой query и пользовательским текстом. Не экранируйте готовую строку целиком и не применяйте одну процедуру одинаково к path и query: это разные части URL. На стороне получения проверяйте декодированное значение, а не внешний вид процента в адресе.
Пример и ожидаемый результат
Пример создаёт единственный параметр q со значением A&B+C, кодирует его и снова разбирает. Правильный круговой результат сохраняет исходный текст и ровно один ключ. При ручном добавлении &B возник бы дополнительный параметр.
package main
import (
"fmt"
"net/url"
)
func main() {
q := url.Values{}
q.Set("q", "A&B+C")
parsed, err := url.ParseQuery(q.Encode())
if err != nil {
panic(err)
}
fmt.Println(parsed.Get("q"), len(parsed))
}
Программа выводит A&B+C 1: текст восстановлен точно, число ключей равно одному. Это локальная проверка кодирования без вызова внешнего API.
Проверка перед применением
- Проверьте пробел, плюс, амперсанд, кириллицу и пустое значение.
- Для повторяемого параметра используйте несколько значений осознанно, не перезаписывайте их случайным Set.
- Не выводите полный URL в журнал, если query содержит персональные или секретные данные.
Для подписи API проверяйте точную каноническую форму по контракту поставщика: порядок параметров, повторяющиеся ключи и кодирование пробела могут иметь значение. Успешное round-trip декодирование подтверждает сохранность текста, но не гарантирует, что подпись совпадёт с чужим алгоритмом без отдельной тестовой пары.
Границы решения
Правильное экранирование не заменяет проверку допустимого хоста и пути. Если пользователь управляет целым URL, возникает отдельная задача ограничения сетевого доступа. Также поставщик может использовать собственную канонизацию при подписи запросов.
Если базовый Go уже знаком и хочется связать HTTP, хранение данных и обработку отказов в одну систему, посмотрите наш платный курс
Микросервисы на Go: HTTP, PostgreSQL, gRPC, Kafka и Docker. Перед записью сравните программу со своей задачей и подготовкой.
Техническая справка: pkg.go.dev: документация.
Следующий шаг: Go backend: HTTP, конкурентность и устойчивость сервиса. По смежным вопросам: Отмена HTTP-запроса в Go: как убедиться, что context дошёл до клиента, Как оборачивать ошибки в Go и не потерять машинную проверку причины.
