♻️ Simplify entry HTTP delivery
This commit is contained in:
parent
8cf7d160c2
commit
c420a83618
|
@ -1,11 +1,11 @@
|
||||||
package http
|
package http
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"context"
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"errors"
|
"fmt"
|
||||||
"mime"
|
"mime"
|
||||||
"net/http"
|
"net/http"
|
||||||
"strings"
|
|
||||||
|
|
||||||
"github.com/go-ap/activitypub"
|
"github.com/go-ap/activitypub"
|
||||||
|
|
||||||
|
@ -13,21 +13,11 @@ import (
|
||||||
"source.toby3d.me/toby3d/home/internal/domain"
|
"source.toby3d.me/toby3d/home/internal/domain"
|
||||||
"source.toby3d.me/toby3d/home/internal/entry"
|
"source.toby3d.me/toby3d/home/internal/entry"
|
||||||
"source.toby3d.me/toby3d/home/internal/site"
|
"source.toby3d.me/toby3d/home/internal/site"
|
||||||
"source.toby3d.me/toby3d/home/internal/theme"
|
|
||||||
"source.toby3d.me/toby3d/home/internal/urlutil"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
type (
|
type (
|
||||||
Handler struct {
|
Handler struct {
|
||||||
*ThemeHandler
|
|
||||||
*ActivityPubHandler
|
|
||||||
sites site.UseCase
|
|
||||||
entries entry.UseCase
|
entries entry.UseCase
|
||||||
themes theme.UseCase
|
|
||||||
}
|
|
||||||
|
|
||||||
ThemeHandler struct {
|
|
||||||
themes theme.UseCase
|
|
||||||
}
|
}
|
||||||
|
|
||||||
ActivityPubHandler struct{}
|
ActivityPubHandler struct{}
|
||||||
|
@ -58,78 +48,26 @@ type (
|
||||||
*/
|
*/
|
||||||
)
|
)
|
||||||
|
|
||||||
func NewHandler(sites site.UseCase, entries entry.UseCase, themes theme.UseCase) *Handler {
|
func NewHandler(sites site.UseCase, entries entry.UseCase) *Handler {
|
||||||
return &Handler{
|
return &Handler{
|
||||||
sites: sites,
|
entries: entries,
|
||||||
entries: entries,
|
|
||||||
themes: themes,
|
|
||||||
ThemeHandler: NewThemeHandler(themes),
|
|
||||||
ActivityPubHandler: NewActivityPubHandler(),
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (h *Handler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
|
func (h *Handler) Handle(ctx context.Context, site *domain.Site, path string) (*domain.Entry, http.Handler, error) {
|
||||||
head, tail := urlutil.ShiftPath(r.URL.Path)
|
entry, err := h.entries.Do(ctx, site.Language, path)
|
||||||
|
|
||||||
lang := domain.NewLanguage(head)
|
|
||||||
|
|
||||||
s, err := h.sites.Do(r.Context(), lang)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
http.Error(w, err.Error(), http.StatusInternalServerError)
|
return nil, nil, fmt.Errorf("cannot handle entry: %w", err)
|
||||||
|
|
||||||
return
|
|
||||||
}
|
}
|
||||||
|
|
||||||
e, err := h.entries.Do(r.Context(), lang, tail)
|
return entry, http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||||
if err != nil {
|
contentType, _, _ := mime.ParseMediaType(r.Header.Get(common.HeaderAccept))
|
||||||
if errors.Is(err, entry.ErrNotExist) {
|
|
||||||
http.NotFound(w, r)
|
switch contentType {
|
||||||
} else {
|
case common.MIMEApplicationLdJSON:
|
||||||
http.Error(w, err.Error(), http.StatusInternalServerError)
|
h.ActivityPubHandler.Handle(s, e).ServeHTTP(w, r)
|
||||||
}
|
}
|
||||||
|
}), nil
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
contentType, _, _ := mime.ParseMediaType(r.Header.Get(common.HeaderAccept))
|
|
||||||
|
|
||||||
switch contentType {
|
|
||||||
default:
|
|
||||||
h.ThemeHandler.Handle(s, e).ServeHTTP(w, r)
|
|
||||||
case common.MIMEApplicationLdJSON:
|
|
||||||
h.ActivityPubHandler.Handle(s, e).ServeHTTP(w, r)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func NewThemeHandler(themes theme.UseCase) *ThemeHandler {
|
|
||||||
return &ThemeHandler{
|
|
||||||
themes: themes,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (h *ThemeHandler) Handle(s *domain.Site, e *domain.Entry) http.Handler {
|
|
||||||
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
|
||||||
// NOTE(toby3d): wrap founded entry into theme template and
|
|
||||||
// answer to client.
|
|
||||||
contentLanguage := make([]string, len(e.Translations))
|
|
||||||
for i := range e.Translations {
|
|
||||||
contentLanguage[i] = e.Translations[i].Language.Code()
|
|
||||||
}
|
|
||||||
|
|
||||||
w.Header().Set(common.HeaderContentLanguage, strings.Join(contentLanguage, ", "))
|
|
||||||
|
|
||||||
template, err := h.themes.Do(r.Context(), s, e)
|
|
||||||
if err != nil {
|
|
||||||
http.Error(w, err.Error(), http.StatusInternalServerError)
|
|
||||||
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
w.Header().Set(common.HeaderContentType, common.MIMETextHTMLCharsetUTF8)
|
|
||||||
if err = template(w); err != nil {
|
|
||||||
http.Error(w, err.Error(), http.StatusInternalServerError)
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewActivityPubHandler() *ActivityPubHandler {
|
func NewActivityPubHandler() *ActivityPubHandler {
|
||||||
|
|
|
@ -11,7 +11,6 @@ import (
|
||||||
entryucase "source.toby3d.me/toby3d/home/internal/entry/usecase"
|
entryucase "source.toby3d.me/toby3d/home/internal/entry/usecase"
|
||||||
siteucase "source.toby3d.me/toby3d/home/internal/site/usecase"
|
siteucase "source.toby3d.me/toby3d/home/internal/site/usecase"
|
||||||
"source.toby3d.me/toby3d/home/internal/testutil"
|
"source.toby3d.me/toby3d/home/internal/testutil"
|
||||||
themeucase "source.toby3d.me/toby3d/home/internal/theme/usecase"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestHandler_ServeHTTP(t *testing.T) {
|
func TestHandler_ServeHTTP(t *testing.T) {
|
||||||
|
@ -36,7 +35,6 @@ func TestHandler_ServeHTTP(t *testing.T) {
|
||||||
delivery.NewHandler(
|
delivery.NewHandler(
|
||||||
siteucase.NewStubSiteUseCase(domain.TestSite(t), nil),
|
siteucase.NewStubSiteUseCase(domain.TestSite(t), nil),
|
||||||
entryucase.NewStubEntryUseCase(domain.TestEntry(t), nil),
|
entryucase.NewStubEntryUseCase(domain.TestEntry(t), nil),
|
||||||
themeucase.NewDummyThemeUseCase(),
|
|
||||||
).ServeHTTP(w, req)
|
).ServeHTTP(w, req)
|
||||||
testutil.GoldenEqual(t, w.Result().Body)
|
testutil.GoldenEqual(t, w.Result().Body)
|
||||||
})
|
})
|
||||||
|
|
Loading…
Reference in New Issue