diff pkg/wfs/download.go @ 2109:86c88fc0ff5e

WFS downloader: Parse for exception reports when calling GetFeature. Not very efficient (uses temp files).
author Sascha L. Teichmann <sascha.teichmann@intevation.de>
date Mon, 04 Feb 2019 17:48:36 +0100
parents 2b72f5e005aa
children fc4ebe7eaeff
line wrap: on
line diff
--- a/pkg/wfs/download.go	Mon Feb 04 17:04:33 2019 +0100
+++ b/pkg/wfs/download.go	Mon Feb 04 17:48:36 2019 +0100
@@ -19,11 +19,14 @@
 	"errors"
 	"fmt"
 	"io"
+	"io/ioutil"
 	"log"
 	"net/http"
 	"net/url"
+	"os"
 	"strconv"
 
+	"gemma.intevation.de/gemma/pkg/config"
 	"golang.org/x/net/html/charset"
 )
 
@@ -256,12 +259,82 @@
 			resp.StatusCode, resp.Status)
 	}
 	defer resp.Body.Close()
-	return handler(url, resp.Body)
+	tmp, err := ioutil.TempFile(config.TmpDir(), "wfs*.tmp")
+	if err != nil {
+		return err
+	}
+	defer os.Remove(tmp.Name())
+
+	_, err = io.Copy(tmp, resp.Body)
+	err2 := tmp.Close()
+	if err != nil {
+		return err
+	}
+	if err2 != nil {
+		return err2
+	}
+	f, err := os.Open(tmp.Name())
+	if err != nil {
+		return err
+	}
+	defer f.Close()
+
+	if err := scanExceptionReport(f); err != nil {
+		return err
+	}
+
+	if _, err := f.Seek(0, 0); err != nil {
+		return err
+	}
+	return handler(url, bufio.NewReader(f))
+}
+
+type ExceptionReport struct {
+	XMLName   xml.Name `xml:"http://www.opengis.net/ows/1.1 ExceptionReport"`
+	Exception struct {
+		ExceptionCode *string `xml:"exceptionCode,attr"`
+		ExceptionText struct {
+			Text *string `xml:",cdata"`
+		} `xml:"http://www.opengis.net/ows/1.1 ExceptionText"`
+	} `xml:"http://www.opengis.net/ows/1.1 Exception"`
+}
+
+func (er *ExceptionReport) Error() string {
+	nilString := func(s *string) string {
+		if s == nil {
+			return ""
+		}
+		return *s
+	}
+	return fmt.Sprintf(
+		"WFS GetFeature error: ExceptionCode: '%s' / ExceptionText: %s",
+		nilString(er.Exception.ExceptionCode),
+		nilString(er.Exception.ExceptionText.Text))
+}
+
+func scanExceptionReport(r io.Reader) *ExceptionReport {
+
+	decoder := xml.NewDecoder(r)
+	decoder.CharsetReader = charset.NewReaderLabel
+
+	var er ExceptionReport
+
+	if err := decoder.Decode(&er); err != nil {
+		// Fine because of other kind of document
+		return nil
+	}
+
+	if er.Exception.ExceptionText.Text == nil && er.Exception.ExceptionCode == nil {
+		return nil
+	}
+
+	return &er
 }
 
 // DownloadURLs does the actual GetFeature requests downloads
 // and hands the resulting io.Readers over to the given handler.
 func DownloadURLs(urls []string, handler func(string, io.Reader) error) error {
+	config.WaitReady()
 	for _, url := range urls {
 		if err := downloadURL(url, handler); err != nil {
 			return err