Golang中API无法调用但在Postman中正常工作的解决方案

Golang中API无法调用但在Postman中正常工作的解决方案 我有一个 API “http://someurl/v1.2/auth/token/get
请求头:
Authorization basic xxxxxxxxxxxxxxxx
Content-Type application/json
请求体:

{
    "grant_type": "client_credentials"
}

这是一个 POST 请求,我能够在 Postman 中成功调用该接口,但在 Golang 中却无法调用相同的 API,可能的原因是什么?
谢谢

7 回复

你的 main.go 文件第21行是做什么的?

更多关于Golang中API无法调用但在Postman中正常工作的解决方案的实战系列教程也可以访问 https://www.itying.com/category-94-b0.html


请包含您用于发出此请求的Go代码相关部分。

结果是什么?您是否遇到任何错误?

否则如果认证信息等于客户端ID {

formData := url.Values{
	"Authorization": {"Basic xxxxxxxxxxxx"},
	"grant_type": {"client_credentials"},

}
resp, err := http.PostForm("http://=sample/v1.2/auth/token/get",formData)
fmt.Println("response from url",resp)

我仍然遇到一个错误 panic: runtime error: invalid memory address or nil pointer dereference
[signal SIGSEGV: segmentation violation code=0xffffffff addr=0x0 pc=0x25706b]

goroutine 1 [running]:
main.main()
/tmp/sandbox814824644/main.go:21 +0x22b
感谢您的热心帮助。

func main() {
    fmt.Println("hello world")
}

我收到来自URL的以下错误响应:&{401 Unauthorized 401 HTTP/1.1 1 1 map[Content-Type:[application/json; charset=utf-8] Cache-Control:[no-cache] X-Xss-Protection:[1;mode=block] Via:[1.1 google] Server:[nginx/1.13.5] Date:[Tue, 01 May 2018 07:24:39 GMT] Content-Length:[66] Www-Authenticate:[basic, bearer] Pragma:[no-cache] X-Content-Type-Options:[nosniff]] 0xc420092380 66 [] false false map[] 0xc4201b4000 } 从URL获取响应时出错

你的Go代码将 Authorizationgrant_type 都放入一个 url.Values 实例中,然后通过 http.PostForm 编码为 application/x-www-form-urlencoded。这与你在上面描述的情况不同,上面描述中 Authorization 是请求头,而请求体被编码为 application/json

尝试使用 http.NewRequest 如下(未经测试):

package main

import (
	"fmt"
	"log"
	"net/http"
	"strings"
)

func main() {
	client := &http.Client{}
	body := strings.NewReader("{\"grant_type\": \"client_credentials\"")
	req, err := http.NewRequest("POST", "https://www.httpbin.org/post", body)
	if err != nil {
		log.Panic(err)
	}
	req.Header.Add("Content-Type", "application/json")
	req.Header.Add("Authorization", "Basic xxxxxxxxxxxxxxxx")
	resp, err := client.Do(req)
	if err != nil {
		log.Panic(err)
	}
	fmt.Println(resp.Status)
}

在Go语言中调用API失败但在Postman中正常工作,通常是由于HTTP客户端配置或请求细节差异导致的。以下是常见原因及解决方案:

1. 基础认证格式问题

Postman会自动处理Basic认证,但在Go中需要手动编码:

package main

import (
    "encoding/base64"
    "fmt"
    "net/http"
    "bytes"
    "io/ioutil"
)

func main() {
    url := "http://someurl/v1.2/auth/token/get"
    
    // Basic认证编码
    username := "your_username"  // 替换为实际用户名
    password := "your_password"  // 替换为实际密码
    auth := username + ":" + password
    basicAuth := "Basic " + base64.StdEncoding.EncodeToString([]byte(auth))
    
    // 请求体
    jsonBody := []byte(`{"grant_type": "client_credentials"}`)
    
    // 创建请求
    req, err := http.NewRequest("POST", url, bytes.NewBuffer(jsonBody))
    if err != nil {
        fmt.Printf("创建请求失败: %v\n", err)
        return
    }
    
    // 设置请求头
    req.Header.Set("Authorization", basicAuth)
    req.Header.Set("Content-Type", "application/json")
    
    // 发送请求
    client := &http.Client{}
    resp, err := client.Do(req)
    if err != nil {
        fmt.Printf("请求失败: %v\n", err)
        return
    }
    defer resp.Body.Close()
    
    // 读取响应
    body, _ := ioutil.ReadAll(resp.Body)
    fmt.Printf("状态码: %d\n", resp.StatusCode)
    fmt.Printf("响应体: %s\n", string(body))
}

2. SSL/TLS证书验证问题

如果API使用HTTPS,可能需要调整TLS配置:

import "crypto/tls"

// 创建自定义HTTP客户端(跳过证书验证,仅用于测试)
client := &http.Client{
    Transport: &http.Transport{
        TLSClientConfig: &tls.Config{
            InsecureSkipVerify: true, // 生产环境不应使用
        },
    },
}

3. 超时设置

添加超时控制:

client := &http.Client{
    Timeout: 30 * time.Second, // 30秒超时
}

4. 完整的错误处理版本

package main

import (
    "encoding/base64"
    "encoding/json"
    "fmt"
    "net/http"
    "bytes"
    "io/ioutil"
    "time"
)

type TokenRequest struct {
    GrantType string `json:"grant_type"`
}

type TokenResponse struct {
    AccessToken string `json:"access_token"`
    TokenType   string `json:"token_type"`
    ExpiresIn   int    `json:"expires_in"`
}

func main() {
    url := "http://someurl/v1.2/auth/token/get"
    
    // 准备认证信息
    username := "your_client_id"
    password := "your_client_secret"
    auth := base64.StdEncoding.EncodeToString([]byte(username + ":" + password))
    
    // 准备请求体
    tokenReq := TokenRequest{
        GrantType: "client_credentials",
    }
    
    jsonBody, err := json.Marshal(tokenReq)
    if err != nil {
        fmt.Printf("JSON序列化失败: %v\n", err)
        return
    }
    
    // 创建请求
    req, err := http.NewRequest("POST", url, bytes.NewBuffer(jsonBody))
    if err != nil {
        fmt.Printf("创建请求失败: %v\n", err)
        return
    }
    
    // 设置请求头
    req.Header.Set("Authorization", "Basic "+auth)
    req.Header.Set("Content-Type", "application/json")
    req.Header.Set("User-Agent", "Go-API-Client/1.0")
    
    // 配置HTTP客户端
    client := &http.Client{
        Timeout: 30 * time.Second,
    }
    
    // 发送请求
    resp, err := client.Do(req)
    if err != nil {
        fmt.Printf("API调用失败: %v\n", err)
        return
    }
    defer resp.Body.Close()
    
    // 检查响应状态
    if resp.StatusCode != http.StatusOK {
        fmt.Printf("API返回错误状态码: %d\n", resp.StatusCode)
        body, _ := ioutil.ReadAll(resp.Body)
        fmt.Printf("错误响应: %s\n", string(body))
        return
    }
    
    // 解析成功响应
    body, err := ioutil.ReadAll(resp.Body)
    if err != nil {
        fmt.Printf("读取响应体失败: %v\n", err)
        return
    }
    
    var tokenResp TokenResponse
    if err := json.Unmarshal(body, &tokenResp); err != nil {
        fmt.Printf("JSON解析失败: %v\n", err)
        fmt.Printf("原始响应: %s\n", string(body))
        return
    }
    
    fmt.Printf("获取Token成功: %s\n", tokenResp.AccessToken)
    fmt.Printf("Token类型: %s, 过期时间: %d秒\n", tokenResp.TokenType, tokenResp.ExpiresIn)
}

调试建议

添加详细的日志输出:

// 在发送请求前添加
fmt.Printf("请求URL: %s\n", url)
fmt.Printf("请求头: %+v\n", req.Header)
fmt.Printf("请求体: %s\n", string(jsonBody))

// 在收到响应后添加
fmt.Printf("响应状态码: %d\n", resp.StatusCode)
fmt.Printf("响应头: %+v\n", resp.Header)

检查Go代码中的认证信息、URL格式和请求体是否与Postman完全一致,特别是Basic认证的编码和JSON格式。

回到顶部