Golang http客户端总是执行get请求而不执行post



我现在遇到了一个问题,这真的让我很沮丧,我完全看不到我的代码有任何问题。

我试图实现的是发送一个http POST消息到我编写的iDrac模型(两个软件都是用golang编写的)来控制模型的powerstate,但是无论我为请求配置什么,模型总是接收带有空体的get请求。

创建并发送请求的函数:

func (iDrac *IDrac) SetPowerstate(powerstate string) error {
//Create reset type json string
var jsonStr = `{"ResetType":"` + powerstate + `"}`
//Create the request with auth header
req, reqErr := iDrac.buildHttpRequestWithAuthorizationHeader(http.MethodPost, "https://"+iDrac.hostAddress+apiBaseURL+apiChassisURL+apiChassisResetAction, jsonStr)
if reqErr != nil {
return fmt.Errorf("COULD_NOT_CREATE_REQUEST: " + reqErr.Error())
}
req.Header.Set("Content-Type", "application/json; charset=UTF-8")
//Make the request
resp, doErr := http.DefaultClient.Do(req)
if doErr != nil {
return fmt.Errorf("COULD_NOT_SEND_POST_REQUEST_TO_IDRAC_API" + doErr.Error())
}
//Check if the request was successful
if resp.StatusCode != 200 {
return fmt.Errorf("COULD_NOT_CHANGE_SERVER_POWER_STATUS_OVER_IDRAC HTTP:" + resp.Status)
}
return nil
}

我用来构建请求的辅助函数:

func (iDrac *IDrac) buildHttpRequestWithAuthorizationHeader(method string, url string, content string) (*http.Request, error) {
req, err := http.NewRequest(method, url, bytes.NewBuffer([]byte(content)))
if err != nil {
return nil, err
}
req.Header.Add("Authorization", "Basic "+iDrac.hashedCredentials)
return req, nil
}
最后是模型处理请求的函数:
func handlePerformReset(w http.ResponseWriter, r *http.Request) {
garbagelog.Log("Handling reset perform request from " + r.RemoteAddr)
if r.Method != http.MethodPost {
garbagelog.Log("Invalid http method! Got " + r.Method + " expected POST")
w.WriteHeader(405)
return
}
if !checkAuthorization(r.BasicAuth()) {
w.WriteHeader(401)
return
}
var resetType nidrac.ResetType
err := json.NewDecoder(r.Body).Decode(&resetType)
if err != nil {
garbagelog.Log("Could not decode reset type: " + err.Error())
w.WriteHeader(422)
return
}
iDracMock.PerformResetAction(resetType.ResetType)
garbagelog.Log(">>>>SEVERSTATE: " + iDracMock.PowerState().PowerState + "<<<<")
w.WriteHeader(200)
}

iDrac模拟试图将正文转换为的类型:

type ResetType struct {
ResetType string
}

它的工作完美无瑕,当我试图达到终点邮差:确认请求成功的iDrac模型日志

邮件请求配置:邮差请求配置

但是当我尝试用go代码请求时,它不知何故不起作用:iDrac模型日志说http方法无效(因为它是get而不是post)

我花了两个小时试图找到一个解决方案,但不知怎么的,我没有找到一个帖子,有人有同样的问题,我有。

编辑:更正旧代码。即使修正了愚蠢的错误,问题仍然存在:

//Create the request with auth header
req, reqErr := iDrac.buildHttpRequestWithAuthorizationHeader(http.MethodPost, "https://"+iDrac.hostAddress+apiBaseURL+apiChassisURL+apiChassisResetAction, jsonStr)
if reqErr != nil {
return fmt.Errorf("COULD_NOT_CREATE_REQUEST: " + reqErr.Error())
}

如何在iDrac模型中构建路由:

http.Handle("/", http.HandlerFunc(handleDefault))
http.Handle("/reset", http.HandlerFunc(handleReset))
http.Handle("/redfish/v1/Systems/System.Embedded.1", http.HandlerFunc(handlePowerStateGet))
http.Handle("/redfish/v1/Systems/System.Embedded.1/Actions/ComputerSystem.Reset", http.HandlerFunc(handlePerformReset))
garbagelog.Log("Starting webserver")
err := http.ListenAndServeTLS(":443", currentConfig.CertFile, currentConfig.PrivKeyFile, nil)
if err != nil {
garbagelog.Log("Could not serve TLS: " + err.Error())
}

在两个请求中,在我的iDrac通信模块中创建的请求和iDrac模型接收的请求都确认请求的路径是:

r.URL。Path =/redfish/v1/Systems/System.Embedded.1/Actions/ComputerSystem.Reset

我发现问题了:

构建url的常量定义如下:

const (
apiBaseURL            = "/redfish/v1/"
apiChassisURL         = "/Systems/System.Embedded.1"
apiChassisResetAction = "/Actions/ComputerSystem.Reset"
)

指向如下url:

https://host/redfish/v1//Systems/System.Embedded.1/Actions/ComputerSystem.Reset(注意v1和Systems之间的双精度//)

所以我已经修复了它:

const (
apiBaseURL            = "/redfish/v1"
apiChassisURL         = "/Systems/System.Embedded.1"
apiChassisResetAction = "/Actions/ComputerSystem.Reset"
)

一切正常工作:测试结果显示每次测试都成功

我感谢大家的意见,帮助我没有完全失去理智。

根据你的截图,我可以看到你正在使用"POST"请求在你的邮差中,但在你的代码中是"GET"

我认为代码没有问题,只是方法有问题:)

相关内容

最新更新