贝利信息

LinkedIn API URL编码问题的正确解决方案

日期:2026-01-18 00:00 / 作者:聖光之護

linkedin v1 api对括号等特殊字符的url编码有特殊要求,直接使用go标准库的`http.newrequest`会导致路径被过度编码而失败;通过手动设置`url.opaque`字段可绕过自动编码,精准构造合法请求路径。

在调用 LinkedIn v1 REST API 时,字段选择器(如 ~:(id,first-name,last-name))中的圆括号 ( 和 ) 在语义上属于路径结构的一部分,不应被 URL 编码。然而,Go 的 net/http 标准库在解析完整 URL 字符串(如 "https://api.linkedin.com/v1/people/~:(id,first-name,last-name)")时,会自动对路径中非安全字符(包括 ( 和 ))进行百分号编码(即转为 %28 和 %29),导致 LinkedIn 服务端无法识别该字段语法,返回 404 及 [invalid.property.name] 错误。

根本原因在于:LinkedIn v1 API 的路径语法是自定义 DSL(类似 OData 选择器),其括号并非传统 URI 中需编码的分隔符,而是资源投影表达式的必需符号。因此,必须确保这些字符以原始形式出现在最终 HTTP 请求行的 path 部分。

✅ 正确做法是避免让 http.NewRequest 解析含特殊符号的完

整 URL,而是拆解为协议+主机+端口,并通过 URL.Opaque 手动注入未编码的路径:

r, err := http.NewRequest("GET", "https://api.linkedin.com", nil)
if err != nil {
    log.Fatal("Failed to create request:", err)
}
// 关键:绕过自动编码,直接设定原始路径(含未编码的括号)
r.URL.Opaque = "/v1/people/~:(id,first-name,last-name)"
r.Header.Set("Authorization", "Bearer "+respBody.AccessToken)
r.Header.Set("x-li-format", "json") // 推荐显式声明 JSON 响应格式

resp, err := http.DefaultClient.Do(r)
if err != nil {
    log.Fatal("Request failed:", err)
}
defer resp.Body.Close()

⚠️ 注意事项:

总结:这不是 Go 编码逻辑的缺陷,而是 API 设计与标准 URI 规范的冲突。URL.Opaque 是 Go 提供的标准、安全、无副作用的绕过机制,是处理此类“伪标准 API”的最佳实践。