扩展golang的http包
Extending golang's http package
我需要扩展 http 包以实现在状态中包含错误描述的非标准响应,即:
400 缺少必需的参数
而不是标准状态描述的 400 错误请求。
这是我的实际实现:
package main
import (
"fmt"
"io"
"io/ioutil"
"net/http"
"net/url"
)
type GatewayHandler int
func main() {
var gh GatewayHandler
http.ListenAndServe(":9000", gh)
}
func (gh GatewayHandler) ServeHTTP(res http.ResponseWriter, req *http.Request) {
legacyApiUrl := "http://some-url.com" + req.URL.RequestURI()
client := &http.Client{}
request, _ := http.NewRequest(req.Method, legacyApiUrl, nil)
response, _ := client.Do(request)
res.Header().Set("Status", response.Status)
for k, v := range response.Header {
fmt.Println(k, ": ", v)
i := ""
for _, j := range v {
i += j
}
res.Header().Set(k, i)
}
res.WriteHeader(response.StatusCode)
if response.Status != "200 OK" {
fmt.Println(response.Status)
}
result, _ := ioutil.ReadAll(response.Body)
output := string(result)
fmt.Println(output)
io.WriteString(res, output)
}
一般来说,我需要从使用它的其他 URL 转发该状态,并且我需要保持它的兼容性。
非常感谢您。
约瑟夫
您可以使用 http.Hijacker
接口 https://golang.org/pkg/net/http/#Hijacker to "hijack" (take over) the server's TCP connection to the client and write to it the custom response. Here is a modification of the example https://golang.org/pkg/net/http/#example_Hijacker 到 return “400 Required parameter is missing”,而不是对客户端的标准“400 Bad request”响应:
package main
import "net/http"
func main() {
http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
hj, ok := w.(http.Hijacker)
if !ok {
http.Error(w, "webserver doesn't support hijacking", http.StatusInternalServerError)
return
}
conn, bufrw, err := hj.Hijack()
if err != nil {
http.Error(w, err.Error(), http.StatusInternalServerError)
return
}
// Don't forget to close the connection:
defer conn.Close()
// non-standard HTTP status text and an HTTP header are written;
// end of the Headers part of the messages is marked by extra \r\n
bufrw.WriteString("HTTP/1.1 400 Required parameter is missing\r\nContent-Type: text/html; charset=utf-8\r\n\r\n")
// write the body of the HTTP response message
bufrw.WriteString("400 Required parameter is missing\n")
bufrw.Flush()
})
http.ListenAndServe(":9000", nil)
}
运行 这个程序和发送 curl 请求会产生所需的响应:
$ curl -i http://localhost:9000/
HTTP/1.1 400 Required parameter is missing
Content-Type: text/html; charset=utf-8
400 Required parameter is missing
扩展它以传播来自旧 API 服务器的其他响应应该很简单。
编辑
在示例程序中使用 \r\n\r\n
根据 HTTP 消息标准 (https://www.rfc-editor.org/rfc/rfc7230#section-3) 终止 HTTP 响应的 Headers 部分;为清楚起见,分开 WriteString
调用 HTTP 响应的 headers 和 body。
我需要扩展 http 包以实现在状态中包含错误描述的非标准响应,即: 400 缺少必需的参数 而不是标准状态描述的 400 错误请求。
这是我的实际实现:
package main
import (
"fmt"
"io"
"io/ioutil"
"net/http"
"net/url"
)
type GatewayHandler int
func main() {
var gh GatewayHandler
http.ListenAndServe(":9000", gh)
}
func (gh GatewayHandler) ServeHTTP(res http.ResponseWriter, req *http.Request) {
legacyApiUrl := "http://some-url.com" + req.URL.RequestURI()
client := &http.Client{}
request, _ := http.NewRequest(req.Method, legacyApiUrl, nil)
response, _ := client.Do(request)
res.Header().Set("Status", response.Status)
for k, v := range response.Header {
fmt.Println(k, ": ", v)
i := ""
for _, j := range v {
i += j
}
res.Header().Set(k, i)
}
res.WriteHeader(response.StatusCode)
if response.Status != "200 OK" {
fmt.Println(response.Status)
}
result, _ := ioutil.ReadAll(response.Body)
output := string(result)
fmt.Println(output)
io.WriteString(res, output)
}
一般来说,我需要从使用它的其他 URL 转发该状态,并且我需要保持它的兼容性。
非常感谢您。
约瑟夫
您可以使用 http.Hijacker
接口 https://golang.org/pkg/net/http/#Hijacker to "hijack" (take over) the server's TCP connection to the client and write to it the custom response. Here is a modification of the example https://golang.org/pkg/net/http/#example_Hijacker 到 return “400 Required parameter is missing”,而不是对客户端的标准“400 Bad request”响应:
package main
import "net/http"
func main() {
http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
hj, ok := w.(http.Hijacker)
if !ok {
http.Error(w, "webserver doesn't support hijacking", http.StatusInternalServerError)
return
}
conn, bufrw, err := hj.Hijack()
if err != nil {
http.Error(w, err.Error(), http.StatusInternalServerError)
return
}
// Don't forget to close the connection:
defer conn.Close()
// non-standard HTTP status text and an HTTP header are written;
// end of the Headers part of the messages is marked by extra \r\n
bufrw.WriteString("HTTP/1.1 400 Required parameter is missing\r\nContent-Type: text/html; charset=utf-8\r\n\r\n")
// write the body of the HTTP response message
bufrw.WriteString("400 Required parameter is missing\n")
bufrw.Flush()
})
http.ListenAndServe(":9000", nil)
}
运行 这个程序和发送 curl 请求会产生所需的响应:
$ curl -i http://localhost:9000/ HTTP/1.1 400 Required parameter is missing Content-Type: text/html; charset=utf-8 400 Required parameter is missing
扩展它以传播来自旧 API 服务器的其他响应应该很简单。
编辑
在示例程序中使用 \r\n\r\n
根据 HTTP 消息标准 (https://www.rfc-editor.org/rfc/rfc7230#section-3) 终止 HTTP 响应的 Headers 部分;为清楚起见,分开 WriteString
调用 HTTP 响应的 headers 和 body。