1
0
Fork 0
mirror of https://github.com/miniflux/v2.git synced 2025-09-15 18:57:04 +00:00

Implement structured logging using log/slog package

This commit is contained in:
Frédéric Guillot 2023-09-24 16:32:09 -07:00
parent 54cb8fa028
commit c0e954f19d
77 changed files with 1868 additions and 892 deletions

View file

@ -9,14 +9,14 @@ import (
"miniflux.app/v2/internal/http/request"
"miniflux.app/v2/internal/http/response/html"
"miniflux.app/v2/internal/http/route"
"miniflux.app/v2/internal/logger"
)
func (h *handler) removeAPIKey(w http.ResponseWriter, r *http.Request) {
keyID := request.RouteInt64Param(r, "keyID")
err := h.store.RemoveAPIKey(request.UserID(r), keyID)
if err != nil {
logger.Error("[UI:RemoveAPIKey] %v", err)
html.ServerError(w, r, err)
return
}
html.Redirect(w, r, route.Path(h.router, "apiKeys"))

View file

@ -9,7 +9,6 @@ import (
"miniflux.app/v2/internal/http/request"
"miniflux.app/v2/internal/http/response/html"
"miniflux.app/v2/internal/http/route"
"miniflux.app/v2/internal/logger"
"miniflux.app/v2/internal/model"
"miniflux.app/v2/internal/ui/form"
"miniflux.app/v2/internal/ui/session"
@ -47,9 +46,7 @@ func (h *handler) saveAPIKey(w http.ResponseWriter, r *http.Request) {
apiKey := model.NewAPIKey(user.ID, apiKeyForm.Description)
if err = h.store.CreateAPIKey(apiKey); err != nil {
logger.Error("[UI:SaveAPIKey] %v", err)
view.Set("errorMessage", "error.unable_to_create_api_key")
html.OK(w, r, view.Render("create_api_key"))
html.ServerError(w, r, err)
return
}

View file

@ -9,7 +9,6 @@ import (
"miniflux.app/v2/internal/http/request"
"miniflux.app/v2/internal/http/response/html"
"miniflux.app/v2/internal/http/route"
"miniflux.app/v2/internal/logger"
"miniflux.app/v2/internal/model"
"miniflux.app/v2/internal/ui/form"
"miniflux.app/v2/internal/ui/session"
@ -43,9 +42,7 @@ func (h *handler) saveCategory(w http.ResponseWriter, r *http.Request) {
}
if _, err = h.store.CreateCategory(loggedUser.ID, categoryRequest); err != nil {
logger.Error("[UI:SaveCategory] %v", err)
view.Set("errorMessage", "error.unable_to_create_category")
html.OK(w, r, view.Render("create_category"))
html.ServerError(w, r, err)
return
}

View file

@ -9,7 +9,6 @@ import (
"miniflux.app/v2/internal/http/request"
"miniflux.app/v2/internal/http/response/html"
"miniflux.app/v2/internal/http/route"
"miniflux.app/v2/internal/logger"
"miniflux.app/v2/internal/model"
"miniflux.app/v2/internal/ui/form"
"miniflux.app/v2/internal/ui/session"
@ -60,9 +59,7 @@ func (h *handler) updateCategory(w http.ResponseWriter, r *http.Request) {
categoryRequest.Patch(category)
if err := h.store.UpdateCategory(category); err != nil {
logger.Error("[UI:UpdateCategory] %v", err)
view.Set("errorMessage", "error.unable_to_update_category")
html.OK(w, r, view.Render("edit_category"))
html.ServerError(w, r, err)
return
}

View file

@ -4,12 +4,12 @@
package ui // import "miniflux.app/v2/internal/ui"
import (
"log/slog"
"net/http"
"miniflux.app/v2/internal/http/request"
"miniflux.app/v2/internal/http/response/html"
"miniflux.app/v2/internal/http/route"
"miniflux.app/v2/internal/logger"
feedHandler "miniflux.app/v2/internal/reader/handler"
)
@ -17,7 +17,12 @@ func (h *handler) refreshFeed(w http.ResponseWriter, r *http.Request) {
feedID := request.RouteInt64Param(r, "feedID")
forceRefresh := request.QueryBoolParam(r, "forceRefresh", false)
if err := feedHandler.RefreshFeed(h.store, request.UserID(r), feedID, forceRefresh); err != nil {
logger.Error("[UI:RefreshFeed] %v", err)
slog.Warn("Unable to refresh feed",
slog.Int64("user_id", request.UserID(r)),
slog.Int64("feed_id", feedID),
slog.Bool("force_refresh", forceRefresh),
slog.Any("error", err),
)
}
html.Redirect(w, r, route.Path(h.router, "feedEntries", "feedID", feedID))

View file

@ -10,7 +10,6 @@ import (
"miniflux.app/v2/internal/http/request"
"miniflux.app/v2/internal/http/response/html"
"miniflux.app/v2/internal/http/route"
"miniflux.app/v2/internal/logger"
"miniflux.app/v2/internal/model"
"miniflux.app/v2/internal/ui/form"
"miniflux.app/v2/internal/ui/session"
@ -74,9 +73,7 @@ func (h *handler) updateFeed(w http.ResponseWriter, r *http.Request) {
err = h.store.UpdateFeed(feedForm.Merge(feed))
if err != nil {
logger.Error("[UI:UpdateFeed] %v", err)
view.Set("errorMessage", "error.unable_to_update_feed")
html.OK(w, r, view.Render("edit_feed"))
html.ServerError(w, r, err)
return
}

View file

@ -4,6 +4,7 @@
package ui // import "miniflux.app/v2/internal/ui"
import (
"log/slog"
"net/http"
"miniflux.app/v2/internal/config"
@ -12,7 +13,6 @@ import (
"miniflux.app/v2/internal/http/route"
"miniflux.app/v2/internal/integration/pocket"
"miniflux.app/v2/internal/locale"
"miniflux.app/v2/internal/logger"
"miniflux.app/v2/internal/ui/session"
)
@ -35,7 +35,10 @@ func (h *handler) pocketAuthorize(w http.ResponseWriter, r *http.Request) {
redirectURL := config.Opts.RootURL() + route.Path(h.router, "pocketCallback")
requestToken, err := connector.RequestToken(redirectURL)
if err != nil {
logger.Error("[Pocket:Authorize] %v", err)
slog.Warn("Pocket authorization request failed",
slog.Any("user_id", user.ID),
slog.Any("error", err),
)
sess.NewFlashErrorMessage(printer.Printf("error.pocket_request_token"))
html.Redirect(w, r, route.Path(h.router, "integrations"))
return
@ -64,7 +67,10 @@ func (h *handler) pocketCallback(w http.ResponseWriter, r *http.Request) {
connector := pocket.NewConnector(config.Opts.PocketConsumerKey(integration.PocketConsumerKey))
accessToken, err := connector.AccessToken(request.PocketRequestToken(r))
if err != nil {
logger.Error("[Pocket:Callback] %v", err)
slog.Warn("Unable to get Pocket access token",
slog.Any("user_id", user.ID),
slog.Any("error", err),
)
sess.NewFlashErrorMessage(printer.Printf("error.pocket_access_token"))
html.Redirect(w, r, route.Path(h.router, "integrations"))
return

View file

@ -4,6 +4,7 @@
package ui // import "miniflux.app/v2/internal/ui"
import (
"log/slog"
"net/http"
"miniflux.app/v2/internal/config"
@ -11,7 +12,6 @@ import (
"miniflux.app/v2/internal/http/request"
"miniflux.app/v2/internal/http/response/html"
"miniflux.app/v2/internal/http/route"
"miniflux.app/v2/internal/logger"
"miniflux.app/v2/internal/ui/form"
"miniflux.app/v2/internal/ui/session"
"miniflux.app/v2/internal/ui/view"
@ -27,13 +27,25 @@ func (h *handler) checkLogin(w http.ResponseWriter, r *http.Request) {
view.Set("form", authForm)
if err := authForm.Validate(); err != nil {
logger.Error("[UI:CheckLogin] %v", err)
slog.Warn("Validation error during login check",
slog.Bool("authentication_failed", true),
slog.String("client_ip", clientIP),
slog.String("user_agent", r.UserAgent()),
slog.String("username", authForm.Username),
slog.Any("error", err),
)
html.OK(w, r, view.Render("login"))
return
}
if err := h.store.CheckPassword(authForm.Username, authForm.Password); err != nil {
logger.Error("[UI:CheckLogin] [ClientIP=%s] %v", clientIP, err)
slog.Warn("Incorrect username or password",
slog.Bool("authentication_failed", true),
slog.String("client_ip", clientIP),
slog.String("user_agent", r.UserAgent()),
slog.String("username", authForm.Username),
slog.Any("error", err),
)
html.OK(w, r, view.Render("login"))
return
}
@ -44,7 +56,14 @@ func (h *handler) checkLogin(w http.ResponseWriter, r *http.Request) {
return
}
logger.Info("[UI:CheckLogin] username=%s just logged in", authForm.Username)
slog.Info("User authenticated successfully with username/password",
slog.Bool("authentication_successful", true),
slog.String("client_ip", clientIP),
slog.String("user_agent", r.UserAgent()),
slog.Int64("user_id", userID),
slog.String("username", authForm.Username),
)
h.store.SetLastLogin(userID)
user, err := h.store.UserByID(userID)

View file

@ -11,7 +11,6 @@ import (
"miniflux.app/v2/internal/http/request"
"miniflux.app/v2/internal/http/response/html"
"miniflux.app/v2/internal/http/route"
"miniflux.app/v2/internal/logger"
"miniflux.app/v2/internal/ui/session"
)
@ -27,7 +26,8 @@ func (h *handler) logout(w http.ResponseWriter, r *http.Request) {
sess.SetTheme(user.Theme)
if err := h.store.RemoveUserSessionByToken(user.ID, request.UserSessionToken(r)); err != nil {
logger.Error("[UI:Logout] %v", err)
html.ServerError(w, r, err)
return
}
http.SetCookie(w, cookie.Expired(

View file

@ -6,6 +6,7 @@ package ui // import "miniflux.app/v2/internal/ui"
import (
"context"
"errors"
"log/slog"
"net/http"
"miniflux.app/v2/internal/config"
@ -13,7 +14,6 @@ import (
"miniflux.app/v2/internal/http/request"
"miniflux.app/v2/internal/http/response/html"
"miniflux.app/v2/internal/http/route"
"miniflux.app/v2/internal/logger"
"miniflux.app/v2/internal/model"
"miniflux.app/v2/internal/storage"
"miniflux.app/v2/internal/ui/session"
@ -38,11 +38,17 @@ func (m *middleware) handleUserSession(next http.Handler) http.Handler {
if m.isPublicRoute(r) {
next.ServeHTTP(w, r)
} else {
logger.Debug("[UI:UserSession] Session not found, redirect to login page")
slog.Debug("Redirecting to login page because no user session has been found",
slog.Any("url", r.RequestURI),
)
html.Redirect(w, r, route.Path(m.router, "login"))
}
} else {
logger.Debug("[UI:UserSession] %s", session)
slog.Debug("User session found",
slog.Any("url", r.RequestURI),
slog.Int64("user_id", session.UserID),
slog.Int64("user_session_id", session.ID),
)
ctx := r.Context()
ctx = context.WithValue(ctx, request.UserIDContextKey, session.UserID)
@ -62,14 +68,16 @@ func (m *middleware) handleAppSession(next http.Handler) http.Handler {
if session == nil {
if request.IsAuthenticated(r) {
userID := request.UserID(r)
logger.Debug("[UI:AppSession] Cookie expired but user #%d is logged: creating a new session", userID)
slog.Debug("Cookie expired but user is logged: creating a new app session",
slog.Int64("user_id", userID),
)
session, err = m.store.CreateAppSessionWithUserPrefs(userID)
if err != nil {
html.ServerError(w, r, err)
return
}
} else {
logger.Debug("[UI:AppSession] Session not found, creating a new one")
slog.Debug("App session not found, creating a new one")
session, err = m.store.CreateAppSession()
if err != nil {
html.ServerError(w, r, err)
@ -78,8 +86,6 @@ func (m *middleware) handleAppSession(next http.Handler) http.Handler {
}
http.SetCookie(w, cookie.New(cookie.CookieAppSessionID, session.ID, config.Opts.HTTPS, config.Opts.BasePath()))
} else {
logger.Debug("[UI:AppSession] %s", session)
}
if r.Method == http.MethodPost {
@ -87,7 +93,11 @@ func (m *middleware) handleAppSession(next http.Handler) http.Handler {
headerValue := r.Header.Get("X-Csrf-Token")
if session.Data.CSRF != formValue && session.Data.CSRF != headerValue {
logger.Error(`[UI:AppSession] Invalid or missing CSRF token: Form="%s", Header="%s"`, formValue, headerValue)
slog.Warn("Invalid or missing CSRF token",
slog.Any("url", r.RequestURI),
slog.String("form_csrf", formValue),
slog.String("header_csrf", headerValue),
)
if mux.CurrentRoute(r).GetName() == "checkLogin" {
html.Redirect(w, r, route.Path(m.router, "login"))
@ -121,7 +131,10 @@ func (m *middleware) getAppSessionValueFromCookie(r *http.Request) *model.Sessio
session, err := m.store.AppSession(cookieValue)
if err != nil {
logger.Error("[UI:AppSession] %v", err)
slog.Debug("Unable to fetch app session from the database; another session will be created",
slog.Any("cookie_value", cookieValue),
slog.Any("error", err),
)
return nil
}
@ -159,7 +172,10 @@ func (m *middleware) getUserSessionFromCookie(r *http.Request) *model.UserSessio
session, err := m.store.UserSessionByToken(cookieValue)
if err != nil {
logger.Error("[UI:UserSession] %v", err)
slog.Error("Unable to fetch user session from the database",
slog.Any("cookie_value", cookieValue),
slog.Any("error", err),
)
return nil
}
@ -180,7 +196,11 @@ func (m *middleware) handleAuthProxy(next http.Handler) http.Handler {
}
clientIP := request.ClientIP(r)
logger.Info("[AuthProxy] [ClientIP=%s] Received authenticated requested for %q", clientIP, username)
slog.Debug("[AuthProxy] Received authenticated requested",
slog.String("client_ip", clientIP),
slog.String("user_agent", r.UserAgent()),
slog.String("username", username),
)
user, err := m.store.UserByUsername(username)
if err != nil {
@ -189,9 +209,13 @@ func (m *middleware) handleAuthProxy(next http.Handler) http.Handler {
}
if user == nil {
logger.Error("[AuthProxy] [ClientIP=%s] %q doesn't exist", clientIP, username)
if !config.Opts.IsAuthProxyUserCreationAllowed() {
slog.Debug("[AuthProxy] User doesn't exist and user creation is not allowed",
slog.Bool("authentication_failed", true),
slog.String("client_ip", clientIP),
slog.String("user_agent", r.UserAgent()),
slog.String("username", username),
)
html.Forbidden(w, r)
return
}
@ -208,7 +232,13 @@ func (m *middleware) handleAuthProxy(next http.Handler) http.Handler {
return
}
logger.Info("[AuthProxy] [ClientIP=%s] username=%s just logged in", clientIP, user.Username)
slog.Info("[AuthProxy] User authenticated successfully",
slog.Bool("authentication_successful", true),
slog.String("client_ip", clientIP),
slog.String("user_agent", r.UserAgent()),
slog.Int64("user_id", user.ID),
slog.String("username", user.Username),
)
m.store.SetLastLogin(user.ID)

View file

@ -6,6 +6,7 @@ package ui // import "miniflux.app/v2/internal/ui"
import (
"crypto/subtle"
"errors"
"log/slog"
"net/http"
"miniflux.app/v2/internal/config"
@ -14,7 +15,6 @@ import (
"miniflux.app/v2/internal/http/response/html"
"miniflux.app/v2/internal/http/route"
"miniflux.app/v2/internal/locale"
"miniflux.app/v2/internal/logger"
"miniflux.app/v2/internal/model"
"miniflux.app/v2/internal/ui/session"
)
@ -26,41 +26,48 @@ func (h *handler) oauth2Callback(w http.ResponseWriter, r *http.Request) {
provider := request.RouteStringParam(r, "provider")
if provider == "" {
logger.Error("[OAuth2] Invalid or missing provider")
slog.Warn("Invalid or missing OAuth2 provider")
html.Redirect(w, r, route.Path(h.router, "login"))
return
}
code := request.QueryStringParam(r, "code", "")
if code == "" {
logger.Error("[OAuth2] No code received on callback")
slog.Warn("No code received on OAuth2 callback")
html.Redirect(w, r, route.Path(h.router, "login"))
return
}
state := request.QueryStringParam(r, "state", "")
if subtle.ConstantTimeCompare([]byte(state), []byte(request.OAuth2State(r))) == 0 {
logger.Error(`[OAuth2] Invalid state value: got "%s" instead of "%s"`, state, request.OAuth2State(r))
slog.Warn("Invalid OAuth2 state value received",
slog.String("expected", request.OAuth2State(r)),
slog.String("received", state),
)
html.Redirect(w, r, route.Path(h.router, "login"))
return
}
authProvider, err := getOAuth2Manager(r.Context()).FindProvider(provider)
if err != nil {
logger.Error("[OAuth2] %v", err)
slog.Error("Unable to initialize OAuth2 provider",
slog.String("provider", provider),
slog.Any("error", err),
)
html.Redirect(w, r, route.Path(h.router, "login"))
return
}
profile, err := authProvider.GetProfile(r.Context(), code, request.OAuth2CodeVerifier(r))
if err != nil {
logger.Error("[OAuth2] %v", err)
slog.Warn("Unable to get OAuth2 profile from provider",
slog.String("provider", provider),
slog.Any("error", err),
)
html.Redirect(w, r, route.Path(h.router, "login"))
return
}
logger.Info("[OAuth2] [ClientIP=%s] Successful auth for %s", clientIP, profile)
if request.IsAuthenticated(r) {
loggedUser, err := h.store.UserByID(request.UserID(r))
if err != nil {
@ -69,7 +76,11 @@ func (h *handler) oauth2Callback(w http.ResponseWriter, r *http.Request) {
}
if h.store.AnotherUserWithFieldExists(loggedUser.ID, profile.Key, profile.ID) {
logger.Error("[OAuth2] User #%d cannot be associated because it is already associated with another user", loggedUser.ID)
slog.Error("Oauth2 user cannot be associated because it is already associated with another user",
slog.Int64("user_id", loggedUser.ID),
slog.String("oauth2_provider", provider),
slog.String("oauth2_profile_id", profile.ID),
)
sess.NewFlashErrorMessage(printer.Printf("error.duplicate_linked_account"))
html.Redirect(w, r, route.Path(h.router, "settings"))
return
@ -119,7 +130,13 @@ func (h *handler) oauth2Callback(w http.ResponseWriter, r *http.Request) {
return
}
logger.Info("[OAuth2] [ClientIP=%s] username=%s (%s) just logged in", clientIP, user.Username, profile)
slog.Info("User authenticated successfully using OAuth2",
slog.Bool("authentication_successful", true),
slog.String("client_ip", clientIP),
slog.String("user_agent", r.UserAgent()),
slog.Int64("user_id", user.ID),
slog.String("username", user.Username),
)
h.store.SetLastLogin(user.ID)
sess.SetLanguage(user.Language)

View file

@ -4,12 +4,12 @@
package ui // import "miniflux.app/v2/internal/ui"
import (
"log/slog"
"net/http"
"miniflux.app/v2/internal/http/request"
"miniflux.app/v2/internal/http/response/html"
"miniflux.app/v2/internal/http/route"
"miniflux.app/v2/internal/logger"
"miniflux.app/v2/internal/oauth2"
"miniflux.app/v2/internal/ui/session"
)
@ -19,14 +19,17 @@ func (h *handler) oauth2Redirect(w http.ResponseWriter, r *http.Request) {
provider := request.RouteStringParam(r, "provider")
if provider == "" {
logger.Error("[OAuth2] Invalid or missing provider: %s", provider)
slog.Warn("Invalid or missing OAuth2 provider")
html.Redirect(w, r, route.Path(h.router, "login"))
return
}
authProvider, err := getOAuth2Manager(r.Context()).FindProvider(provider)
if err != nil {
logger.Error("[OAuth2] %v", err)
slog.Error("Unable to initialize OAuth2 provider",
slog.String("provider", provider),
slog.Any("error", err),
)
html.Redirect(w, r, route.Path(h.router, "login"))
return
}

View file

@ -4,13 +4,13 @@
package ui // import "miniflux.app/v2/internal/ui"
import (
"log/slog"
"net/http"
"miniflux.app/v2/internal/http/request"
"miniflux.app/v2/internal/http/response/html"
"miniflux.app/v2/internal/http/route"
"miniflux.app/v2/internal/locale"
"miniflux.app/v2/internal/logger"
"miniflux.app/v2/internal/ui/session"
)
@ -18,14 +18,17 @@ func (h *handler) oauth2Unlink(w http.ResponseWriter, r *http.Request) {
printer := locale.NewPrinter(request.UserLanguage(r))
provider := request.RouteStringParam(r, "provider")
if provider == "" {
logger.Info("[OAuth2] Invalid or missing provider")
slog.Warn("Invalid or missing OAuth2 provider")
html.Redirect(w, r, route.Path(h.router, "login"))
return
}
authProvider, err := getOAuth2Manager(r.Context()).FindProvider(provider)
if err != nil {
logger.Error("[OAuth2] %v", err)
slog.Error("Unable to initialize OAuth2 provider",
slog.String("provider", provider),
slog.Any("error", err),
)
html.Redirect(w, r, route.Path(h.router, "settings"))
return
}

View file

@ -4,6 +4,7 @@
package ui // import "miniflux.app/v2/internal/ui"
import (
"log/slog"
"net/http"
"miniflux.app/v2/internal/config"
@ -11,14 +12,14 @@ import (
"miniflux.app/v2/internal/http/request"
"miniflux.app/v2/internal/http/response/html"
"miniflux.app/v2/internal/http/route"
"miniflux.app/v2/internal/logger"
"miniflux.app/v2/internal/reader/opml"
"miniflux.app/v2/internal/ui/session"
"miniflux.app/v2/internal/ui/view"
)
func (h *handler) uploadOPML(w http.ResponseWriter, r *http.Request) {
user, err := h.store.UserByID(request.UserID(r))
loggedUserID := request.UserID(r)
user, err := h.store.UserByID(loggedUserID)
if err != nil {
html.ServerError(w, r, err)
return
@ -26,17 +27,20 @@ func (h *handler) uploadOPML(w http.ResponseWriter, r *http.Request) {
file, fileHeader, err := r.FormFile("file")
if err != nil {
logger.Error("[UI:UploadOPML] %v", err)
slog.Error("OPML file upload error",
slog.Int64("user_id", loggedUserID),
slog.Any("error", err),
)
html.Redirect(w, r, route.Path(h.router, "import"))
return
}
defer file.Close()
logger.Debug(
"[UI:UploadOPML] User #%d uploaded this file: %s (%d bytes)",
user.ID,
fileHeader.Filename,
fileHeader.Size,
slog.Info("OPML file uploaded",
slog.Int64("user_id", loggedUserID),
slog.String("file_name", fileHeader.Filename),
slog.Int64("file_size", fileHeader.Size),
)
sess := session.New(h.store, request.SessionID(r))
@ -62,7 +66,8 @@ func (h *handler) uploadOPML(w http.ResponseWriter, r *http.Request) {
}
func (h *handler) fetchOPML(w http.ResponseWriter, r *http.Request) {
user, err := h.store.UserByID(request.UserID(r))
loggedUserID := request.UserID(r)
user, err := h.store.UserByID(loggedUserID)
if err != nil {
html.ServerError(w, r, err)
return
@ -74,10 +79,9 @@ func (h *handler) fetchOPML(w http.ResponseWriter, r *http.Request) {
return
}
logger.Debug(
"[UI:FetchOPML] User #%d fetching this URL: %s",
user.ID,
url,
slog.Info("Fetching OPML file remotely",
slog.Int64("user_id", loggedUserID),
slog.String("opml_file_url", url),
)
sess := session.New(h.store, request.SessionID(r))

View file

@ -8,6 +8,7 @@ import (
"crypto/sha256"
"encoding/base64"
"errors"
"log/slog"
"net/http"
"time"
@ -16,7 +17,6 @@ import (
"miniflux.app/v2/internal/http/request"
"miniflux.app/v2/internal/http/response"
"miniflux.app/v2/internal/http/response/html"
"miniflux.app/v2/internal/logger"
)
func (h *handler) mediaProxy(w http.ResponseWriter, r *http.Request) {
@ -29,19 +29,19 @@ func (h *handler) mediaProxy(w http.ResponseWriter, r *http.Request) {
encodedDigest := request.RouteStringParam(r, "encodedDigest")
encodedURL := request.RouteStringParam(r, "encodedURL")
if encodedURL == "" {
html.BadRequest(w, r, errors.New("No URL provided"))
html.BadRequest(w, r, errors.New("no URL provided"))
return
}
decodedDigest, err := base64.URLEncoding.DecodeString(encodedDigest)
if err != nil {
html.BadRequest(w, r, errors.New("Unable to decode this Digest"))
html.BadRequest(w, r, errors.New("unable to decode this digest"))
return
}
decodedURL, err := base64.URLEncoding.DecodeString(encodedURL)
if err != nil {
html.BadRequest(w, r, errors.New("Unable to decode this URL"))
html.BadRequest(w, r, errors.New("unable to decode this URL"))
return
}
@ -55,7 +55,9 @@ func (h *handler) mediaProxy(w http.ResponseWriter, r *http.Request) {
}
mediaURL := string(decodedURL)
logger.Debug(`[Proxy] Fetching %q`, mediaURL)
slog.Debug("MediaProxy: Fetching remote resource",
slog.String("media_url", mediaURL),
)
req, err := http.NewRequest("GET", mediaURL, nil)
if err != nil {
@ -82,19 +84,28 @@ func (h *handler) mediaProxy(w http.ResponseWriter, r *http.Request) {
resp, err := clt.Do(req)
if err != nil {
logger.Error(`[Proxy] Unable to initialize HTTP client: %v`, err)
slog.Error("MediaProxy: Unable to initialize HTTP client",
slog.String("media_url", mediaURL),
slog.Any("error", err),
)
http.Error(w, http.StatusText(http.StatusInternalServerError), http.StatusInternalServerError)
return
}
defer resp.Body.Close()
if resp.StatusCode == http.StatusRequestedRangeNotSatisfiable {
logger.Error(`[Proxy] Status Code is %d for URL %q`, resp.StatusCode, mediaURL)
slog.Warn("MediaProxy: "+http.StatusText(http.StatusRequestedRangeNotSatisfiable),
slog.String("media_url", mediaURL),
slog.Int("status_code", resp.StatusCode),
)
html.RequestedRangeNotSatisfiable(w, r, resp.Header.Get("Content-Range"))
return
}
if resp.StatusCode != http.StatusOK && resp.StatusCode != http.StatusPartialContent {
logger.Error(`[Proxy] Status Code is %d for URL %q`, resp.StatusCode, mediaURL)
slog.Warn("MediaProxy: Unexpected response status code",
slog.String("media_url", mediaURL),
slog.Int("status_code", resp.StatusCode),
)
html.NotFound(w, r)
return
}

View file

@ -9,14 +9,14 @@ import (
"miniflux.app/v2/internal/http/request"
"miniflux.app/v2/internal/http/response/html"
"miniflux.app/v2/internal/http/route"
"miniflux.app/v2/internal/logger"
)
func (h *handler) removeSession(w http.ResponseWriter, r *http.Request) {
sessionID := request.RouteInt64Param(r, "sessionID")
err := h.store.RemoveUserSessionByID(request.UserID(r), sessionID)
if err != nil {
logger.Error("[UI:RemoveSession] %v", err)
html.ServerError(w, r, err)
return
}
html.Redirect(w, r, route.Path(h.router, "sessions"))

View file

@ -10,7 +10,6 @@ import (
"miniflux.app/v2/internal/http/response/html"
"miniflux.app/v2/internal/http/route"
"miniflux.app/v2/internal/locale"
"miniflux.app/v2/internal/logger"
"miniflux.app/v2/internal/model"
"miniflux.app/v2/internal/ui/form"
"miniflux.app/v2/internal/ui/session"
@ -74,9 +73,7 @@ func (h *handler) updateSettings(w http.ResponseWriter, r *http.Request) {
err = h.store.UpdateUser(settingsForm.Merge(loggedUser))
if err != nil {
logger.Error("[UI:UpdateSettings] %v", err)
view.Set("errorMessage", "error.unable_to_update_user")
html.OK(w, r, view.Render("settings"))
html.ServerError(w, r, err)
return
}

View file

@ -10,7 +10,6 @@ import (
"miniflux.app/v2/internal/http/request"
"miniflux.app/v2/internal/http/response/html"
"miniflux.app/v2/internal/http/route"
"miniflux.app/v2/internal/logger"
"miniflux.app/v2/internal/model"
feedHandler "miniflux.app/v2/internal/reader/handler"
"miniflux.app/v2/internal/reader/subscription"
@ -61,15 +60,12 @@ func (h *handler) submitSubscription(w http.ResponseWriter, r *http.Request) {
subscriptionForm.AllowSelfSignedCertificates,
)
if findErr != nil {
logger.Error("[UI:SubmitSubscription] %q -> %s", subscriptionForm.URL, findErr)
v.Set("form", subscriptionForm)
v.Set("errorMessage", findErr)
html.OK(w, r, v.Render("add_subscription"))
return
}
logger.Debug("[UI:SubmitSubscription] %s", subscriptions)
n := len(subscriptions)
switch {
case n == 0:

View file

@ -6,7 +6,6 @@ package ui // import "miniflux.app/v2/internal/ui"
import (
"net/http"
"miniflux.app/v2/internal/logger"
"miniflux.app/v2/internal/storage"
"miniflux.app/v2/internal/template"
"miniflux.app/v2/internal/worker"
@ -20,7 +19,7 @@ func Serve(router *mux.Router, store *storage.Storage, pool *worker.Pool) {
templateEngine := template.NewEngine(router)
if err := templateEngine.ParseTemplates(); err != nil {
logger.Fatal(`Unable to parse templates: %v`, err)
panic(err)
}
handler := &handler{router, store, templateEngine, pool}

View file

@ -37,7 +37,7 @@ func (h *handler) removeUser(w http.ResponseWriter, r *http.Request) {
}
if selectedUser.ID == loggedUser.ID {
html.BadRequest(w, r, errors.New("You cannot remove yourself"))
html.BadRequest(w, r, errors.New("you cannot remove yourself"))
return
}

View file

@ -9,7 +9,6 @@ import (
"miniflux.app/v2/internal/http/request"
"miniflux.app/v2/internal/http/response/html"
"miniflux.app/v2/internal/http/route"
"miniflux.app/v2/internal/logger"
"miniflux.app/v2/internal/model"
"miniflux.app/v2/internal/ui/form"
"miniflux.app/v2/internal/ui/session"
@ -64,9 +63,7 @@ func (h *handler) saveUser(w http.ResponseWriter, r *http.Request) {
}
if _, err := h.store.CreateUser(userCreationRequest); err != nil {
logger.Error("[UI:SaveUser] %v", err)
view.Set("errorMessage", "error.unable_to_create_user")
html.OK(w, r, view.Render("create_user"))
html.ServerError(w, r, err)
return
}

View file

@ -9,7 +9,6 @@ import (
"miniflux.app/v2/internal/http/request"
"miniflux.app/v2/internal/http/response/html"
"miniflux.app/v2/internal/http/route"
"miniflux.app/v2/internal/logger"
"miniflux.app/v2/internal/ui/form"
"miniflux.app/v2/internal/ui/session"
"miniflux.app/v2/internal/ui/view"
@ -64,9 +63,7 @@ func (h *handler) updateUser(w http.ResponseWriter, r *http.Request) {
userForm.Merge(selectedUser)
if err := h.store.UpdateUser(selectedUser); err != nil {
logger.Error("[UI:UpdateUser] %v", err)
view.Set("errorMessage", "error.unable_to_update_user")
html.OK(w, r, view.Render("edit_user"))
html.ServerError(w, r, err)
return
}