Commit 17149133 authored by Andreas Wagner's avatar Andreas Wagner
Browse files

Add error handling.

parent 5735e7d0
...@@ -15,7 +15,8 @@ ...@@ -15,7 +15,8 @@
"token": "aBcDeFgHiJkLmNoPqRsTuVwXyZ", "token": "aBcDeFgHiJkLmNoPqRsTuVwXyZ",
"user": "digicademy", "user": "digicademy",
"repo": "digicademy/svsal", "repo": "digicademy/svsal",
"commit_keyword": "" "commit_keyword": "",
"commit_dontpublish_keyword": "test"
}, },
"metadata": { "metadata": {
"fields": [ "fields": [
......
...@@ -15,10 +15,7 @@ import ( ...@@ -15,10 +15,7 @@ import (
"gitlab.gwdg.de/rg-mpg-de/tei2zenodo" "gitlab.gwdg.de/rg-mpg-de/tei2zenodo"
) )
// 0. decide where trigger keywords can be stored - in commit messages? // ====== Types =======
// 1. parse github push request -> get commits
// 2. retrieve commits -> get files
// 3. retrieve files -> pipe to zenodo
// PushHook stores the payload of a github push webhook event // PushHook stores the payload of a github push webhook event
type PushHook struct { type PushHook struct {
...@@ -271,11 +268,17 @@ type FileInfo struct { ...@@ -271,11 +268,17 @@ type FileInfo struct {
Date time.Time Date time.Time
} }
// ====== Functions =======
// 1. parse github push request -> get commits, check repo, pusher, keywords in commit msgs
// 2. retrieve commits -> get files
// 3. retrieve files -> pipe to zenodo
// ProcessHook processes a Webhook's payload // ProcessHook processes a Webhook's payload
// it returns a (boolean) doPublish value, a map of filenames/urls with all concerned files, and an error value // it returns a (boolean) doPublish value, a map of filenames/urls with all concerned files, and an error value
func ProcessHook(hookType string, r io.ReadSeeker, conf *tei2zenodo.Config) (bool, map[string]FileInfo, error) { func ProcessHook(hookType string, r io.ReadSeeker, conf *tei2zenodo.Config) (bool, map[string]FileInfo, error) {
doPublish := false doPublish := true
switch hookType { switch hookType {
case "push": case "push":
...@@ -286,15 +289,15 @@ func ProcessHook(hookType string, r io.ReadSeeker, conf *tei2zenodo.Config) (boo ...@@ -286,15 +289,15 @@ func ProcessHook(hookType string, r io.ReadSeeker, conf *tei2zenodo.Config) (boo
err := json.NewDecoder(r).Decode(&payload) err := json.NewDecoder(r).Decode(&payload)
if err != nil { if err != nil {
log.Printf("Error processing push hook: %+v", err) log.Printf("Error processing push hook: %+v", err)
return false, nil, fmt.Errorf("error processing push hook: %s", err) return false, nil, tei2zenodo.NewError("errInternal", fmt.Sprintf("error processing push hook: %s", err.Error()), 500, err)
} }
if payload.Repository.FullName != conf.AllowedGit.Repo && conf.AllowedGit.Repo != "" { if payload.Repository.FullName != conf.AllowedGit.Repo && conf.AllowedGit.Repo != "" {
log.Printf("Repo not allowed: %s", payload.Repository.FullName) log.Printf("Repo not allowed: %s", payload.Repository.FullName)
return false, nil, fmt.Errorf("repo not allowed: %s", payload.Repository.FullName) return false, nil, tei2zenodo.NewError("errBadConfig", fmt.Sprintf("repo not allowed: %s", payload.Repository.FullName), 500, nil)
} }
if payload.Pusher.Name != conf.AllowedGit.User && conf.AllowedGit.User != "" { if payload.Pusher.Name != conf.AllowedGit.User && conf.AllowedGit.User != "" {
log.Printf("Git user not allowed as pusher: %s", payload.Pusher.Name) log.Printf("Git user not allowed as pusher: %s", payload.Pusher.Name)
return false, nil, fmt.Errorf("git user not allowed as pusher: %s", payload.Pusher.Name) return false, nil, tei2zenodo.NewError("errBadConfig", fmt.Sprintf("git user not allowed as pusher: %s", payload.Pusher.Name), 500, nil)
} }
if conf.Verbose { if conf.Verbose {
log.Printf("Push payload: %+v", payload) log.Printf("Push payload: %+v", payload)
...@@ -302,18 +305,24 @@ func ProcessHook(hookType string, r io.ReadSeeker, conf *tei2zenodo.Config) (boo ...@@ -302,18 +305,24 @@ func ProcessHook(hookType string, r io.ReadSeeker, conf *tei2zenodo.Config) (boo
commitsURL := payload.Repository.CommitsURL commitsURL := payload.Repository.CommitsURL
// Get all commits and their associated files // Get all commits and their associated files
log.Printf("--- Get all commits and their associated files ---")
files := make(map[string]FileInfo) files := make(map[string]FileInfo)
for _, c := range payload.Commits { for _, c := range payload.Commits {
sha := c.URL[strings.LastIndex(c.URL, "/")+1:] sha := c.URL[strings.LastIndex(c.URL, "/")+1:]
log.Printf(" commit %s ...", sha) if conf.Verbose {
log.Printf(" commit %s ...", sha)
}
if !(strings.Contains(c.Message, conf.AllowedGit.Keyword)) && conf.AllowedGit.Keyword != "" { if !(strings.Contains(c.Message, conf.AllowedGit.Keyword)) && conf.AllowedGit.Keyword != "" {
log.Printf("Required keyword not contained in commit message for commit %s", sha) if conf.Verbose {
log.Printf("Required keyword not contained in commit message for commit %s", sha)
}
continue continue
} }
f, err := retrieveFiles(commitsURL, sha, conf) f, err := retrieveFiles(commitsURL, sha, conf)
if err != nil { if err != nil {
log.Printf("Error retrieving files from commit %s: %+v", sha, err) log.Printf("Error retrieving files from commit %s: %+v", sha, err)
return false, nil, fmt.Errorf("error retrieving files from commit %s: %s", sha, err) return false, nil, tei2zenodo.NewError("errInternal", fmt.Sprintf("error retrieving files from commit %s: %s", sha, err), 500, err)
} }
for k, v := range f { for k, v := range f {
if old, ok := files[k]; ok { // file is already present if old, ok := files[k]; ok { // file is already present
...@@ -324,16 +333,21 @@ func ProcessHook(hookType string, r io.ReadSeeker, conf *tei2zenodo.Config) (boo ...@@ -324,16 +333,21 @@ func ProcessHook(hookType string, r io.ReadSeeker, conf *tei2zenodo.Config) (boo
files[k] = v files[k] = v
} }
} }
if !(strings.Contains(c.Message, conf.AllowedGit.DontPublishKeyword)) && conf.AllowedGit.DontPublishKeyword != "" {
log.Printf("!!! Don't-publish-keyword '%s' contained in commit message for commit %s,\n", conf.AllowedGit.DontPublishKeyword, sha)
log.Printf("!!! not going to publish zenodo deposit !!!")
doPublish = false
}
} }
// log.Printf("Parsed hook: %+v", payload) // log.Printf("Parsed hook: %+v", payload)
if conf.Verbose { if conf.Verbose {
log.Printf("Push hook with %d commits and %d files: %+v", len(payload.Commits), len(files), files) log.Printf(" Parsed push hook with %d commits and %d files: %+v", len(payload.Commits), len(files), files)
} else { } else {
fls := "" var fls []string
for s := range files { for s := range files {
fls = fls + " " + s fls = append(fls, s)
} }
log.Printf("Push hook with %d commits and %d files: %s", len(payload.Commits), len(files), fls) log.Printf(" Parsed push hook with %d commits and %d files: %s", len(payload.Commits), len(files), strings.Join(fls, ", "))
} }
return doPublish, files, nil return doPublish, files, nil
} }
...@@ -344,7 +358,7 @@ func ProcessHook(hookType string, r io.ReadSeeker, conf *tei2zenodo.Config) (boo ...@@ -344,7 +358,7 @@ func ProcessHook(hookType string, r io.ReadSeeker, conf *tei2zenodo.Config) (boo
default: default:
{ {
log.Printf("Unknown hook type %s", hookType) log.Printf("Unknown hook type %s", hookType)
return false, nil, fmt.Errorf("unknown hook type %s", hookType) return false, nil, tei2zenodo.NewError("errWebhook", fmt.Sprintf("hook type %s not implemented", hookType), 501, nil)
} }
} }
} }
...@@ -359,15 +373,15 @@ func retrieveFiles(commitsURL string, sha string, conf *tei2zenodo.Config) (map[ ...@@ -359,15 +373,15 @@ func retrieveFiles(commitsURL string, sha string, conf *tei2zenodo.Config) (map[
// Send GET request // Send GET request
if conf.Verbose { if conf.Verbose {
log.Printf(" Get files at %s", targetURI) log.Printf(" Get files at %s:", targetURI)
} else { } else {
log.Printf(" Get files") log.Printf(" Get files:")
} }
client := &http.Client{} client := &http.Client{}
resp, err := client.Do(req) resp, err := client.Do(req)
if err != nil { if err != nil {
log.Printf("Problem creating GET request: %v ...", err) log.Printf("Problem sending GET request: %v ...", err)
return files, fmt.Errorf("problem creating GET request: %s", err) return nil, tei2zenodo.NewError("errNetComm", fmt.Sprintf("error sending GET request: %s", err.Error()), 500, err)
} }
defer resp.Body.Close() defer resp.Body.Close()
...@@ -375,11 +389,11 @@ func retrieveFiles(commitsURL string, sha string, conf *tei2zenodo.Config) (map[ ...@@ -375,11 +389,11 @@ func retrieveFiles(commitsURL string, sha string, conf *tei2zenodo.Config) (map[
content, err := ioutil.ReadAll(resp.Body) content, err := ioutil.ReadAll(resp.Body)
if err != nil { if err != nil {
log.Printf("Problem reading GET response: %v ...", err) log.Printf("Problem reading GET response: %v ...", err)
return files, fmt.Errorf("problem reading GET response: %s", err) return nil, tei2zenodo.NewError("errNetComm", fmt.Sprintf("error reading GET request: %s", err.Error()), 500, err)
} }
if strconv.Itoa(resp.StatusCode)[:1] != "2" { if strconv.Itoa(resp.StatusCode)[:1] != "2" {
log.Printf("Problem reported by github: %d %v. %+v ...", resp.StatusCode, err, content) log.Printf("Problem reported by github: %d %v. %+v ...", resp.StatusCode, err, content)
return files, fmt.Errorf("problem reported by github: %d %v", resp.StatusCode, err) return nil, tei2zenodo.NewError("errNetComm", fmt.Sprintf("problem reported by github: %d %v", resp.StatusCode, err), 500, err)
} }
// Parse response // Parse response
...@@ -387,24 +401,30 @@ func retrieveFiles(commitsURL string, sha string, conf *tei2zenodo.Config) (map[ ...@@ -387,24 +401,30 @@ func retrieveFiles(commitsURL string, sha string, conf *tei2zenodo.Config) (map[
err = json.Unmarshal(content, &commit) err = json.Unmarshal(content, &commit)
if err != nil { if err != nil {
log.Printf("Problem parsing github's response: %v ...", err) log.Printf("Problem parsing github's response: %v ...", err)
return nil, fmt.Errorf("problem parsing github's response: %s", err) return nil, tei2zenodo.NewError("errParse", fmt.Sprintf("problem parsing github's response: %s", err), 500, err)
} }
// layout := "2006-01-02T15:04:05.000Z" // layout := "2006-01-02T15:04:05.000Z"
str := commit.Commit.Committer.Date str := commit.Commit.Committer.Date
commitDate, err := time.Parse(time.RFC3339, str) commitDate, err := time.Parse(time.RFC3339, str)
for i, f := range commit.Files { counter := 0
for _, f := range commit.Files {
filename := f.Filename filename := f.Filename
url := f.RawURL url := f.RawURL
modType := f.Status modType := f.Status
if conf.Verbose {
log.Printf(" %d. %s %s: %s", i+1, modType, filename, url)
} else {
log.Printf(" %d. %s %s", i+1, modType, filename)
}
if modType != "deleted" && modType != "renamed" { if modType != "deleted" && modType != "renamed" {
counter++
if conf.Verbose {
log.Printf(" %d. '%s' (%s): %s", counter, filename, modType, url)
} else {
log.Printf(" %d. '%s' (%s)", counter, filename, modType)
}
files[filename] = FileInfo{URL: url, Change: modType, Date: commitDate} files[filename] = FileInfo{URL: url, Change: modType, Date: commitDate}
} else {
if conf.Verbose {
log.Printf(" ignore %s file %s: %s", modType, filename, url)
}
} }
} }
return files, nil return files, nil
......
...@@ -40,6 +40,12 @@ func SetupRoutes(conf tei2zenodo.Config) *gin.Engine { ...@@ -40,6 +40,12 @@ func SetupRoutes(conf tei2zenodo.Config) *gin.Engine {
var doPublish bool var doPublish bool
var myDeposit tei2zenodo.Deposit var myDeposit tei2zenodo.Deposit
if conf.Verbose {
log.Printf("====== Received POST message from %s at %s ======", c.Request.RemoteAddr, conf.FileAPI)
} else {
log.Printf("====== Received POST message ======")
}
// Read file from Request body // Read file from Request body
buf := new(bytes.Buffer) buf := new(bytes.Buffer)
buf.ReadFrom(c.Request.Body) buf.ReadFrom(c.Request.Body)
...@@ -47,9 +53,16 @@ func SetupRoutes(conf tei2zenodo.Config) *gin.Engine { ...@@ -47,9 +53,16 @@ func SetupRoutes(conf tei2zenodo.Config) *gin.Engine {
r = strings.NewReader(file) r = strings.NewReader(file)
// Get filename for upload // Get filename for upload
filename := c.Request.FormValue(`filename`) var filename string
filename = c.Request.FormValue(`filename`)
if filename == "" { if filename == "" {
filename = t2zxml.GetFilename(r) f, GFErr := t2zxml.GetFilename(r)
if GFErr != nil {
log.Printf("Problem reading filename: %+v", GFErr)
AbortMsg(500, tei2zenodo.NewError("errParse", fmt.Sprintf("Error reading filename: %s", GFErr), 500, GFErr), c)
return
}
filename = f
r.Seek(0, 0) r.Seek(0, 0)
} }
myDeposit.Filename = filename myDeposit.Filename = filename
...@@ -62,13 +75,26 @@ func SetupRoutes(conf tei2zenodo.Config) *gin.Engine { ...@@ -62,13 +75,26 @@ func SetupRoutes(conf tei2zenodo.Config) *gin.Engine {
} }
// Send file to processing... // Send file to processing...
err := zenodo.ProcessFile(&conf, &myDeposit, r, doPublish) PFErr := zenodo.ProcessFile(&conf, &myDeposit, r, doPublish)
if err != nil { if PFErr != nil {
AbortMsg(500, err, c) switch PFErr.Typ {
return case "errNoTEIXML":
{
log.Printf("Problem processing file %s: %+v", myDeposit.Filename, PFErr)
AbortMsg(500, tei2zenodo.NewError("errZProcessing", fmt.Sprintf("problem processing file %s", myDeposit.Filename), 500, PFErr), c)
return
}
default:
{
log.Printf("Problem processing file %s: %+v", myDeposit.Filename, PFErr)
AbortMsg(500, tei2zenodo.NewError("errZProcessing", fmt.Sprintf("problem processing file %s", myDeposit.Filename), 500, PFErr), c)
return
}
}
} }
log.Printf("=== All done ===") log.Printf("====== All done ======")
c.JSON(200, myDeposit) c.JSON(200, myDeposit)
}) })
} }
...@@ -79,6 +105,11 @@ func SetupRoutes(conf tei2zenodo.Config) *gin.Engine { ...@@ -79,6 +105,11 @@ func SetupRoutes(conf tei2zenodo.Config) *gin.Engine {
// Read hook type from header // Read hook type from header
hookType := c.Request.Header.Get("X-GitHub-Event") hookType := c.Request.Header.Get("X-GitHub-Event")
if conf.Verbose {
log.Printf("====== Received %s message from %s at %s ======", hookType, c.Request.RemoteAddr, conf.WebhookAPI)
} else {
log.Printf("====== Received %s message ======", hookType)
}
// Read payload from Request body // Read payload from Request body
buf := new(bytes.Buffer) buf := new(bytes.Buffer)
...@@ -87,27 +118,39 @@ func SetupRoutes(conf tei2zenodo.Config) *gin.Engine { ...@@ -87,27 +118,39 @@ func SetupRoutes(conf tei2zenodo.Config) *gin.Engine {
r = strings.NewReader(file) r = strings.NewReader(file)
// Process Hook to extract files // Process Hook to extract files
doPublish, files, err := github.ProcessHook(hookType, r, &conf) doPublish, files, PHErr := github.ProcessHook(hookType, r, &conf)
if err != nil { if PHErr != nil {
log.Printf("Error parsing webhook event: %v", err) log.Printf("Error parsing webhook event: %v", PHErr)
AbortMsg(500, fmt.Errorf("problem parsing webhook event: %s", err), c) AbortMsg(500, tei2zenodo.NewError("errWebhook", fmt.Sprintf("problem parsing webhook for %s event", hookType), 500, PHErr), c)
} }
log.Printf("%d files returned", len(files)) // log.Printf(" %d files returned", len(files))
log.Printf("doPublish: %s", strconv.FormatBool(doPublish)) log.Printf(" doPublish: %s", strconv.FormatBool(doPublish))
// Send each file to processing // Send each file to processing
for f := range files { for f := range files {
var myDeposit tei2zenodo.Deposit var myDeposit tei2zenodo.Deposit
log.Printf("Processing file %s", f) log.Printf("\n")
log.Printf("Processing file '%s'", f)
myDeposit.Filename = strings.Replace(f, "/", "_", -1) myDeposit.Filename = strings.Replace(f, "/", "_", -1)
err := zenodo.ProcessDownloadFile(&conf, &myDeposit, files[f].URL, doPublish) PDErr := zenodo.ProcessDownloadFile(&conf, &myDeposit, files[f].URL, doPublish)
if err != nil { if PDErr != nil {
AbortMsg(500, err, c) switch PDErr.Typ {
return case "errNoTEIXML":
{
log.Printf(" No TEI XML file, skipping...")
continue
}
default:
{
log.Printf("Problem processing file %s: %+v", myDeposit.Filename, PDErr)
AbortMsg(500, tei2zenodo.NewError("errZProcessing", fmt.Sprintf("problem processing file %s", myDeposit.Filename), 500, PDErr), c)
return
}
}
} }
} }
log.Printf("=== All done ===") log.Printf("====== All done ======")
c.JSON(200, "processed hook successfully") c.JSON(200, "processed hook successfully")
}) })
} }
...@@ -116,7 +159,7 @@ func SetupRoutes(conf tei2zenodo.Config) *gin.Engine { ...@@ -116,7 +159,7 @@ func SetupRoutes(conf tei2zenodo.Config) *gin.Engine {
} }
// AbortMsg returns an error code and message. // AbortMsg returns an error code and message.
func AbortMsg(code int, err error, c *gin.Context) { func AbortMsg(code int, err *tei2zenodo.Error, c *gin.Context) {
c.String(code, "Something has gone wrong, causing a %v error.\n", code) c.String(code, "Something has gone wrong, causing a %v error.\n", code)
// A custom error page with HTML templates can be shown by c.HTML() // A custom error page with HTML templates can be shown by c.HTML()
// A JSON object would be given like c.JSON(404, gin.H{"code": "PAGE_NOT_FOUND", "message": "Seite nicht gefunden"}) // A JSON object would be given like c.JSON(404, gin.H{"code": "PAGE_NOT_FOUND", "message": "Seite nicht gefunden"})
......
...@@ -15,34 +15,45 @@ import ( ...@@ -15,34 +15,45 @@ import (
) )
// GetFilename extracts what can serve as filename. Like /TEI/@xml:id // GetFilename extracts what can serve as filename. Like /TEI/@xml:id
// it returns a string to serve as filename // it returns a string to serve as filename and an error value
func GetFilename(r io.Reader) string { func GetFilename(r io.Reader) (string, error) {
// Parse document (in r) wih antchfx/xmlquery... // Parse document (in r) wih antchfx/xmlquery...
doc, err := xmlquery.Parse(r) doc, err := xmlquery.Parse(r)
if err != nil { if err != nil {
log.Printf("Could not parse xml.\n") log.Printf("Could not parse xml.\n")
return "" return "", tei2zenodo.NewError("errParse", "could not parse xml", 500, err)
} }
t := xmlquery.FindOne(doc, `/TEI/@xml:id`) t := xmlquery.FindOne(doc, `/TEI/@xml:id`)
if n := t; t != nil { if n := t; t != nil {
u := n.InnerText() u := n.InnerText()
return u + ".xml" return u + ".xml", nil
} }
return "" return "", nil
} }
// ParseTEI reads a TEI file and parses its metadata into a ZMetadata variable. // ParseTEI reads a TEI file and parses its metadata into a ZMetadata variable.
// Returns a doi (maybe empty) and an error value. // Returns a doi (maybe empty) and an error value.
func ParseTEI(r io.Reader, md *tei2zenodo.ZMetadata, c *tei2zenodo.Config) (string, error) { func ParseTEI(r io.Reader, md *tei2zenodo.ZMetadata, c *tei2zenodo.Config) (string, *tei2zenodo.Error) {
conf := c.Metadata conf := c.Metadata
var doc *xmlquery.Node var doc *xmlquery.Node
log.Printf(" Parse TEI XML file")
// Parse document r wih antchfx/xmlquery... // Parse document r wih antchfx/xmlquery...
doc, err := xmlquery.Parse(r) doc, PErr := xmlquery.Parse(r)
if err != nil { if PErr != nil {
log.Printf("Could not parse xml.\n") log.Printf("Could not parse xml.\n")
return "", err return "", tei2zenodo.NewError("errParse", "could not parse xml", 500, PErr)
}
if doc == nil || (doc.FirstChild == nil && doc.InnerText() == "") {
log.Printf(" Parse returned no or empty node only.\n")
return "", tei2zenodo.NewError("errNoTEIXML", "not a TEI XML file", 400, nil)
}
rootElement := xmlquery.FindOne(doc, `/*[1]`)
if !(rootElement.NamespaceURI == "http://www.tei-c.org/ns/1.0" && rootElement.Data == "TEI") {
log.Printf(" This is not a TEI XML file. %+v", rootElement)
return "", tei2zenodo.NewError("errNoTEIXML", "not a TEI XML file", 400, nil)
} }
re := regexp.MustCompile(`\s+`) re := regexp.MustCompile(`\s+`)
...@@ -114,7 +125,7 @@ func ParseTEI(r io.Reader, md *tei2zenodo.ZMetadata, c *tei2zenodo.Config) (stri ...@@ -114,7 +125,7 @@ func ParseTEI(r io.Reader, md *tei2zenodo.ZMetadata, c *tei2zenodo.Config) (stri
xexpr, err := xpath.Compile(confSubfields[m].XExpression) xexpr, err := xpath.Compile(confSubfields[m].XExpression)
if err != nil { if err != nil {
log.Printf("Erroneous XPath expression: %s ...", confSubfields[m].XExpression) log.Printf("Erroneous XPath expression: %s ...", confSubfields[m].XExpression)
return "", fmt.Errorf("erroneous XPath expression: %s", confSubfields[m].XExpression) return "", tei2zenodo.NewError("errBadConfig", fmt.Sprintf("erroneous XPath expression: %s", confSubfields[m].XExpression), 500, err)
} }
switch zStructFieldtype.String() { switch zStructFieldtype.String() {
case "string": case "string":
...@@ -139,12 +150,12 @@ func ParseTEI(r io.Reader, md *tei2zenodo.ZMetadata, c *tei2zenodo.Config) (stri ...@@ -139,12 +150,12 @@ func ParseTEI(r io.Reader, md *tei2zenodo.ZMetadata, c *tei2zenodo.Config) (stri
default: default:
log.Printf("Unknown (hardcoded?) metadata type: %s.%s ...", structFieldtype, zStructFieldtype) log.Printf("Unknown (hardcoded?) metadata type: %s.%s ...", structFieldtype, zStructFieldtype)
return "", fmt.Errorf("xml: unknown (hardcoded?) metadata type: %s.%s", structFieldtype, zStructFieldtype) return "", tei2zenodo.NewError("errInternal", fmt.Sprintf("xml: unknown (hardcoded?) metadata type: %s.%s", structFieldtype, zStructFieldtype), 500, nil)
} }
} else if confSubfields[m].Field == "name" || confSubfields[m].Field == "type" { } else if confSubfields[m].Field == "name" || confSubfields[m].Field == "type" {
log.Printf("Problem with config: XPath or XExpression missing in %v ...", conf.Fields[j]) log.Printf("Problem with config: XPath or XExpression missing in %v ...", conf.Fields[j])
return "", fmt.Errorf("xml: malformed config (xpath/xexpression missing): %v", conf.Fields[j]) return "", tei2zenodo.NewError("errBadConfig", fmt.Sprintf("XPath or XExpression missing in %v ...", conf.Fields[j]), 500, nil)
} }
} }
} }
...@@ -176,12 +187,13 @@ func ParseTEI(r io.Reader, md *tei2zenodo.ZMetadata, c *tei2zenodo.Config) (stri ...@@ -176,12 +187,13 @@ func ParseTEI(r io.Reader, md *tei2zenodo.ZMetadata, c *tei2zenodo.Config) (stri
f.Set(newSlice) f.Set(newSlice)
default: default:
log.Printf("Problem with type conversion of %s (%s)", structFieldname, varType.Name()) log.Printf("Problem with type conversion of %s (%s)", structFieldname, varType.Name())
return "", fmt.Errorf("xml: malformed config (type problem in %s [%s])", structFieldname, varType.Name()) return "", tei2zenodo.NewError("errInternal", fmt.Sprintf("type problem in %s [%s]", structFieldname, varType.Name()), 500, nil)
} }
} }
} else { } else {
log.Printf("Problem with config: XPath missing in %v ...", conf.Fields[j]) log.Printf("Problem with config: XPath missing in %v ...", conf.Fields[j])
return "", fmt.Errorf("xml: malformed config (xpath missing): %v", conf.Fields[j]) return "", tei2zenodo.NewError("errBadConfig", fmt.Sprintf("XPath or XExpression missing in %v ...", conf.Fields[j]), 500, nil)
} }
} else if conf.Fields[j].XPath != "" { } else if conf.Fields[j].XPath != "" {
...@@ -208,13 +220,13 @@ func ParseTEI(r io.Reader, md *tei2zenodo.ZMetadata, c *tei2zenodo.Config) (stri ...@@ -208,13 +220,13 @@ func ParseTEI(r io.Reader, md *tei2zenodo.ZMetadata, c *tei2zenodo.Config) (stri
default: default:
log.Printf("Unknown (hardcoded?) metadata type: %s ...", structFieldtype) log.Printf("Unknown (hardcoded?) metadata type: %s ...", structFieldtype)
return "", fmt.Errorf("xml: unknown (hardcoded?) metadata type: %s", structFieldtype) return "", tei2zenodo.NewError("errInternal", fmt.Sprintf("xml: unknown (hardcoded?) metadata type: %s", structFieldtype), 500, nil)
} }
} else if conf.Fields[j].XExpression != "" { } else if conf.Fields[j].XExpression != "" {
xexpr, err := xpath.Compile(conf.Fields[j].XExpression) xexpr, err := xpath.Compile(conf.Fields[j].XExpression)
if err != nil {