mirror of https://github.com/jlelse/GoBlog
Improve content negotiation and activity streams
This commit is contained in:
parent
13f770dd7f
commit
163e22c49c
|
@ -5,20 +5,28 @@ import (
|
|||
"crypto/x509"
|
||||
"encoding/json"
|
||||
"encoding/pem"
|
||||
"fmt"
|
||||
"net/http"
|
||||
"strings"
|
||||
|
||||
"github.com/araddon/dateparse"
|
||||
"github.com/elnormous/contenttype"
|
||||
)
|
||||
|
||||
var asContext = []string{"https://www.w3.org/ns/activitystreams"}
|
||||
|
||||
var asCheckMediaTypes = []contenttype.MediaType{
|
||||
contenttype.NewMediaType(contentTypeHTML),
|
||||
contenttype.NewMediaType(contentTypeAS),
|
||||
contenttype.NewMediaType("application/ld+json"),
|
||||
}
|
||||
|
||||
const asRequestKey requestContextKey = "asRequest"
|
||||
|
||||
func checkActivityStreamsRequest(next http.Handler) http.Handler {
|
||||
return http.HandlerFunc(func(rw http.ResponseWriter, r *http.Request) {
|
||||
if ap := appConfig.ActivityPub; ap != nil && ap.Enabled {
|
||||
if lowerAccept := strings.ToLower(r.Header.Get("Accept")); (strings.Contains(lowerAccept, contentTypeAS) || strings.Contains(lowerAccept, "application/ld+json")) && !strings.Contains(lowerAccept, contentTypeHTML) {
|
||||
// Check if accepted media type is not HTML
|
||||
if mt, _, err := contenttype.GetAcceptableMediaType(r, asCheckMediaTypes); err == nil && mt.String() != asCheckMediaTypes[0].String() {
|
||||
next.ServeHTTP(rw, r.WithContext(context.WithValue(r.Context(), asRequestKey, true)))
|
||||
return
|
||||
}
|
||||
|
@ -41,6 +49,7 @@ type asNote struct {
|
|||
ID string `json:"id,omitempty"`
|
||||
URL string `json:"url,omitempty"`
|
||||
AttributedTo string `json:"attributedTo,omitempty"`
|
||||
Tag []*asTag `json:"tag,omitempty"`
|
||||
}
|
||||
|
||||
type asPerson struct {
|
||||
|
@ -62,6 +71,12 @@ type asAttachment struct {
|
|||
URL string `json:"url,omitempty"`
|
||||
}
|
||||
|
||||
type asTag struct {
|
||||
Type string `json:"type,omitempty"`
|
||||
Name string `json:"name,omitempty"`
|
||||
Href string `json:"href,omitempty"`
|
||||
}
|
||||
|
||||
type asPublicKey struct {
|
||||
ID string `json:"id,omitempty"`
|
||||
Owner string `json:"owner,omitempty"`
|
||||
|
@ -106,6 +121,16 @@ func (p *post) toASNote() *asNote {
|
|||
})
|
||||
}
|
||||
}
|
||||
// Tags
|
||||
for _, tagTax := range appConfig.ActivityPub.TagsTaxonomies {
|
||||
for _, tag := range p.Parameters[tagTax] {
|
||||
as.Tag = append(as.Tag, &asTag{
|
||||
Type: "Hashtag",
|
||||
Name: tag,
|
||||
Href: appConfig.Server.PublicAddress + appConfig.Blogs[p.Blog].getRelativePath(fmt.Sprintf("/%s/%s", tagTax, urlize(tag))),
|
||||
})
|
||||
}
|
||||
}
|
||||
// Dates
|
||||
dateFormat := "2006-01-02T15:04:05-07:00"
|
||||
if p.Published != "" {
|
||||
|
|
|
@ -184,6 +184,7 @@ type configRegexRedirect struct {
|
|||
type configActivityPub struct {
|
||||
Enabled bool `mapstructure:"enabled"`
|
||||
KeyPath string `mapstructure:"keyPath"`
|
||||
TagsTaxonomies []string `mapstructure:"tagsTaxonomies"`
|
||||
}
|
||||
|
||||
type configNotifications struct {
|
||||
|
@ -230,6 +231,7 @@ func initConfig() error {
|
|||
viper.SetDefault("micropub.photoParam", "images")
|
||||
viper.SetDefault("micropub.photoDescriptionParam", "imagealts")
|
||||
viper.SetDefault("activityPub.keyPath", "data/private.pem")
|
||||
viper.SetDefault("activityPub.tagsTaxonomies", []string{"tags"})
|
||||
// Unmarshal config
|
||||
err = viper.Unmarshal(appConfig)
|
||||
if err != nil {
|
||||
|
|
10
errors.go
10
errors.go
|
@ -3,7 +3,8 @@ package main
|
|||
import (
|
||||
"fmt"
|
||||
"net/http"
|
||||
"strings"
|
||||
|
||||
"github.com/elnormous/contenttype"
|
||||
)
|
||||
|
||||
type errorData struct {
|
||||
|
@ -15,8 +16,13 @@ func serve404(w http.ResponseWriter, r *http.Request) {
|
|||
serveError(w, r, fmt.Sprintf("%s was not found", r.RequestURI), http.StatusNotFound)
|
||||
}
|
||||
|
||||
var errorCheckMediaTypes = []contenttype.MediaType{
|
||||
contenttype.NewMediaType(contentTypeHTML),
|
||||
}
|
||||
|
||||
func serveError(w http.ResponseWriter, r *http.Request, message string, status int) {
|
||||
if !strings.Contains(strings.ToLower(r.Header.Get("Accept")), contentTypeHTML) {
|
||||
if mt, _, err := contenttype.GetAcceptableMediaType(r, errorCheckMediaTypes); err != nil || mt.String() != errorCheckMediaTypes[0].String() {
|
||||
// Request doesn't accept HTML
|
||||
http.Error(w, message, status)
|
||||
return
|
||||
}
|
||||
|
|
1
go.mod
1
go.mod
|
@ -11,6 +11,7 @@ require (
|
|||
github.com/caddyserver/certmagic v0.12.0
|
||||
github.com/dchest/captcha v0.0.0-20200903113550-03f5f0333e1f
|
||||
github.com/dgrijalva/jwt-go v3.2.0+incompatible
|
||||
github.com/elnormous/contenttype v0.0.0-20210110050721-79150725153f
|
||||
github.com/go-chi/chi/v5 v5.0.0
|
||||
github.com/go-fed/httpsig v1.1.0
|
||||
github.com/go-sql-driver/mysql v1.5.0 // indirect
|
||||
|
|
2
go.sum
2
go.sum
|
@ -62,6 +62,8 @@ github.com/dgrijalva/jwt-go v3.2.0+incompatible h1:7qlOGliEKZXTDg6OTjfoBKDXWrumC
|
|||
github.com/dgrijalva/jwt-go v3.2.0+incompatible/go.mod h1:E3ru+11k8xSBh+hMPgOLZmtrrCbhqsmaPHjLKYnJCaQ=
|
||||
github.com/dgryski/go-sip13 v0.0.0-20181026042036-e10d5fee7954/go.mod h1:vAd38F8PWV+bWy6jNmig1y/TA+kYO4g3RSRF0IAv0no=
|
||||
github.com/dustin/go-humanize v1.0.0/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25KnS6fMYU6eOk=
|
||||
github.com/elnormous/contenttype v0.0.0-20210110050721-79150725153f h1:juwLa2Kbp2uwOGMOagrkTYXN/5+7sbINMmIZSluH2Gc=
|
||||
github.com/elnormous/contenttype v0.0.0-20210110050721-79150725153f/go.mod h1:ngVcyGGU8pnn4QJ5sL4StrNgc/wmXZXy5IQSBuHOFPg=
|
||||
github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4=
|
||||
github.com/felixge/httpsnoop v1.0.1 h1:lvB5Jl89CsZtGIWuTcDM1E/vkVs49/Ml7JJe07l8SPQ=
|
||||
github.com/felixge/httpsnoop v1.0.1/go.mod h1:m8KPJKqk1gH5J9DgRY2ASl2lWCfGKXixSwevea8zH2U=
|
||||
|
|
Loading…
Reference in New Issue