Skip to content

Commit

Permalink
chore: implement memo route
Browse files Browse the repository at this point in the history
  • Loading branch information
boojack committed Dec 14, 2023
1 parent 6cf7192 commit 5274301
Show file tree
Hide file tree
Showing 3 changed files with 58 additions and 10 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ tmp

# Frontend asset
web/dist
server/frontend/dist

# build folder
build
Expand Down
57 changes: 53 additions & 4 deletions server/frontend/frontend.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package frontend

import (
"embed"
"fmt"
"io/fs"
"net/http"
"strings"
Expand All @@ -10,6 +11,8 @@ import (
"github.com/labstack/echo/v4/middleware"

"github.com/usememos/memos/internal/util"
"github.com/usememos/memos/server/profile"
"github.com/usememos/memos/store"
)

//go:embed dist
Expand All @@ -18,7 +21,19 @@ var embeddedFiles embed.FS
//go:embed dist/index.html
var rawIndexHTML string

func Serve(e *echo.Echo) {
type FrontendService struct {
Profile *profile.Profile
Store *store.Store
}

func NewFrontendService(profile *profile.Profile, store *store.Store) *FrontendService {
return &FrontendService{
Profile: profile,
Store: store,
}
}

func (s *FrontendService) Serve(e *echo.Echo) {
// Use echo static middleware to serve the built dist folder
// refer: https://github.com/labstack/echo/blob/master/middleware/static.go
e.Use(middleware.StaticWithConfig(middleware.StaticConfig{
Expand All @@ -44,16 +59,50 @@ func Serve(e *echo.Echo) {
Filesystem: getFileSystem("dist/assets"),
}))

registerRoutes(e)
s.registerRoutes(e)
}

func registerRoutes(e *echo.Echo) {
func (s *FrontendService) registerRoutes(e *echo.Echo) {
e.GET("/m/:memoID", func(c echo.Context) error {
indexHTML := strings.ReplaceAll(rawIndexHTML, "<!-- memos.metadata -->", "<meta name=\"memos-memo-id\" content=\""+c.Param("memoID")+"\">"+"\n")
ctx := c.Request().Context()
memoID, err := util.ConvertStringToInt32(c.Param("memoID"))
if err != nil {
return echo.NewHTTPError(http.StatusBadRequest, "invalid memo id")
}

memo, err := s.Store.GetMemo(ctx, &store.FindMemo{
ID: &memoID,
})
if err != nil {
return echo.NewHTTPError(http.StatusInternalServerError, "failed to retrieve memo")
}
if memo == nil {
return echo.NewHTTPError(http.StatusNotFound, "memo not found")
}
if memo.Visibility != store.Public {
return echo.NewHTTPError(http.StatusForbidden, "memo is not public")
}
indexHTML := strings.ReplaceAll(rawIndexHTML, "<!-- memos.metadata -->", generateMemoMetadata(memo))
return c.HTML(http.StatusOK, indexHTML)
})
}

func generateMemoMetadata(memo *store.Memo) string {
metadataList := []string{
fmt.Sprintf(`<meta name="description" content="%s" />`, memo.Content),
fmt.Sprintf(`<meta property="og:title" content="%s" />`, fmt.Sprintf("Memos - %d", memo.ID)),
fmt.Sprintf(`<meta property="og:description" content="%s" />`, memo.Content),
fmt.Sprintf(`<meta property="og:image" content="%s" />`, "https://www.usememos.com/logo.png"),
`<meta property="og:type" content="website" />`,
// Twitter related metadata.
fmt.Sprintf(`<meta name="twitter:title" content="%s" />`, fmt.Sprintf("Memos - %d", memo.ID)),
fmt.Sprintf(`<meta name="twitter:description" content="%s" />`, memo.Content),
fmt.Sprintf(`<meta name="twitter:image" content="%s" />`, "https://www.usememos.com/logo.png"),
`<meta name="twitter:card" content="summary" />`,
}
return strings.Join(metadataList, "\n")
}

func getFileSystem(path string) http.FileSystem {
fs, err := fs.Sub(embeddedFiles, path)
if err != nil {
Expand Down
10 changes: 4 additions & 6 deletions server/server.go
Original file line number Diff line number Diff line change
Expand Up @@ -33,9 +33,6 @@ type Server struct {
Profile *profile.Profile
Store *store.Store

// API services.
apiV2Service *apiv2.APIV2Service

// Asynchronous runners.
backupRunner *backup.BackupRunner
telegramBot *telegram.Bot
Expand Down Expand Up @@ -84,7 +81,8 @@ func NewServer(ctx context.Context, profile *profile.Profile, store *store.Store
s.ID = serverID

// Serve frontend.
frontend.Serve(e)
frontendService := frontend.NewFrontendService(profile, store)
frontendService.Serve(e)

// Serve swagger in dev/demo mode.
if profile.Mode == "dev" || profile.Mode == "demo" {
Expand All @@ -110,9 +108,9 @@ func NewServer(ctx context.Context, profile *profile.Profile, store *store.Store
apiV1Service := apiv1.NewAPIV1Service(s.Secret, profile, store, s.telegramBot)
apiV1Service.Register(rootGroup)

s.apiV2Service = apiv2.NewAPIV2Service(s.Secret, profile, store, s.Profile.Port+1)
apiV2Service := apiv2.NewAPIV2Service(s.Secret, profile, store, s.Profile.Port+1)
// Register gRPC gateway as api v2.
if err := s.apiV2Service.RegisterGateway(ctx, e); err != nil {
if err := apiV2Service.RegisterGateway(ctx, e); err != nil {
return nil, errors.Wrap(err, "failed to register gRPC gateway")
}

Expand Down

0 comments on commit 5274301

Please sign in to comment.