// 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 }
func (r *ThingsController) Create(ctx context.Context) error { data, dataErr := ctx.RequestData() if dataErr != nil { return goweb.API.RespondWithError(ctx, http.StatusInternalServerError, dataErr.Error()) } dataMap := data.(map[string]interface{}) thing := new(Thing) thing.Id = dataMap["Id"].(string) thing.Text = dataMap["Text"].(string) r.Things = append(r.Things, thing) return goweb.Respond.WithStatus(ctx, http.StatusCreated) }
//add error catching here. func (r *UniversumController) Read(brand string, ctx context.Context) error { fmt.Println("rest") query := ctx.HttpRequest().URL.RawQuery //metric_name := GetQueryValue("name",query) since_str := GetQueryValue("since", query) const shortForm = "2006-Jan-02" since, _ := time.Parse(shortForm, since_str) until_str := GetQueryValue("until", query) until, _ := time.Parse(shortForm, until_str) resolution := "day" key := GetQueryValue("apikey", query) fmt.Println("the api key is " + key) user_id := db.Read("universum", "apikeys", key) if len(user_id) < 1 { errObject := "unverified api key" return goweb.API.RespondWithError(ctx, 500, errObject) } if brand == "ranking" { ranking := new(RankingData) ranking.Type = brand ranking.Brands, ranking.Change = GetMetrics(brand, query, since, until, resolution) return goweb.API.RespondWithData(ctx, ranking) } data := new(Data) data.Brand = brand data.Metrics, data.TimeStamp = GetMetrics(brand, query, since, until, resolution) fmt.Println("booyay") return goweb.API.RespondWithData(ctx, data) }
// WillHandle checks whether this handler will be used to handle the specified // request or not. func (p *PathMatchHandler) WillHandle(c context.Context) (bool, error) { // check each matcher func matcherFuncMatches := true matcherFuncDecisionMade := false for _, matcherFunc := range p.MatcherFuncs { decision, matcherFuncErr := matcherFunc(c) if matcherFuncErr != nil { return false, matcherFuncErr } switch decision { case NoMatch: matcherFuncMatches = false matcherFuncDecisionMade = true break case Match: matcherFuncMatches = true matcherFuncDecisionMade = true break } if matcherFuncDecisionMade { break } } // check HTTP methods var httpMethodMatch bool = false if len(p.HttpMethods) == 0 { // no specific HTTP methods httpMethodMatch = true } else { for _, httpMethod := range p.HttpMethods { if httpMethod == c.MethodString() { httpMethodMatch = true break } } } // cancel early if we didn't get an HTTP Method match if !httpMethodMatch { return false, nil } // check path match pathMatch := p.PathPattern.GetPathMatch(c.Path()) var allMatch bool if matcherFuncDecisionMade { allMatch = matcherFuncMatches } else { allMatch = pathMatch.Matches } if allMatch { // save the match parameters for later c.Data().Set(context.DataKeyPathParameters, pathMatch.Parameters) } return allMatch, nil }
// 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 }