2015-02-16 2 views
1

Я следующий кодКак обнаружить, если редирект был вызван

package main 

import (
    "log" 
    "net/http" 
) 

func fooHandler(w http.ResponseWriter, r *http.Request) { 
    // Here an if condition, if should redirect or not 
    http.Redirect(w, r, "http://www.google.com", 301) 
    // Do something.... 
    // Call function if redirect was invoked 

} 

func main() { 
    http.HandleFunc("/", fooHandler) 
    err := http.ListenAndServe(":9090", nil) 
    if err != nil { 
     log.Fatal("ListenAndServe: ", err) 
    } 
} 

Как я могу обнаружить, если редирект был записан в объекте ответа?

+0

Как правило, если вы используете http.Redirect, вы хотели бы немедленно вернуться, так что браузер может следить за переадресацию. Могу ли я спросить, какой код придет после перенаправления? Кроме того, если вы не используете какую-либо структуру, в которой у вас есть доступ к базовому экземпляру того, что реализует http.ResponseWriter, вы не сможете узнать, что это за состояние. – user114241

+0

Поскольку у меня есть структура-оболочка, которая будет отображать html-файл или нет, если была настроена перенаправление, тогда не следует отображать html-файл. –

ответ

0

Если я вас правильно понял, вы хотите что-то больше вдоль этих линий:

func fooHandler(w http.ResponseWriter, r *http.Request) { 
    // Here an if condition, if should redirect or not 
    if needToRedirect { 
     http.Redirect(w, r, "http://www.google.com", 301) 
     return 
    } 
    // Do something.... 
    // Call function if redirect was invoked 
    // render template 
} 

Обычно в ходу мы следуем за выхода рано мантру. В вашем примере, как только вы определили, что пользователь должен быть перенаправлен (игнорируя любое другое ведение журнала, которое вы, возможно, захотите сделать), лучше сразу вернуться.

0

Вы можете проверить статус ответа (для 3xx redirection status code), так как в этом http REST driver:

req, err = http.NewRequest(verb, url, body) 

    if err != nil { 
     return nil, err 
    } 

    for k, v := range headers { 
     req.Header.Add(k, v) 
    } 

    resp, err = d.httpClient.Do(req) 

    if err != nil { 
     return nil, err 
    } 

    log.Printf("Exec responce: %v\n", resp) 

    statusCode := resp.StatusCode 


    if statusCode == 307 { // Temporary Redirect 

     // For instance (put your own code here) 

     redirectUrl, ok := resp.Header["Location"] 
     if !ok { 
      return nil, fmt.Errorf("%s %s", "Failed to redirect:", "header key 'Location' wasn't found") 
     } 
     log.Printf("Redirecting: '%s' --> '%s'", url, redirectUrl[0]) 
     url = redirectUrl[0] 
     continue 

    } 
+0

На самом деле он не может этого сделать - в этом примере 'resp' является' * http.Response', в который вы можете получить доступ к полям. В примере OPs его ответ - это http.ResponseWriter (интерфейс), который он не может получить доступ к полям (если только он не знает основную реализацию). – user114241

+0

@ user114241 согласен. Возможно, утверждение типа может работать (если OP знает о базовом типе). Подождем обратной связи OP. – VonC

+0

В целом, я больше подозреваю, что OP может использовать/записывать фреймворк, который отображает шаблон, привязанный к приемнику/методу метода, когда метод завершает выполнение. В таком случае в структуре скорее всего будет поле bool (или что-то подобное), которое будет установлено, как только будет сделан любой вызов функции «Write()» (чтобы указать, было ли написанное вещество, в свою очередь, он должен проверить код состояния, прежде чем он отобразит шаблон). – user114241

0

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

func fooHandler(w http.ResponseWriter, r *http.Request) { 
    if needToRedirect { 
     http.Redirect(w, r, "http://www.google.com", 301) 
     defer func() { 
      // stuff that only happens if redirected, but happens last 
     }() 
    } 
    // stuff that happens whether redirected or not 
    // note that this will happen before the deferred func is called 
} 

Вот документация DEFER: http://blog.golang.org/defer-panic-and-recover

Это довольно просто. Отложенный вызов будет выполняться после того, как возвращается окружающая функция (fooHandler), но она все равно будет иметь доступ к чему-либо в области fooHandler, включая именованные возвращаемые значения. Также важно отметить, что отложенная функция будет вызвана даже во время паники, хотя ничего не произойдет, если она не называет recover().

EDIT: Вот простой пример того, как это работает: http://play.golang.org/p/5TgCv4O_rA

+1

Пожалуйста, старайтесь избегать чего-то подобного, хотя 'defers' по-прежнему относительно медленны в Go (http://fr.slideshare.net/derekcollison/gophercon-2014), и веб-серверы должны быть как можно быстрее. Это также делает код гораздо менее понятным для чтения. Это также было бы более функциональным, если бы отсрочка была первой в этой функции и указала переменную, которая может быть установлена ​​как флаг внутри 'if needToRedirect {...}'. – user114241

+0

Я не знал, что перебежчики были медленными. TIL, спасибо за урок.Кроме того, если кто-то их использовал, я согласен с вашей рекомендацией по удобочитаемости. – burfl

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