If a log is uploaded with a sensible filename, preserve it (#18)

- the mobile guys want to be able to distinguish between crash.log and other
logs.
This commit is contained in:
Richard van der Hoff 2017-05-04 15:58:23 +01:00 committed by GitHub
parent f630c6a78a
commit 63d6917dfe
3 changed files with 29 additions and 8 deletions

View File

@ -57,11 +57,16 @@ logs.)
* `log`: a log file, with lines separated by newline characters. Multiple log
files can be included by including several `log` parts.
If the log is uploaded with a filename `name.ext`, where `name` contains only
alphanumerics, `.`, `-` or `_`, and `ext` is one of `log` or `txt`, then the
file saved to disk is based on that. Otherwise, a suitable name is
constructed.
If using the JSON upload encoding, the request object should instead include
a single `logs` field, which is an array of objects with the following
fields:
* `id`: textual identifier for the logs. Currently ignored.
* `id`: textual identifier for the logs. Used as the filename, as above.
* `lines`: log data. Newlines should be encoded as `\n`, as normal in JSON).
* `compressed-log`: a gzipped logfile. Decompressed and then treated the same as

View File

@ -189,7 +189,7 @@ func parseJSONRequest(w http.ResponseWriter, req *http.Request, reportDir string
for i, log := range p.Logs {
buf := bytes.NewBufferString(log.Lines)
leafName, err := saveLogPart(i, buf, reportDir)
leafName, err := saveLogPart(i, log.ID, buf, reportDir)
if err != nil {
return nil, err
}
@ -286,7 +286,7 @@ func parseFormPart(part *multipart.Part, p *parsedPayload, reportDir string) err
}
if field == "log" || field == "compressed-log" {
leafName, err := saveLogPart(len(p.Logs), partReader, reportDir)
leafName, err := saveLogPart(len(p.Logs), part.FileName(), partReader, reportDir)
if err != nil {
return err
}
@ -359,11 +359,27 @@ func saveFormPart(leafName string, reader io.Reader, reportDir string) (string,
return leafName, nil
}
// we require a sensible extension, and don't allow the filename to start with
// '.'
var logRegexp = regexp.MustCompile(`^[a-zA-Z0-9_-][a-zA-Z0-9_.-]*\.(log|txt)$`)
// saveLogPart saves a log upload to the report directory.
//
// Returns the leafname of the saved file.
func saveLogPart(logNum int, reader io.Reader, reportDir string) (string, error) {
leafName := fmt.Sprintf("logs-%04d.log.gz", logNum)
func saveLogPart(logNum int, filename string, reader io.Reader, reportDir string) (string, error) {
// pick a name to save the log file with.
//
// some clients use sensible names (foo.N.log), which we preserve. For
// others, we just make up a filename.
//
// Either way, we need to append .gz, because we're compressing it.
var leafName string
if logRegexp.MatchString(filename) {
leafName = filename + ".gz"
} else {
leafName = fmt.Sprintf("logs-%04d.log.gz", logNum)
}
fullname := filepath.Join(reportDir, leafName)
f, err := os.Create(fullname)

View File

@ -112,7 +112,7 @@ func TestMultipartUpload(t *testing.T) {
// check logs uploaded correctly
checkUploadedFile(t, reportDir, "logs-0000.log.gz", true, "log\nlog\nlog")
checkUploadedFile(t, reportDir, "logs-0001.log.gz", true, "log")
checkUploadedFile(t, reportDir, "console.0.log.gz", true, "log")
checkUploadedFile(t, reportDir, "logs-0002.log.gz", true, "test\n")
// check file uploaded correctly
@ -156,7 +156,7 @@ log
log
log
------WebKitFormBoundarySsdgl8Nq9voFyhdO
Content-Disposition: form-data; name="log"; filename="instance-0.067644760733513781492004890379"
Content-Disposition: form-data; name="log"; filename="console.0.log"
Content-Type: text/plain
log
@ -207,7 +207,7 @@ func checkParsedMultipartUpload(t *testing.T, p *parsedPayload) {
if p.Logs[0] != wanted {
t.Errorf("Log 0: got %s, want %s", p.Logs[0], wanted)
}
wanted = "logs-0001.log.gz"
wanted = "console.0.log.gz"
if p.Logs[1] != wanted {
t.Errorf("Log 1: got %s, want %s", p.Logs[1], wanted)
}