From a52f83378bf4057e04ff185604afff5abea44652 Mon Sep 17 00:00:00 2001 From: Maxim Lebedev Date: Wed, 14 Feb 2024 21:24:20 +0600 Subject: [PATCH] :building_construction: Connect and use entry handler in home cmd --- internal/cmd/home/home.go | 123 +++++++++----------------------------- 1 file changed, 27 insertions(+), 96 deletions(-) diff --git a/internal/cmd/home/home.go b/internal/cmd/home/home.go index 4e5c600..3aec5d9 100644 --- a/internal/cmd/home/home.go +++ b/internal/cmd/home/home.go @@ -3,11 +3,11 @@ package home import ( "bytes" "context" - "errors" "fmt" "io" "io/fs" "log" + "mime" "net" "net/http" "os" @@ -18,7 +18,7 @@ import ( "source.toby3d.me/toby3d/home/internal/common" "source.toby3d.me/toby3d/home/internal/domain" - "source.toby3d.me/toby3d/home/internal/entry" + entryhttpdelivery "source.toby3d.me/toby3d/home/internal/entry/delivery/http" pagefsrepo "source.toby3d.me/toby3d/home/internal/entry/repository/fs" pageucase "source.toby3d.me/toby3d/home/internal/entry/usecase" "source.toby3d.me/toby3d/home/internal/middleware" @@ -62,31 +62,40 @@ func NewApp(logger *log.Logger, config *domain.Config) (*App, error) { serverer := servercase.NewServerUseCase(sites) webfingerer := webfingerucase.NewWebFingerUseCase(sites) webfingerHandler := webfingerhttpdelivery.NewHandler(webfingerer) + entryHandler := entryhttpdelivery.NewHandler(siter, entrier, themer) handler := http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { // NOTE(toby3d): any static file is public and unprotected by // design, so it's safe to search it first before deep down to // any page or it's resource which might be protected by // middleware or something else. - if static, err := staticer.Do(r.Context(), strings.TrimPrefix(r.URL.Path, "/")); err == nil { + if static, err := staticer.Do(r.Context(), r.URL.Path); err == nil { http.ServeContent(w, r, static.Name(), static.ModTime(), static) return } head, tail := urlutil.ShiftPath(r.URL.Path) - lang := domain.LanguageUnd - - // NOTE(toby3d): read $HOME_CONTENT_DIR/index.md as a source of - // truth and global settings for any child entry. - s, err := siter.Do(r.Context(), lang) - if err != nil { - http.Error(w, err.Error(), http.StatusInternalServerError) - - return - } switch strings.ToLower(head) { case "": + contentType, _, _ := mime.ParseMediaType(r.Header.Get(common.HeaderAccept)) + + switch contentType { + case common.MIMEApplicationLdJSON: // NOTE(toby3d): show entry as ActivityPub object. + entryHandler.ServeHTTP(w, r) + + return + } + + // NOTE(toby3d): read $HOME_CONTENT_DIR/index.md as a source of + // truth and global settings for any child entry. + s, err := siter.Do(r.Context(), domain.LanguageUnd) + if err != nil { + http.Error(w, err.Error(), http.StatusInternalServerError) + + return + } + if s.IsMultiLingual() { supported := make([]language.Tag, len(s.Languages)) for i := range s.Languages { @@ -105,37 +114,11 @@ func NewApp(logger *log.Logger, config *domain.Config) (*App, error) { } matched, _, _ := language.NewMatcher(supported).Match(requested...) - lang = domain.NewLanguage(matched.String()) - - http.Redirect(w, r, "/"+lang.Lang()+"/", http.StatusSeeOther) + http.Redirect(w, r, "/"+domain.NewLanguage(matched.String()).Lang()+"/", + http.StatusSeeOther) return } - - e, err := entrier.Do(r.Context(), lang, r.URL.Path) - if err != nil { - if errors.Is(err, entry.ErrNotExist) { - http.NotFound(w, r) - } else { - http.Error(w, err.Error(), http.StatusInternalServerError) - } - - return - } - - template, err := themer.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) - } - - return case ".well-known": switch strings.ToLower(tail) { case "/webfinger": @@ -145,27 +128,7 @@ func NewApp(logger *log.Logger, config *domain.Config) (*App, error) { } } - if s.IsMultiLingual() { - // NOTE(toby3d): $HOME_CONTENT_DIR contains at least two - // index.md with different language codes. - head, tail = urlutil.ShiftPath(r.URL.Path) - - // NOTE(toby3d): client request '/:lang/...', try to - // understand which language code in subdir is requested. - if lang = domain.NewLanguage(head); lang != domain.LanguageUnd { - r.URL.Path = tail - } - - // NOTE(toby3d): get localized site config for requested - // subdir if exists. - if s, err = siter.Do(r.Context(), lang); err != nil { - http.Error(w, err.Error(), http.StatusInternalServerError) - - return - } - } - - if res, err := resourcer.Do(r.Context(), r.URL.Path); err == nil { + if res, err := resourcer.Do(r.Context(), tail); err == nil { // TODO(toby3d) : ugly workaround, must be refactored resFile, err := contentDir.Open(res.File.Filename()) if err != nil { @@ -188,42 +151,10 @@ func NewApp(logger *log.Logger, config *domain.Config) (*App, error) { return } - // NOTE(toby3d): search entry for requested URL and language - // code in subdir. - e, err := entrier.Do(r.Context(), lang, tail) - if err != nil { - if errors.Is(err, entry.ErrNotExist) { - http.NotFound(w, r) - } else { - http.Error(w, err.Error(), http.StatusInternalServerError) - } - - return - } - - // 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 := themer.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) - } + entryHandler.ServeHTTP(w, r) }) chain := middleware.Chain{ - middleware.LogFmt(), + // middleware.LogFmt(), middleware.Redirect(middleware.RedirectConfig{Serverer: serverer}), middleware.Header(middleware.HeaderConfig{Serverer: serverer}), }