0

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

4

1 に答える 1

2

http.Hijackerインターフェースhttps://golang.org/pkg/net/http/#Hijackerを使用して、サーバーのクライアントへの TCP 接続を「ハイジャック」 (乗っ取り) し、それにカスタム応答を書き込むことができます。クライアントへの標準の「400 Bad request」応答の代わりに「400 Required parameter is missing」を返すようにhttps://golang.org/pkg/net/http/#example_Hijackerの例を変更したものを次に示します。

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 必須パラメーターがありません
コンテンツ タイプ: テキスト/html; 文字セット=utf-8

400 必要なパラメータがありません

レガシー API サーバーからの他の応答を伝播するように拡張するのは簡単です。


サンプル プログラムで使用される編集は、HTTP メッセージ標準 ( https://www.rfc-editor.org/rfc/rfc7230#section-3 )\r\n\r\nに従って HTTP 応答のヘッダー部分を終了します。わかりやすくするために、HTTP 応答のヘッダーと本文の呼び出しを分離しました。WriteString

于 2016-07-26T10:20:49.790 に答える