FAQ
Hello,

Here is a beginner's question. Sorry that it's a bit long. I'd be happy
if somebody could help.

I am trying to turn an existing http.ResponseWriter into a new object, also
implementing the http.ResponseWriter interface. The new object should do
the following:
- in the WriteHeader method, set a session cookie before writing the header
- pass on everything else to the given parent ResponseWriter.

The following is a failed attempt to implement this:

--------------------------------------------------------------------------
type SessionResponseWriter struct {
     http.ResponseWriter
     SessionId []byte
}

func (w *SessionResponseWriter) WriteHeader(code int) {
     setSessionCookie(w, w.SessionId, sessionTimeoutSeconds)
     w.ResponseWriter.WriteHeader(code)
}
--------------------------------------------------------------------------

The above compiles, but does not work. The Write method seems to not call
my version of the WriteHeader method and thus the session cookie das not
get set if the user calls .Write().

I managed to fix the problem, using the following code:

--------------------------------------------------------------------------
type SessionResponseWriter struct {
     parent http.ResponseWriter
     wroteHeader bool
     SessionId []byte
}

func (w *SessionResponseWriter) Header() http.Header {
     return w.parent.Header()
}

func (w *SessionResponseWriter) Write(data []byte) (int, error) {
     if !w.wroteHeader {
         w.WriteHeader(http.StatusOK)
     }
     n, err := w.parent.Write(data)
     return n, err
}

func (w *SessionResponseWriter) WriteHeader(code int) {
     w.wroteHeader = true
     setSessionCookie(w.parent, w.SessionId, sessionTimeoutSeconds)
     w.parent.WriteHeader(code)
}
--------------------------------------------------------------------------

This works, but looks ugly:
- The wroteHeader logic is now present both in w and in w.parent. This
looks like unnecessary duplication to me.
- The new Header() method doesn't do anything interesting. Do I really
need to write this out?

My question: Is there a better way of solving this problem?

Many thanks,
Jochen

--
You received this message because you are subscribed to the Google Groups "golang-nuts" group.
To unsubscribe from this group and stop receiving emails from it, send an email to [email protected].
For more options, visit https://groups.google.com/groups/opt_out.

Search Discussions

  • Jesse McNelis at May 17, 2013 at 1:21 pm
    On Fri, May 17, 2013 at 8:38 PM, Jochen Voss wrote:

    Note that Go doesn't have inheritance so it doesn't support the concept of
    'subclassing'.
    Embedding is just composition with automatic method call forwarding. You
    get a tiny bit more code duplication, but you get less coupling and more
    straight forward code.


    type SessionResponseWriter struct {
    http.ResponseWriter
    wroteHeader bool
    SessionId []byte
    }

    func (w *SessionResponseWriter) Write(data []byte) (int, error) {
    if !w.wroteHeader {
    w.WriteHeader(http.StatusOK)
    }
    n, err := w.ResponseWriter.Write(data)
    return n, err
    }

    func (w *SessionResponseWriter) WriteHeader(code int) {
    w.wroteHeader = true
    setSessionCookie(w.parent, w.SessionId, sessionTimeoutSeconds)
    w.ResponseWriter.WriteHeader(code)
    }
    --------------------------------------------------------------------------
    This works, but looks ugly:
    - The wroteHeader logic is now present both in w and in w.parent. This
    looks like unnecessary duplication to me.
    It's not unnecessary duplication.


    - The new Header() method doesn't do anything interesting. Do I really
    need to write this out?
    You can drop the Header() method by just embedding the ResponseWriter as
    above.

    --
    You received this message because you are subscribed to the Google Groups "golang-nuts" group.
    To unsubscribe from this group and stop receiving emails from it, send an email to [email protected].
    For more options, visit https://groups.google.com/groups/opt_out.
  • Jochen Voss at May 17, 2013 at 3:38 pm
    Dear Jesse,

    Thanks a lot for your answer.
    On Friday, 17 May 2013 14:20:58 UTC+1, Jesse McNelis wrote:

    On Fri, May 17, 2013 at 8:38 PM, Jochen Voss <[email protected]<javascript:>
    wrote:
    type SessionResponseWriter struct {
    http.ResponseWriter
    wroteHeader bool
    SessionId []byte
    }

    func (w *SessionResponseWriter) Write(data []byte) (int, error) {
    if !w.wroteHeader {
    w.WriteHeader(http.StatusOK)
    }
    n, err := w.ResponseWriter.Write(data)
    return n, err
    }

    func (w *SessionResponseWriter) WriteHeader(code int) {
    w.wroteHeader = true
    setSessionCookie(w.parent, w.SessionId, sessionTimeoutSeconds)
    w.ResponseWriter.WriteHeader(code)
    }
    --------------------------------------------------------------------------
    This works, but looks ugly:
    - The wroteHeader logic is now present both in w and in w.parent. This
    looks like unnecessary duplication to me.
    It's not unnecessary duplication.
    The parent ResponseWriter will still have its own wroteHeader field. I
    believe that this field is completely unused, since it's function has now
    been taken over by the corresponding field in SessionResponseWriter. But I
    guess that this is unavoidable with my approach ...

    - The new Header() method doesn't do anything interesting. Do I really
    need to write this out?
    You can drop the Header() method by just embedding the ResponseWriter as
    above.
    Thanks, I tried and this worked for me.

    Many thanks,
    Jochen

    --
    You received this message because you are subscribed to the Google Groups "golang-nuts" group.
    To unsubscribe from this group and stop receiving emails from it, send an email to [email protected].
    For more options, visit https://groups.google.com/groups/opt_out.
  • Jesse McNelis at May 18, 2013 at 4:33 am

    On 18/05/2013 1:38 AM, "Jochen Voss" wrote:
    The parent ResponseWriter will still have its own wroteHeader field.
    ResponseWriter is an interface. It doesn't have fields. An implementation
    might, but it would be a violation of the interface for you to care about
    that.

    --
    You received this message because you are subscribed to the Google Groups "golang-nuts" group.
    To unsubscribe from this group and stop receiving emails from it, send an email to [email protected].
    For more options, visit https://groups.google.com/groups/opt_out.

Related Discussions

Discussion Navigation
viewthread | post
Discussion Overview
groupgolang-nuts @
categoriesgo
postedMay 17, '13 at 1:01p
activeMay 18, '13 at 4:33a
posts4
users2
websitegolang.org

2 users in discussion

Jochen Voss: 2 posts Jesse McNelis: 2 posts

People

Translate

site design / logo © 2023 Grokbase