// WriteResponseObject writes the status code and response object to the HttpResponseWriter in // the specified context, in the format best suited based on the request. // // Goweb uses the WebCodecService to decide which codec to use when responding // see http://godoc.org/github.com/stretchrcom/codecs/services#WebCodecService for more information. // // This method should be used when the Goweb Standard Response Object does not satisfy the needs of // the API, but other Respond* methods are recommended. func (a *GowebAPIResponder) WriteResponseObject(ctx context.Context, status int, responseObject interface{}) error { service := a.GetCodecService() acceptHeader := ctx.HttpRequest().Header.Get("Accept") extension := ctx.FileExtension() hasCallback := len(ctx.QueryValue("callback")) > 0 codec, codecError := service.GetCodecForResponding(acceptHeader, extension, hasCallback) if codecError != nil { return codecError } var options map[string]interface{} // do we need to add some options? if hasCallback { options = map[string]interface{}{constants.OptionKeyClientCallback: ctx.QueryValue("callback")} } output, marshalErr := codec.Marshal(responseObject, options) if marshalErr != nil { return marshalErr } // use the HTTP responder to respond ctx.HttpResponseWriter().Header().Set("Content-Type", codec.ContentType()) // TODO: test me a.httpResponder.With(ctx, status, output) return nil }
// Handle writes the error from the context into the HttpResponseWriter with a // 500 http.StatusInternalServerError status code. func (h *DefaultErrorHandler) Handle(ctx context.Context) (stop bool, err error) { var handlerError HandlerError = ctx.Data().Get(DataKeyForError).(HandlerError) hostname, _ := os.Hostname() w := ctx.HttpResponseWriter() // write the error out w.Header().Set("Content-Type", "text/html") w.WriteHeader(http.StatusInternalServerError) w.Write([]byte("<!DOCTYPE html><html><head>")) w.Write([]byte("<style>")) w.Write([]byte("h1 { font-size: 17px }")) w.Write([]byte("h1 strong {text-decoration:underline}")) w.Write([]byte("h2 { background-color: #ffd; padding: 20px }")) w.Write([]byte("footer { margin-top: 20px; border-top:1px solid black; padding:10px; font-size:0.9em }")) w.Write([]byte("</style>")) w.Write([]byte("</head><body>")) w.Write([]byte(fmt.Sprintf("<h1>Error in <code>%s</code></h1><h2>%s</h2>", handlerError.Handler, handlerError))) w.Write([]byte(fmt.Sprintf("<h3><code>%s</code> error in Handler <code>%v</code></h3> <code><pre>%s</pre></code>", reflect.TypeOf(handlerError.OriginalError), &handlerError.Handler, handlerError.Handler))) w.Write([]byte(fmt.Sprintf("on %s", hostname))) w.Write([]byte("<footer>Learn more about <a href='http://github.com/stretchrcom/goweb' target='_blank'>Goweb</a></footer>")) w.Write([]byte("</body></html>")) // responses are actually ignored return false, nil }
// Before gets called before any other method. func (r *ThingsController) Before(ctx context.Context) error { // set a Things specific header ctx.HttpResponseWriter().Header().Set("X-Things-Controller", "true") return nil }
// With writes a response to the request in the specified context. func (r *GowebHTTPResponder) With(ctx context.Context, httpStatus int, body []byte) error { r.WithStatus(ctx, httpStatus) _, writeErr := ctx.HttpResponseWriter().Write(body) return writeErr }
// WithPermanentRedirect responds with a redirection to the specific path or URL with the // http.StatusMovedPermanently status. func (r *GowebHTTPResponder) WithPermanentRedirect(ctx context.Context, pathOrURLSegments ...interface{}) error { ctx.HttpResponseWriter().Header().Set("Location", paths.PathFromSegments(pathOrURLSegments...)) return r.WithStatus(ctx, http.StatusMovedPermanently) }
// WithStatus writes the specified HTTP Status Code to the Context's ResponseWriter. func (r *GowebHTTPResponder) WithStatus(ctx context.Context, httpStatus int) error { ctx.HttpResponseWriter().WriteHeader(httpStatus) return nil }