summaryrefslogtreecommitdiff
path: root/internal/api
diff options
context:
space:
mode:
Diffstat (limited to 'internal/api')
-rw-r--r--internal/api/util/mime.go1
-rw-r--r--internal/api/util/negotiate.go5
-rw-r--r--internal/api/wellknown.go4
-rw-r--r--internal/api/wellknown/hostmeta/hostmeta.go45
-rw-r--r--internal/api/wellknown/hostmeta/hostmetaget.go73
5 files changed, 128 insertions, 0 deletions
diff --git a/internal/api/util/mime.go b/internal/api/util/mime.go
index 30f0f0d6e..cfdc3b08b 100644
--- a/internal/api/util/mime.go
+++ b/internal/api/util/mime.go
@@ -25,6 +25,7 @@ type MIME string
const (
AppJSON MIME = `application/json`
AppXML MIME = `application/xml`
+ AppXMLXRD MIME = `application/xrd+xml`
AppRSSXML MIME = `application/rss+xml`
AppActivityJSON MIME = `application/activity+json`
AppActivityLDJSON MIME = `application/ld+json; profile="https://www.w3.org/ns/activitystreams"`
diff --git a/internal/api/util/negotiate.go b/internal/api/util/negotiate.go
index 3a5f21775..06a202815 100644
--- a/internal/api/util/negotiate.go
+++ b/internal/api/util/negotiate.go
@@ -58,6 +58,11 @@ var HTMLOrActivityPubHeaders = []MIME{
AppActivityLDJSON,
}
+var HostMetaHeaders = []MIME{
+ AppXMLXRD,
+ AppXML,
+}
+
// 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/wellknown.go b/internal/api/wellknown.go
index 7edbb4d7d..a837667fb 100644
--- a/internal/api/wellknown.go
+++ b/internal/api/wellknown.go
@@ -20,6 +20,7 @@ package api
import (
"github.com/gin-gonic/gin"
+ "github.com/superseriousbusiness/gotosocial/internal/api/wellknown/hostmeta"
"github.com/superseriousbusiness/gotosocial/internal/api/wellknown/nodeinfo"
"github.com/superseriousbusiness/gotosocial/internal/api/wellknown/webfinger"
"github.com/superseriousbusiness/gotosocial/internal/middleware"
@@ -30,6 +31,7 @@ import (
type WellKnown struct {
nodeInfo *nodeinfo.Module
webfinger *webfinger.Module
+ hostMeta *hostmeta.Module
}
func (w *WellKnown) Route(r router.Router, m ...gin.HandlerFunc) {
@@ -45,11 +47,13 @@ func (w *WellKnown) Route(r router.Router, m ...gin.HandlerFunc) {
w.nodeInfo.Route(wellKnownGroup.Handle)
w.webfinger.Route(wellKnownGroup.Handle)
+ w.hostMeta.Route(wellKnownGroup.Handle)
}
func NewWellKnown(p *processing.Processor) *WellKnown {
return &WellKnown{
nodeInfo: nodeinfo.New(p),
webfinger: webfinger.New(p),
+ hostMeta: hostmeta.New(p),
}
}
diff --git a/internal/api/wellknown/hostmeta/hostmeta.go b/internal/api/wellknown/hostmeta/hostmeta.go
new file mode 100644
index 000000000..17eb748ec
--- /dev/null
+++ b/internal/api/wellknown/hostmeta/hostmeta.go
@@ -0,0 +1,45 @@
+/*
+ GoToSocial
+ Copyright (C) 2021-2023 GoToSocial Authors admin@gotosocial.org
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU Affero General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Affero General Public License for more details.
+
+ You should have received a copy of the GNU Affero General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
+*/
+
+package hostmeta
+
+import (
+ "net/http"
+
+ "github.com/gin-gonic/gin"
+ "github.com/superseriousbusiness/gotosocial/internal/processing"
+)
+
+const (
+ HostMetaContentType = "application/xrd+xml"
+ HostMetaPath = "/host-meta"
+)
+
+type Module struct {
+ processor *processing.Processor
+}
+
+func New(processor *processing.Processor) *Module {
+ return &Module{
+ processor: processor,
+ }
+}
+
+func (m *Module) Route(attachHandler func(method string, path string, f ...gin.HandlerFunc) gin.IRoutes) {
+ attachHandler(http.MethodGet, HostMetaPath, m.HostMetaGETHandler)
+}
diff --git a/internal/api/wellknown/hostmeta/hostmetaget.go b/internal/api/wellknown/hostmeta/hostmetaget.go
new file mode 100644
index 000000000..f45b2cf9c
--- /dev/null
+++ b/internal/api/wellknown/hostmeta/hostmetaget.go
@@ -0,0 +1,73 @@
+/*
+ GoToSocial
+ Copyright (C) 2021-2023 GoToSocial Authors admin@gotosocial.org
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU Affero General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Affero General Public License for more details.
+
+ You should have received a copy of the GNU Affero General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
+*/
+
+package hostmeta
+
+import (
+ "bytes"
+ "encoding/xml"
+ "net/http"
+
+ "github.com/gin-gonic/gin"
+ apiutil "github.com/superseriousbusiness/gotosocial/internal/api/util"
+ "github.com/superseriousbusiness/gotosocial/internal/gtserror"
+)
+
+// HostMetaGETHandler swagger:operation GET /.well-known/host-meta hostMetaGet
+//
+// Returns a compliant hostmeta response to web host metadata queries.
+//
+// See: https://www.rfc-editor.org/rfc/rfc6415.html
+//
+// ---
+// tags:
+// - .well-known
+//
+// produces:
+// - application/xrd+xml"
+//
+// responses:
+// '200':
+// schema:
+// "$ref": "#/definitions/hostmeta"
+func (m *Module) HostMetaGETHandler(c *gin.Context) {
+ if _, err := apiutil.NegotiateAccept(c, apiutil.HostMetaHeaders...); err != nil {
+ apiutil.ErrorHandler(c, gtserror.NewErrorNotAcceptable(err, err.Error()), m.processor.InstanceGetV1)
+ return
+ }
+
+ hostMeta := m.processor.Fedi().HostMetaGet()
+
+ // this setup with a separate buffer we encode into is used because
+ // xml.Marshal does not emit xml.Header by itself
+ var buf bytes.Buffer
+
+ // Preallocate buffer of reasonable length.
+ buf.Grow(len(xml.Header) + 64)
+
+ // No need to check for error on write to buffer.
+ _, _ = buf.WriteString(xml.Header)
+
+ // Encode host-meta as XML to in-memory buffer.
+ if err := xml.NewEncoder(&buf).Encode(hostMeta); err != nil {
+ apiutil.ErrorHandler(c, gtserror.NewErrorInternalError(err), m.processor.InstanceGetV1)
+ return
+ }
+
+ c.Data(http.StatusOK, HostMetaContentType, buf.Bytes())
+}