2016-07-26 6 views
0

Мне нужно было бы расширить пакет http для достижения нестандартного ответа, содержащего описание ошибки в статусе, то есть: 400 Требуемый параметр отсутствует вместо 400 Базовый запрос, который является стандартным описанием статуса.Расширение пакета http galang

Это моя фактическая реализация:

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, который использует его, и мне нужно, чтобы держать его совместимым.

спасибо, что заранее.

Юзеф

+1

Какая у вас проблема? Что не работает для вас в вашей текущей реализации? Вы хотите написать прокси для некоторых устаревших API? – Nebril

+0

Да, вроде ... Проблема заключается в заголовках, которые должны быть похожими на <сообщение о статусе> Сообщение о состоянии должно содержать описание ошибки, но не такое стандартное, как 400 Плохой запрос, но 400 Требуемый параметр отсутствует или 400 Нет временной отметки в запросе или так ... –

ответ

2

Вы можете использовать интерфейс https://golang.org/pkg/net/http/#Hijackerhttp.Hijacker на «угон» (взять) соединение TCP сервера к клиенту и записывать в него пользовательский ответ. Вот модификация примера https://golang.org/pkg/net/http/#example_Hijacker вернуть «400 отсутствует обязательный параметр» вместо стандартного «400 Bad запроса» ответ клиента:

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 -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 в соответствии со стандартом HTTP-сообщение (https://tools.ietf.org/html/rfc7230#section-3); разделенный WriteString вызывает для ясности заголовки и тело ответа HTTP.

+0

TIL! Спасибо за это. – Nebril

+0

Ничего себе это довольно, но как писать заголовки и контент для этого захваченного соединения? Во всяком случае, это то, что я ищу. Заранее спасибо :) –

+0

Я модифицировал программу выше, чтобы иметь отдельные вызовы bufrw.WriteString для заголовков и тела, разделенных дополнительной строкой '\ r \ n'. Конечно, вы можете добавить больше заголовков или скопировать их из прокси-соединения. Просто помните, что с захватом у вас есть полный контроль над тем, что написано и имитирует HTTP-сервер - так, например, если важно отправить заголовок Content-Length, вы должны рассчитать длину ответа и отправить заголовок «вручную», как это сделано в Content-Type в примере. – dmitris