summaryrefslogtreecommitdiff
path: root/internal/api/util
diff options
context:
space:
mode:
authorLibravatar tobi <31960611+tsmethurst@users.noreply.github.com>2024-07-31 16:03:34 +0200
committerLibravatar GitHub <noreply@github.com>2024-07-31 15:03:34 +0100
commit38f041cea1ba0cd3492f351353a29aa5b73e2731 (patch)
treebdd055d5cf7d9c06523c694cb4abe86d220960d0 /internal/api/util
parent[feature] Object store custom URL (S3) (#3046) (diff)
downloadgotosocial-38f041cea1ba0cd3492f351353a29aa5b73e2731.tar.xz
[feature] Allow users to export data via the settings panel (#3140)
* [feature] Allow users to export data via the settings panel * rename/move some stuff
Diffstat (limited to 'internal/api/util')
-rw-r--r--internal/api/util/mime.go1
-rw-r--r--internal/api/util/negotiate.go6
-rw-r--r--internal/api/util/response.go42
3 files changed, 49 insertions, 0 deletions
diff --git a/internal/api/util/mime.go b/internal/api/util/mime.go
index 8dcbfc28c..4d8946e5d 100644
--- a/internal/api/util/mime.go
+++ b/internal/api/util/mime.go
@@ -35,6 +35,7 @@ const (
TextXML = `text/xml`
TextHTML = `text/html`
TextCSS = `text/css`
+ TextCSV = `text/csv`
)
// JSONContentType returns whether is application/json(;charset=utf-8)? content-type.
diff --git a/internal/api/util/negotiate.go b/internal/api/util/negotiate.go
index 5b4f54bc6..4910b7aef 100644
--- a/internal/api/util/negotiate.go
+++ b/internal/api/util/negotiate.go
@@ -88,6 +88,12 @@ var HostMetaHeaders = []string{
AppXML,
}
+// CSVHeaders just contains the text/csv
+// MIME type, used for import/export.
+var CSVHeaders = []string{
+ TextCSV,
+}
+
// NegotiateAccept takes the *gin.Context from an incoming request, and a
// slice of Offers, and performs content negotiation for the given request
// with the given content-type offers. It will return a string representation
diff --git a/internal/api/util/response.go b/internal/api/util/response.go
index afdc578aa..01f15ccfb 100644
--- a/internal/api/util/response.go
+++ b/internal/api/util/response.go
@@ -18,6 +18,7 @@
package util
import (
+ "encoding/csv"
"encoding/json"
"encoding/xml"
"io"
@@ -213,6 +214,47 @@ func EncodeXMLResponse(
putBuf(buf)
}
+// EncodeCSVResponse encodes 'records' as CSV HTTP response
+// to ResponseWriter with given status code, using CSV content-type.
+func EncodeCSVResponse(
+ rw http.ResponseWriter,
+ r *http.Request,
+ statusCode int,
+ records [][]string,
+) {
+ // Acquire buffer.
+ buf := getBuf()
+
+ // Wrap buffer in CSV writer.
+ csvWriter := csv.NewWriter(buf)
+
+ // Write all the records to the buffer.
+ if err := csvWriter.WriteAll(records); err == nil {
+ // Respond with the now-known
+ // size byte slice within buf.
+ WriteResponseBytes(rw, r,
+ statusCode,
+ TextCSV,
+ buf.B,
+ )
+ } else {
+ // This will always be an csv error, we
+ // can't really add any more useful context.
+ log.Error(r.Context(), err)
+
+ // Any error returned here is unrecoverable,
+ // set Internal Server Error JSON response.
+ WriteResponseBytes(rw, r,
+ http.StatusInternalServerError,
+ AppJSON,
+ StatusInternalServerErrorJSON,
+ )
+ }
+
+ // Release.
+ putBuf(buf)
+}
+
// writeResponseUnknownLength handles reading data of unknown legnth
// efficiently into memory, and passing on to WriteResponseBytes().
func writeResponseUnknownLength(