// Before gets called before any other method. func (r *DevelopersController) Before(ctx context.Context) error { // set a Developers specific header ctx.HttpResponseWriter().Header().Set("X-Developers-Controller", "true") ctx.HttpResponseWriter().Header().Set("Connection", "keep-alive") return nil }
// GET /api/session func (ctrl *SessionController) ReadMany(ctx context.Context) (err error) { session, _ := session_store.Get(ctx.HttpRequest(), session_name) if session.Values["username"] != nil { return goweb.API.RespondWithError(ctx, http.StatusBadRequest, "has session") } // check form value(not empty?) id := ctx.FormValue("id") passwd := ctx.FormValue("password") if id == "" || passwd == "" { return goweb.API.RespondWithError(ctx, http.StatusBadRequest, "not enough query") } // get userdata from database user, err := GetUser(id, passwd) if err != nil { return goweb.API.RespondWithError(ctx, http.StatusInternalServerError, "error on database") } if user == nil { return goweb.API.RespondWithError(ctx, http.StatusUnauthorized, "user not found") } session.Values["username"] = user.Name session.Save(ctx.HttpRequest(), ctx.HttpResponseWriter()) return goweb.API.RespondWithData(ctx, 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/stretchr/goweb' target='_blank'>Goweb</a></footer>")) w.Write([]byte("</body></html>")) // responses are actually ignored return false, nil }
func serializeGowebResponse( c context.Context, syntaxName string, statements chan *goraptor.Statement) error { var str string if syntaxName == "trig" { // real trig mode is crashing serializer := goraptor.NewSerializer("ntriples") defer serializer.Free() ntriples, err := serializer.Serialize(statements, "") if err != nil { panic(err) } log.Printf("got %d bytes of ntriples", len(ntriples)) str = "<http://projects.bigasterisk.com/room/laundryDoor> { " + ntriples + "}" log.Printf("str now %d bytes", len(str)) } else { serializer := goraptor.NewSerializer(syntaxName) defer serializer.Free() var err error str, err = serializer.Serialize(statements, "") if err != nil { panic(err) } } c.HttpResponseWriter().Header().Set("Content-Type", goraptor.SerializerSyntax[syntaxName].MimeType) return goweb.Respond.With(c, 200, []byte(str)) }
// Before gets called before any other method. func (r *BooksController) Before(ctx context.Context) error { // set a Books specific header ctx.HttpResponseWriter().Header().Set("X-Books-Controller", "true") return nil }
// 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/stretchr/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(CallbackParameter)) > 0 codec, codecError := service.GetCodecForResponding(acceptHeader, extension, hasCallback) if codecError != nil { return codecError } options := ctx.CodecOptions() // do we need to add some options? if _, exists := options[constants.OptionKeyClientCallback]; hasCallback && !exists { options[constants.OptionKeyClientCallback] = ctx.QueryValue(CallbackParameter) } output, marshalErr := service.MarshalWithCodec(codec, 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 }
// 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 (ctrl *TokenController) ReadMany(ctx context.Context) (err error) { t, _ := generateRandomString(tokenlength) session, _ := session_store.Get(ctx.HttpRequest(), session_name) session.Values["token"] = t session.Save(ctx.HttpRequest(), ctx.HttpResponseWriter()) return goweb.API.RespondWithData(ctx, t) }
// Respond performs an API response, adding some additional data to // the context's CodecOptions to support our custom codecs. This // particular function is very specifically for use with the // github.com/stretchr/goweb web framework. // // TODO: Move the with={} parameter to options in the mimetypes in the // Accept header. func Respond(ctx context.Context, status int, notifications MessageMap, data interface{}, useFullDomain ...bool) error { body, err := web_request_readers.ParseBody(ctx) if err != nil { return err } if ctx.QueryParams().Has("joins") { if m, ok := body.(objx.Map); ok { m.Set("joins", ctx.QueryValue("joins")) } } protocol := "http" if ctx.HttpRequest().TLS != nil { protocol += "s" } host := ctx.HttpRequest().Host requestDomain := fmt.Sprintf("%s://%s", protocol, host) if status == http.StatusOK { location := "Error: no location present" if locationer, ok := data.(Locationer); ok { location = fmt.Sprintf("%s%s", requestDomain, locationer.Location()) } ctx.HttpResponseWriter().Header().Set("Location", location) if linker, ok := data.(RelatedLinker); ok { linkMap := linker.RelatedLinks() links := make([]string, 0, len(linkMap)+1) links = append(links, fmt.Sprintf(`<%s>; rel="location"`, location)) for rel, link := range linkMap { link := fmt.Sprintf(`<%s%s>; rel="%s"`, requestDomain, link, rel) links = append(links, link) } ctx.HttpResponseWriter().Header().Set("Link", strings.Join(links, ", ")) } } // Transitionary period - don't pass the domain to the codec // unless it's requested in the responder if len(useFullDomain) == 0 || useFullDomain[0] == false { requestDomain = "" } options := ctx.CodecOptions() options.MergeHere(objx.Map{ "status": status, "input_params": body, "notifications": notifications, "domain": requestDomain, }) // Right now, this line is commented out to support our joins // logic. Unfortunately, that means that codecs other than our // custom codecs from this package will not work. Whoops. // data = CreateResponse(data) return goweb.API.WriteResponseObject(ctx, status, data) }
// DELETE /api/session func (ctrl *SessionController) DeleteMany(ctx context.Context) (err error) { session, _ := session_store.Get(ctx.HttpRequest(), session_name) // clear user's session data session.Values["username"] = nil session.Save(ctx.HttpRequest(), ctx.HttpResponseWriter()) return goweb.API.RespondWithData(ctx, nil) }
// WithStatus writes the specified HTTP Status Code to the Context's ResponseWriter. // // If the Always200ParamName parameter is present, it will ignore the httpStatus argument, // and always write net/http.StatusOK (200). func (r *GowebHTTPResponder) WithStatus(ctx context.Context, httpStatus int) error { // check for always200 if len(ctx.FormValue(Always200ParamName)) > 0 { // always return OK httpStatus = http.StatusOK } ctx.HttpResponseWriter().WriteHeader(httpStatus) return nil }
func isSessionValid(ctx context.Context) bool { session, _ := session_store.Get(ctx.HttpRequest(), session_name) session_token := session.Values["token"] session.Values["token"] = "" session.Save(ctx.HttpRequest(), ctx.HttpResponseWriter()) if session_token == "" || session_token != ctx.FormValue("token") { return false } return true }
// WithStatusText writes the specified HTTP Status Code to the Context's ResponseWriter and // includes a body with the default status text. func (r *GowebHTTPResponder) WithStatusText(ctx context.Context, httpStatus int) error { writeStatusErr := r.WithStatus(ctx, httpStatus) if writeStatusErr != nil { return writeStatusErr } // write the body header _, writeErr := ctx.HttpResponseWriter().Write([]byte(http.StatusText(httpStatus))) return writeErr }
func streamDownload(ctx context.Context, n *node.Node, filename string) { nf, err := n.FileReader() defer nf.Close() if err != nil { // File not found or some sort of file read error. // Probably deserves more checking err_msg := "err:@preAuth node.FileReader: " + err.Error() logger.Error(err_msg) responder.RespondWithError(ctx, 500, err_msg) return } s := &request.Streamer{R: []file.SectionReader{nf}, W: ctx.HttpResponseWriter(), ContentType: "application/octet-stream", Filename: filename, Size: n.File.Size, Filter: nil} err = s.Stream() if err != nil { // causes "multiple response.WriteHeader calls" error but better than no response err_msg := "err:@preAuth: s.stream: " + err.Error() logger.Error(err_msg) responder.RespondWithError(ctx, 500, err_msg) } }
func (r *IceController) Read(brand string, ctx context.Context) error { fmt.Println("already interfacing with cassandra") ctx.HttpResponseWriter().Header().Set("Access-Control-Allow-Origin", "*") query := ctx.HttpRequest().URL.RawQuery id := GetQueryValue("user_id", query) column := GetQueryValue("op", query) fmt.Println(id) newsclusters := db.ReadValue("ice", "user_data", id, column) /*for _, cluster := range newsclusters { fmt.Println(cluster) }*/ fmt.Println(column) data := new(IceData) data.Output = newsclusters data.TimeStamp = []string{"testing", "timestamp"} return goweb.API.RespondWithData(ctx, data) }
func Login(ctx context.Context) error { var currentUser, ok = ctx.Data()["user"].(m.User) if ok { return goweb.API.RespondWithData(ctx, currentUser.Token) } else { username := ctx.FormValue("username") password := ctx.FormValue("password") // Check or basic auth header authHeader := ctx.HttpRequest().Header.Get("Authorization") if len(authHeader) > 0 { info, err := base64.StdEncoding.DecodeString(strings.Split(authHeader, " ")[1]) if err == nil { decryptedInfo := strings.Split(string(info), ":") username = decryptedInfo[0] password = decryptedInfo[1] } } if len(username) < 3 || len(password) < 6 { return goweb.API.Respond(ctx, 200, nil, []string{"Invalid data supplied, please fill all fields."}) } user := m.User{} query := bson.M{} if strings.Contains(username, "@") { query["username"] = username } else { query["email"] = username } err := m.GetDB("User").Find(query).One(&user) if err != nil { log.Error("Error in find user on login " + err.Error()) return goweb.API.Respond(ctx, 200, nil, []string{"No such username, please register."}) } passport := m.Passport{} err = m.GetDB("Passport").Find(bson.M{"provider": "local", "user": user.Id}).One(&passport) if err != nil { log.Error("Error in find user passport on login " + err.Error()) return goweb.API.Respond(ctx, 200, nil, []string{"You have registered through Facebook."}) } err = bcrypt.CompareHashAndPassword([]byte(passport.Password), []byte(password)) if err != nil { return goweb.API.Respond(ctx, 200, nil, []string{"Incorrect password."}) } log.Info("User found on local login") if user.Token == "" || user.TokenUpdate.Before(time.Now().AddDate(0, 0, -1)) { var token = nonce.NewToken() nonce.MarkToken(token) user.Token = token user.TokenUpdate = time.Now() err := m.GetDB("User").UpdateId(user.Id, user) if err != nil { log.Error("Failed to update token: " + err.Error()) } } ctx.HttpResponseWriter().Header().Add("cookie", "token="+user.Token) return goweb.API.RespondWithData(ctx, user.Token) } }
func write(ctx context.Context, output string) { ctx.HttpResponseWriter().Write([]byte(output)) }
// Makes sure that the Vary header is set to Accept func (controller *BaseRestController) After(ctx context.Context) error { ctx.HttpResponseWriter().Header().Set("Vary", "Accept") return 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) }
func GetTrails(ctx context.Context) error { var result []m.Track // Get the info from the context isHeatmap, err := strconv.ParseBool(ctx.FormValue("heatmap")) if err != nil { isHeatmap = false } isPersonal, err := strconv.ParseBool(ctx.FormValue("personal")) if err != nil { isPersonal = false } fromDate, fromDateExists := utils.ParseDateFromContext("from_", ctx) toDate, toDateExists := utils.ParseDateFromContext("to_", ctx) if !isPersonal { err = m.GetDB("Track").Find(bson.M{}).All(&result) } else if isPersonal { var query bson.M var currentUser, ok = ctx.Data()["user"].(m.User) if ok && !fromDateExists && !toDateExists { query = bson.M{} query["user"] = currentUser.Id err = m.GetDB("Track").Find(query).All(&result) } else if ok && fromDateExists && toDateExists { query = bson.M{"user": currentUser.Id, "date": bson.M{"$gte": fromDate, "$lte": toDate}} err = m.GetDB("Track").Find(query).All(&result) } } if !isHeatmap { mapName := "GpsTrails" var buffer bytes.Buffer buffer.WriteString("<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<kml xmlns=\"http://earth.google.com/kml/2.0\">\n<Document>\n<name>") buffer.WriteString(mapName) buffer.WriteString("</name>\n<description>Glasgow Memories Server</description>\n") for i := 0; i < len(color); i++ { buffer.WriteString("<Style id=\"line") buffer.WriteString(strconv.Itoa(i + 1)) buffer.WriteString("\">\n<LineStyle>\n<color>") buffer.WriteString(color[i%len(color)]) buffer.WriteString("</color>\n<width>4</width>\n</LineStyle>\n</Style>\n\n") } for i := 0; i < len(result); i++ { buffer.WriteString("<Placemark>\n<name>Track ") buffer.WriteString(result[i].Date.String()) buffer.WriteString("</name>\n<styleUrl>#line") buffer.WriteString(strconv.Itoa(utils.GetStyle(strings.Split(result[i].Date.String()[0:10], "-"), len(color)) + 1)) buffer.WriteString("</styleUrl>\n<LineString>\n<altitudeMode>relative</altitudeMode>\n<coordinates>\n") for j := 0; j < len(result[i].Coordinates); j++ { buffer.WriteString(result[i].Coordinates[j].Lon + "," + result[i].Coordinates[j].Lat + ",0\n") } buffer.WriteString("</coordinates>\n</LineString>\n</Placemark>\n") } buffer.WriteString("</Document>\n") buffer.WriteString("</kml>\n") ctx.HttpResponseWriter().Header().Set("Content-Type", "application/vnd.google-earth.kml+xml") ctx.HttpResponseWriter().Write([]byte(buffer.String())) return nil // return goweb.Respond.With(ctx, http.StatusOK, []byte(buffer.String())) } else { var formattedData [][]string for i := 0; i < len(result); i++ { for j := 0; j < len(result[i].Coordinates); j++ { formattedData = utils.Append(formattedData, []string{result[i].Coordinates[j].Lat, result[i].Coordinates[j].Lon}) } } return goweb.API.RespondWithData(ctx, formattedData) } }
func (i *uploadController) Before(c context.Context) error { c.HttpResponseWriter().Header().Set("X-types.UploadController", "true") return nil }
// GET: /node/{id} func (cr *NodeController) Read(id string, ctx context.Context) error { u, err := request.Authenticate(ctx.HttpRequest()) if err != nil && err.Error() != e.NoAuth { return request.AuthError(err, ctx) } // Fake public user if u == nil { if conf.Bool(conf.Conf["anon-read"]) { u = &user.User{Uuid: ""} } else { return responder.RespondWithError(ctx, http.StatusUnauthorized, e.NoAuth) } } // Gather query params query := ctx.HttpRequest().URL.Query() var fFunc filter.FilterFunc = nil if _, ok := query["filter"]; ok { if filter.Has(query.Get("filter")) { fFunc = filter.Filter(query.Get("filter")) } } // Load node and handle user unauthorized n, err := node.Load(id, u.Uuid) if err != nil { if err.Error() == e.UnAuth { return responder.RespondWithError(ctx, http.StatusUnauthorized, e.UnAuth) } else if err.Error() == e.MongoDocNotFound { return responder.RespondWithError(ctx, http.StatusNotFound, "Node not found") } else { // In theory the db connection could be lost between // checking user and load but seems unlikely. logger.Error("Err@node_Read:LoadNode:" + id + ":" + err.Error()) n, err = node.LoadFromDisk(id) if err != nil { err_msg := "Err@node_Read:LoadNodeFromDisk:" + id + ":" + err.Error() logger.Error(err_msg) return responder.RespondWithError(ctx, http.StatusInternalServerError, err_msg) } } } // Switch though param flags // ?download=1 if _, ok := query["download"]; ok { if !n.HasFile() { return responder.RespondWithError(ctx, http.StatusBadRequest, "Node has no file") } filename := n.Id if _, ok := query["filename"]; ok { filename = query.Get("filename") } if _, ok := query["index"]; ok { //handling bam file if query.Get("index") == "bai" { s := &request.Streamer{R: []file.SectionReader{}, W: ctx.HttpResponseWriter(), ContentType: "application/octet-stream", Filename: filename, Size: n.File.Size, Filter: fFunc} var region string if _, ok := query["region"]; ok { //retrieve alingments overlapped with specified region region = query.Get("region") } argv, err := request.ParseSamtoolsArgs(ctx) if err != nil { return responder.RespondWithError(ctx, http.StatusBadRequest, "Invaid args in query url") } err = s.StreamSamtools(n.FilePath(), region, argv...) if err != nil { return responder.RespondWithError(ctx, http.StatusBadRequest, "error while involking samtools") } return nil } // if forgot ?part=N if _, ok := query["part"]; !ok { return responder.RespondWithError(ctx, http.StatusBadRequest, "Index parameter requires part parameter") } // open file r, err := n.FileReader() defer r.Close() if err != nil { err_msg := "Err@node_Read:Open: " + err.Error() logger.Error(err_msg) return responder.RespondWithError(ctx, http.StatusInternalServerError, err_msg) } // load index idx, err := n.Index(query.Get("index")) if err != nil { return responder.RespondWithError(ctx, http.StatusBadRequest, "Invalid index") } if idx.Type() == "virtual" { csize := conf.CHUNK_SIZE if _, ok := query["chunk_size"]; ok { csize, err = strconv.ParseInt(query.Get("chunk_size"), 10, 64) if err != nil { return responder.RespondWithError(ctx, http.StatusBadRequest, "Invalid chunk_size") } } idx.Set(map[string]interface{}{"ChunkSize": csize}) } var size int64 = 0 s := &request.Streamer{R: []file.SectionReader{}, W: ctx.HttpResponseWriter(), ContentType: "application/octet-stream", Filename: filename, Filter: fFunc} for _, p := range query["part"] { pos, length, err := idx.Part(p) if err != nil { return responder.RespondWithError(ctx, http.StatusBadRequest, "Invalid index part") } size += length s.R = append(s.R, io.NewSectionReader(r, pos, length)) } s.Size = size err = s.Stream() if err != nil { // causes "multiple response.WriteHeader calls" error but better than no response err_msg := "err:@node_Read s.stream: " + err.Error() logger.Error(err_msg) responder.RespondWithError(ctx, http.StatusBadRequest, err_msg) } } else { nf, err := n.FileReader() defer nf.Close() if err != nil { // File not found or some sort of file read error. // Probably deserves more checking err_msg := "err:@node_Read node.FileReader: " + err.Error() logger.Error(err_msg) return responder.RespondWithError(ctx, http.StatusBadRequest, err_msg) } s := &request.Streamer{R: []file.SectionReader{nf}, W: ctx.HttpResponseWriter(), ContentType: "application/octet-stream", Filename: filename, Size: n.File.Size, Filter: fFunc} err = s.Stream() if err != nil { // causes "multiple response.WriteHeader calls" error but better than no response err_msg := "err:@node_Read: s.stream: " + err.Error() logger.Error(err_msg) responder.RespondWithError(ctx, http.StatusBadRequest, err_msg) } } } else if _, ok := query["download_url"]; ok { if !n.HasFile() { return responder.RespondWithError(ctx, http.StatusBadRequest, "Node has not file") } else if u.Uuid == "" { return responder.RespondWithError(ctx, http.StatusUnauthorized, e.NoAuth) } else { options := map[string]string{} if _, ok := query["filename"]; ok { options["filename"] = query.Get("filename") } if p, err := preauth.New(util.RandString(20), "download", n.Id, options); err != nil { err_msg := "err:@node_Read download_url: " + err.Error() logger.Error(err_msg) responder.RespondWithError(ctx, http.StatusInternalServerError, err_msg) } else { responder.RespondWithData(ctx, util.UrlResponse{Url: util.ApiUrl(ctx) + "/preauth/" + p.Id, ValidTill: p.ValidTill.Format(time.ANSIC)}) } } } else { // Base case respond with node in json responder.RespondWithData(ctx, n) } return nil }
func beforeHandler(c context.Context) (err error) { session, _ := session_store.Get(c.HttpRequest(), session_name) session.Save(c.HttpRequest(), c.HttpResponseWriter()) return nil }