Golang HTTPS/TLS POST 客户端/服务器

huangapple go评论87阅读模式
英文:

Golang HTTPS/TLS POST client/server

问题

我已经写了一个简单的Go客户端/服务器,可以通过TLS进行HTTP GET,但我也想让它能够通过TLS进行HTTP POST。

在下面的示例中,index.html只包含文本hello,HTTP GET正常工作。我希望客户端能够获取HTTP GET并将hello world写回服务器。

客户端:

package main

import (
    "crypto/tls"
    "fmt"
    "io/ioutil"
    "net/http"
    "strings"
)

func main() {
    link := "https://10.0.0.1/static/index.html"

    tr := &http.Transport{
        TLSClientConfig: &tls.Config{InsecureSkipVerify: true},
    }
    client := &http.Client{Transport: tr}
    response, err := client.Get(link)
    if err != nil {
        fmt.Println(err)
    }
    defer response.Body.Close()

    content, _ := ioutil.ReadAll(response.Body)
    s := strings.TrimSpace(string(content))

    fmt.Println(s)

    out := s + " world"
    resp, err := client.Post(link, "text/plain", strings.NewReader(out))
    if err != nil {
        fmt.Println(err)
    }
    defer resp.Body.Close()

    // 处理POST响应
    // ...

}

服务器:

package main

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

func main() {
    http.HandleFunc("/static/", func(w http.ResponseWriter, r *http.Request) {
        fmt.Println("Got connection!")
        http.ServeFile(w, r, r.URL.Path[1:])
    })
    log.Fatal(http.ListenAndServeTLS(":443", "server.crt", "server.key", nil))
}

我目前还没有处理服务器端的POST请求,但我只是希望它将其打印到屏幕上,这样当我运行客户端时,我将看到服务器打印出hello world

如何修复我的客户端代码以进行正确的POST?相应的服务器代码应该是什么样的以接受POST请求?任何帮助将不胜感激,我很难找到HTTPS/TLS POST的示例。

英文:

I have written a simple client/server in Go that will do an HTTP GET over TLS, but I'm trying to also make it capable of doing an HTTP POST over TLS.

In the example below index.html just contains the text hello, and the HTTP GET is working fine. I want the client to get the HTTP GET and write back, hello world to the server.

client

package main

import (
    "crypto/tls"
    "fmt"
    "io/ioutil"
    "net/http"
	"strings"
)

func main() {
	link := "https://10.0.0.1/static/index.html"

    tr := &http.Transport{
        TLSClientConfig: &tls.Config{InsecureSkipVerify: true},
    }
    client := &http.Client{Transport: tr}
    response, err := client.Get(link)
    if err != nil {
        fmt.Println(err)
    }
	defer response.Body.Close()
	
	content, _ := ioutil.ReadAll(response.Body)
	s := strings.TrimSpace(string(content))
	
	fmt.Println(s)

    // out := s + " world"    	
    // Not working POST...
	// resp, err := client.Post(link, "text/plain", &out)

}

server

package main

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

func main() {
    http.HandleFunc("/static/", func (w http.ResponseWriter, r *http.Request) {
        fmt.Println("Got connection!")
        http.ServeFile(w, r, r.URL.Path[1:])
    })
    log.Fatal(http.ListenAndServeTLS(":443", "server.crt", "server.key", nil))
}

I also currently have nothing to handle the POST on the server side, but I just want it to print it out to the screen so when I run the client I will see the server print hello world.

How should I fix my client code to do a proper POST? And what should the corresponding server code look like to accept the POST? Any help would be appreciated, I'm having trouble finding HTTPS/TLS POST examples.

答案1

得分: 2

你没有分享错误信息,但我猜测client.Post调用不允许将字符串作为其第三个参数,因为它需要一个io.Reader。请尝试使用以下代码:

out := s + " world"     
resp, err := client.Post(link, "text/plain", bytes.NewBufferString(out))

在服务器端,你已经设置了正确的代码来处理POST请求。只需检查请求的方法:

http.HandleFunc("/static/", func (w http.ResponseWriter, r *http.Request) {
    if r.Method == "POST" {
        // 处理POST请求
    } else {
        // 处理其他请求
    }
})

我注意到还有另一个问题。在这里使用index.html可能行不通。http.ServeFile会重定向该路径。请参考https://golang.org/pkg/net/http/#ServeFile:
> 作为特例,ServeFile会将任何以"/index.html"结尾的请求重定向到相同的路径,但不包括最后的"index.html"。要避免这种重定向,要么修改路径,要么使用ServeContent。

我建议使用不同的文件名来避免这个问题。

英文:

You didn't share the error message, but I assume the client.Post call wasn't allowing a string as its third parameter, because it requires an io.Reader. Try this instead:

out := s + " world"     
resp, err := client.Post(link, "text/plain", bytes.NewBufferString(out))

On the server side, you already have the right code set up to handle the POST request. Just check the method:

http.HandleFunc("/static/", func (w http.ResponseWriter, r *http.Request) {
    if r.Method == "POST" {
        // handle POST requests
    } else {
        // handle all other requests
    }
})

I noticed one other issue. Using index.html probably won't work here. http.ServeFile will redirect that path. See https://golang.org/pkg/net/http/#ServeFile:
> As a special case, ServeFile redirects any request where r.URL.Path
> ends in "/index.html" to the same path, without the final
> "index.html". To avoid such redirects either modify the path or use
> ServeContent.

I'd suggest just using a different file name to avoid that issue.

huangapple
  • 本文由 发表于 2016年10月17日 01:04:35
  • 转载请务必保留本文链接:https://go.coder-hub.com/40072965.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定