func GetArtifactContent(r render.Render, req *http.Request, res http.ResponseWriter, db database.Database, params martini.Params, s3bucket *s3.Bucket, artifact *model.Artifact) { if artifact == nil { JsonErrorf(r, http.StatusBadRequest, "Error: no artifact specified") return } switch artifact.State { case model.UPLOADED: // Fetch from S3 reader, err := s3bucket.GetReader(artifact.S3URL) if err != nil { JsonErrorf(r, http.StatusInternalServerError, err.Error()) return } // Ideally, we'll use a Hijacker to take over the conn so that we can employ an io.Writer // instead of loading the entire file into memory before writing it back out. But, for now, we // will run the risk of OOM if large files need to be served. var buf bytes.Buffer _, err = buf.ReadFrom(reader) if err != nil { JsonErrorf(r, http.StatusInternalServerError, "Error reading upload buffer: %s", err.Error()) return } res.Write(buf.Bytes()) return case model.UPLOADING: // Not done uploading to S3 yet. Error. r.JSON(http.StatusNotFound, map[string]string{"error": "Waiting for content to complete uploading"}) return case model.APPENDING: fallthrough case model.APPEND_COMPLETE: // Pick from log chunks logChunks, err := db.ListLogChunksInArtifact(artifact.Id) if err != nil { JsonErrorf(r, http.StatusInternalServerError, err.Error()) return } var buf bytes.Buffer for _, logChunk := range logChunks { buf.WriteString(logChunk.Content) } res.Write(buf.Bytes()) return case model.WAITING_FOR_UPLOAD: // Not started yet. Error JsonErrorf(r, http.StatusNotFound, "Waiting for content to get uploaded") return } }