douzhu5900 2016-07-26 07:32
浏览 31
已采纳

扩展golang的http包

I would need to extend http package to achieve non standard response containing error description in status ie: 400 Required parameter is missing instead of 400 Bad request that is standard status description.

This is my actual implementation:

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)
}

In general I need to forward that status from other URL that uses it and I need to keep it compatible.

Thank you very much in advance.

Jozef

  • 写回答

1条回答 默认 最新

  • dongshao9106 2016-07-26 10:20
    关注

    You can use the http.Hijacker interface 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 to return "400 Required parameter is missing" instead of the standard "400 Bad request" response to the client:

    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 
    
            bufrw.WriteString("HTTP/1.1 400 Required parameter is missing
    Content-Type: text/html; charset=utf-8
    
    ")
            // write the body of the HTTP response message
            bufrw.WriteString("400 Required parameter is missing
    ")
            bufrw.Flush()
        })
        http.ListenAndServe(":9000", nil)
    }
    

    Running this program and sending a curl request produces the desired response:

    $ 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
    

    It should be straightforward to extend it to propagate other responses from your legacy API server.

    Edit
    used in the example program to terminate the Headers portion of the HTTP response in accordance with the HTTP message standard (https://tools.ietf.org/html/rfc7230#section-3); separated WriteString calls for the headers and body of the HTTP response for clarity.

    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论

报告相同问题?

悬赏问题

  • ¥15 单片机学习顺序问题!!
  • ¥15 ikuai客户端多拨vpn,重启总是有个别重拨不上
  • ¥20 关于#anlogic#sdram#的问题,如何解决?(关键词-performance)
  • ¥15 相敏解调 matlab
  • ¥15 求lingo代码和思路
  • ¥15 公交车和无人机协同运输
  • ¥15 stm32代码移植没反应
  • ¥15 matlab基于pde算法图像修复,为什么只能对示例图像有效
  • ¥100 连续两帧图像高速减法
  • ¥15 如何绘制动力学系统的相图