2016-02-20 6 views
3

Я кодирую веб-приложение в Go, а в то время как различные библиотеки мультиплексоров предоставляют способ установки пользовательского обработчика ошибок 404, нет ничего для других кодов ошибок 4xx и 5xx.Переопределение интерфейса ResponseWriter для улавливания ошибок HTTP

Одно из предложений заключается в том, чтобы переопределить метод WriteHeader в интерфейсе ResponseWriter и проверить код состояния, но я смущен тем, как это было бы фактически записано (переопределение методов ResponseWriter до вывода). Один из возможных примеров можно найти на странице negroni package.

Будет ли это правильным способом обслуживания настраиваемого шаблона для ошибок 4xx и 5xx? Может ли кто-нибудь привести пример того, как это можно реализовать?

Update

Большое спасибо Давиду и elithrar их ответов и кода. Структура Interceptor, которую Дэвид закодировал, может использоваться в оболочке для серверного мультиплексирования, как показывает elithrar в комментариях. Для тех, кто ищет дополнительные объяснения относительно того, почему и как это работает, this section from astaxie's book дает очень хорошую информацию о работе пакета net/http, а также просматривает server.go source code из пакета net/http.

ответ

2

В библиотеках мультиплексоров есть только способ установки обработчика не найденного объекта как средство предоставления вам способа перехвата запросов, когда мультиплексор не может разрешить URL-адрес для его известных сопоставлений.

Например, вы делаете:

mux.Handle("/foo",fooFunc) 
mux.Handle("/bar",barFunc) 

Но клиент получает доступ /baz к которому у Мультиплексор имеет никакого отображения.

Они фактически не перехватывают 404, идущих к клиенту, они просто вызывают не найденный обработчик, когда он сталкивается с этой проблемой.

Кроме того, если ваш обработчик foo отправляет ответ 404, то не найденный не вызывает.

Если вы хотите, чтобы пользовательские страницы отображали различные обратные ответы из ваших сопоставленных URL-адресов, просто сделайте различные обработчики, чтобы написать правильный ответ.

Если вы не контролируете эту логику (то есть: кадрирование что-то пишет и не имеет возможности переопределить), тогда вы можете перехватить все запросы и переопределить http.ResposeWriter с логикой обнаружения кода ответа.

Вот пример перехватчика, который в основном делает то, что вы хотите. По Play

package main 

import (
    "fmt" 
    "log" 
) 
import "net/http" 

type Interceptor struct { 
    origWriter http.ResponseWriter 
    overridden bool 
} 

func (i *Interceptor) WriteHeader(rc int) { 
    switch rc { 
    case 500: 
     http.Error(i.origWriter, "Custom 500 message/content", 500) 
    case 404: 
     http.Error(i.origWriter, "Custom 404 message", 404) 
    case 403: 
     i.origWriter.WriteHeader(403) 
     fmt.Fprintln(i.origWriter, "Custom 403 message") 
    default: 
     i.origWriter.WriteHeader(rc) 
     return 
    } 
    // if the default case didn't execute (and return) we must have overridden the output 
    i.overridden = true 
    log.Println(i.overridden) 
} 

func (i *Interceptor) Write(b []byte) (int, error) { 
    if !i.overridden { 
     return i.origWriter.Write(b) 
    } 

    // Return nothing if we've overriden the response. 
    return 0, nil 
} 

func (i *Interceptor) Header() http.Header { 
    return i.origWriter.Header() 
} 
+0

Большое спасибо за пример! Я думаю, что я понимаю, что вы имеете в виду, когда мои обработчики могут писать конкретные ошибки 4xx и 5xx для маршрутов в соответствии с логикой приложения, не так ли? Мое беспокойство, однако, было бы ошибками, генерируемыми самим сетью/http-пакетом, и просто соблюдением всех, совместимых с одной страницей ошибок. Где именно у меня есть '& Interceptor {origWriter: nil}', поэтому я могу заменить nil на фактический 'http.ResponseWriter'? Я думаю, что он пойдет в функцию «ServeHTTP» для моего собственного «http.Handler», но не уверен, как это будет выглядеть (или если это так). Еще раз спасибо! – eclipse1121

+0

Не могли бы вы показать, что он используется в 'main()' с простым вызовом 'http.Handle', например ' http.Ручка ("/ test", InterceptHandler) ' (если это правильный путь)? – eclipse1121

+0

@ eclipse1121 Оберните весь мукс с помощью некоторого промежуточного программного обеспечения, которое заменит ResponseWriter по умолчанию на InterceptWriter - http://play.golang.org/p/esiiY7p-CC – elithrar

Смежные вопросы