首页 > 解决方案 > 如何将 GET 请求重定向到包含一些数据的 POST 请求?

问题描述

当用户使用 GET 请求点击某个 url 时,我想将他们重定向到另一个位置的 POST 请求。

package main


import (
    "bytes"
    "fmt"
    "io/ioutil"
    "log"
    "net/http"
    "net/url"
)

func old(w http.ResponseWriter, r *http.Request) {
    newURL := "/new"
    var bdy = []byte(`title=Buy cheese and bread for breakfast.`)

    r.Method = "POST"
    r.URL, _ = url.Parse(newURL)
    r.RequestURI = newURL
    r.Body = ioutil.NopCloser(bytes.NewReader(bdy))
    r.Header.Set("Content-Type", "application/x-www-form-urlencoded")
    http.Redirect(w, r, newURL, 302)
}

func new(w http.ResponseWriter, r *http.Request) {
    r.ParseForm()
    fmt.Printf("Method:%v\n", r.Method)
    fmt.Printf("Title:%v\n", r.Form.Get("title"))
}

func main() {
    http.HandleFunc("/", old)
    http.HandleFunc("/new", new)
    port := 8000
    fmt.Printf("listening on %v\n", port)
    if err := http.ListenAndServe(fmt.Sprintf(":%v", port), nil); err != nil {
        log.Fatal("ListenAndServe: ", err)
    }
}

当我点击“/”时,我最终被重定向到“/new”,但是有一个 GET 请求并且没有表单数据:

Method:GET
Title:

如果我直接卷曲“/ new”,我会得到:

curl -XPOST localhost:8000/new -d "title=Buy cheese and bread for breakfast."

Method:POST
Title:Buy cheese and bread for breakfast.

标签: go

解决方案


HTTP 重定向(即回复状态码为 301、302、307,308 和Location标头)只能将现有请求重定向到另一个位置,而不会更改请求的负载。不过,它可以在响应标头中添加一些 cookie。

为了自动将 GET 请求更改为具有特定负载的 POST 请求,您可能会尝试向客户端发送带有 a 的 HTML 页面<form method=POST...和带有隐藏输入字段的负载,即<input name=... value=... type=hidden>,然后将一些 JavaScript 添加到自动提交表单的页面. 但是这种黑客只能在浏览器中使用,并且只有在启用 JavaScript 的情况下才能使用,并且也不适用于所有类型的有效负载。

为了与更广泛的客户端保持兼容性,最好进行不同的设计,即将 GET 请求保留在重定向中,但将必要的有效负载作为参数提供给新目标,即http://new.target/foo?payload=..... 但细节取决于请求的目标可以处理什么。


推荐阅读