From 381c0109c036ded017b253543ba3c41906431f68 Mon Sep 17 00:00:00 2001 From: dbampalikis Date: Wed, 1 Nov 2023 09:19:09 +0100 Subject: [PATCH] Add case for encrypted files in download testing stuff --- api/sda/sda.go | 62 ++++++++++++++++++++++++++++++++++++++++++-------- 1 file changed, 53 insertions(+), 9 deletions(-) diff --git a/api/sda/sda.go b/api/sda/sda.go index 2f7b137..ef22f21 100644 --- a/api/sda/sda.go +++ b/api/sda/sda.go @@ -195,16 +195,29 @@ func Download(c *gin.Context) { return } - hr := bytes.NewReader(fileDetails.Header) - mr := io.MultiReader(hr, file) - c4ghr, err := streaming.NewCrypt4GHReader(mr, *config.Config.App.Crypt4GHKey, nil) - if err != nil { - log.Errorf("could not prepare file for streaming, %s", err) - c.String(http.StatusInternalServerError, "file stream error") + // Stitch file and prepare it for streaming + var fileStream *streaming.Crypt4GHReader + switch c.Param("type") { + case "encrypted": + log.Print("Return encrypted file") + fileStream, err = stitchEncryptedFile(fileDetails.Header, file) + if err != nil { + log.Errorf("could not prepare file for streaming, %s", err) + c.String(http.StatusInternalServerError, "file stream error") - return + return + } + c.Header("Content-Length", "") + default: + // Stitch file and prepare it for streaming + fileStream, err = stitchFile(fileDetails.Header, file) + if err != nil { + log.Errorf("could not prepare file for streaming, %s", err) + c.String(http.StatusInternalServerError, "file stream error") + + return + } } - defer c4ghr.Close() // Get query params qStart := c.DefaultQuery("startCoordinate", "0") @@ -212,6 +225,7 @@ func Download(c *gin.Context) { // Parse and verify coordinates are valid start, err := strconv.ParseInt(qStart, 10, 0) + if err != nil { log.Errorf("failed to convert start coordinate %d to integer, %s", start, err) c.String(http.StatusBadRequest, "startCoordinate must be an integer") @@ -242,7 +256,7 @@ func Download(c *gin.Context) { c.Header("Content-Length", fmt.Sprint(togo)) } - err = sendStream(c4ghr, c.Writer, start, end) + err = sendStream(fileStream, c.Writer, start, end) if err != nil { log.Errorf("error occurred while sending stream: %v", err) c.String(http.StatusInternalServerError, "an error occurred") @@ -251,6 +265,36 @@ func Download(c *gin.Context) { } } +// stitchFile stitches the header and file body together for Crypt4GHReader +// and returns a streamable Reader +var stitchFile = func(header []byte, file io.ReadCloser) (*streaming.Crypt4GHReader, error) { + log.Debugf("stitching header to file %s for streaming", file) + // Stitch header and file body together + hr := bytes.NewReader(header) + mr := io.MultiReader(hr, file) + + c4ghr, err := streaming.NewCrypt4GHReader(mr, *config.Config.App.Crypt4GHKey, nil) + //defer c4ghr.Close() + return c4ghr, err +} + +// stitchEncryptedFile stitches the header and file body together for Crypt4GHReader +// and returns a streamable Reader +var stitchEncryptedFile = func(header []byte, file io.ReadCloser) (*streaming.Crypt4GHReader, error) { + log.Debugf("stitching header to file %s for streaming", file) + // Stitch header and file body together + hr := bytes.NewReader(header) + + encryptedFile := io.MultiReader(hr, io.MultiReader(hr, file)) + + log.Print("Encrypted file:", encryptedFile) + + log.Debugf("file stream for %s constructed", file) + c4ghr, err := streaming.NewCrypt4GHReader(encryptedFile, *config.Config.App.Crypt4GHKey, nil) + + return c4ghr, err +} + // sendStream // used from: https://github.com/neicnordic/crypt4gh/blob/master/examples/reader/main.go#L48C1-L113C1 var sendStream = func(reader *streaming.Crypt4GHReader, writer http.ResponseWriter, start, end int64) error {