1
0
Fork 0
mirror of https://github.com/miniflux/v2.git synced 2025-06-27 16:36:00 +00:00

Use vanilla HTTP handlers (refactoring)

This commit is contained in:
Frédéric Guillot 2018-04-29 16:35:04 -07:00
parent 1eba1730d1
commit f49b42f70f
121 changed files with 4339 additions and 3369 deletions

View file

@ -6,9 +6,12 @@ package middleware
import (
"context"
"errors"
"net/http"
"github.com/miniflux/miniflux/http/cookie"
"github.com/miniflux/miniflux/http/request"
"github.com/miniflux/miniflux/http/response/html"
"github.com/miniflux/miniflux/logger"
"github.com/miniflux/miniflux/model"
)
@ -17,20 +20,21 @@ import (
func (m *Middleware) AppSession(next http.Handler) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
var err error
session := m.getSessionValueFromCookie(r)
session := m.getAppSessionValueFromCookie(r)
if session == nil {
logger.Debug("[Middleware:Session] Session not found")
logger.Debug("[Middleware:AppSession] Session not found")
session, err = m.store.CreateSession()
if err != nil {
logger.Error("[Middleware:Session] %v", err)
http.Error(w, http.StatusText(http.StatusInternalServerError), http.StatusInternalServerError)
logger.Error("[Middleware:AppSession] %v", err)
html.ServerError(w, err)
return
}
http.SetCookie(w, cookie.New(cookie.CookieSessionID, session.ID, m.cfg.IsHTTPS, m.cfg.BasePath()))
} else {
logger.Debug("[Middleware:Session] %s", session)
logger.Debug("[Middleware:AppSession] %s", session)
}
if r.Method == "POST" {
@ -38,9 +42,8 @@ func (m *Middleware) AppSession(next http.Handler) http.Handler {
headerValue := r.Header.Get("X-Csrf-Token")
if session.Data.CSRF != formValue && session.Data.CSRF != headerValue {
logger.Error(`[Middleware:Session] Invalid or missing CSRF token: Form="%s", Header="%s"`, formValue, headerValue)
w.WriteHeader(http.StatusBadRequest)
w.Write([]byte("Invalid or missing CSRF session!"))
logger.Error(`[Middleware:AppSession] Invalid or missing CSRF token: Form="%s", Header="%s"`, formValue, headerValue)
html.BadRequest(w, errors.New("invalid or missing CSRF"))
return
}
}
@ -56,15 +59,15 @@ func (m *Middleware) AppSession(next http.Handler) http.Handler {
})
}
func (m *Middleware) getSessionValueFromCookie(r *http.Request) *model.Session {
sessionCookie, err := r.Cookie(cookie.CookieSessionID)
if err == http.ErrNoCookie {
func (m *Middleware) getAppSessionValueFromCookie(r *http.Request) *model.Session {
cookieValue := request.Cookie(r, cookie.CookieSessionID)
if cookieValue == "" {
return nil
}
session, err := m.store.Session(sessionCookie.Value)
session, err := m.store.Session(cookieValue)
if err != nil {
logger.Error("[Middleware:Session] %v", err)
logger.Error("[Middleware:AppSession] %v", err)
return nil
}

View file

@ -8,6 +8,7 @@ import (
"context"
"net/http"
"github.com/miniflux/miniflux/http/response/json"
"github.com/miniflux/miniflux/logger"
)
@ -15,35 +16,30 @@ import (
func (m *Middleware) BasicAuth(next http.Handler) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
w.Header().Set("WWW-Authenticate", `Basic realm="Restricted"`)
errorResponse := `{"error_message": "Not Authorized"}`
username, password, authOK := r.BasicAuth()
if !authOK {
logger.Debug("[Middleware:BasicAuth] No authentication headers sent")
w.WriteHeader(http.StatusUnauthorized)
w.Write([]byte(errorResponse))
json.Unauthorized(w)
return
}
if err := m.store.CheckPassword(username, password); err != nil {
logger.Info("[Middleware:BasicAuth] Invalid username or password: %s", username)
w.WriteHeader(http.StatusUnauthorized)
w.Write([]byte(errorResponse))
json.Unauthorized(w)
return
}
user, err := m.store.UserByUsername(username)
if err != nil {
logger.Error("[Middleware:BasicAuth] %v", err)
w.WriteHeader(http.StatusInternalServerError)
w.Write([]byte(errorResponse))
json.ServerError(w, err)
return
}
if user == nil {
logger.Info("[Middleware:BasicAuth] User not found: %s", username)
w.WriteHeader(http.StatusUnauthorized)
w.Write([]byte(errorResponse))
json.Unauthorized(w)
return
}

View file

@ -0,0 +1,25 @@
// Copyright 2018 Frédéric Guillot. All rights reserved.
// Use of this source code is governed by the Apache 2.0
// license that can be found in the LICENSE file.
package middleware
import (
"net/http"
)
// CommonHeaders sends common HTTP headers.
func (m *Middleware) CommonHeaders(next http.Handler) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
w.Header().Set("X-XSS-Protection", "1; mode=block")
w.Header().Set("X-Content-Type-Options", "nosniff")
w.Header().Set("X-Frame-Options", "DENY")
w.Header().Set("Content-Security-Policy", "default-src 'self'; img-src *; media-src *; frame-src *; child-src *")
if m.cfg.IsHTTPS && m.cfg.HasHSTS() {
w.Header().Set("Strict-Transport-Security", "max-age=31536000")
}
next.ServeHTTP(w, r)
})
}

View file

@ -8,27 +8,25 @@ import (
"context"
"net/http"
"github.com/miniflux/miniflux/http/response/json"
"github.com/miniflux/miniflux/logger"
)
// FeverAuth handles Fever API authentication.
func (m *Middleware) FeverAuth(next http.Handler) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
logger.Debug("[Middleware:Fever]")
apiKey := r.FormValue("api_key")
user, err := m.store.UserByFeverToken(apiKey)
if err != nil {
logger.Error("[Fever] %v", err)
w.Header().Set("Content-Type", "application/json")
w.Write([]byte(`{"api_version": 3, "auth": 0}`))
logger.Error("[Middleware:Fever] %v", err)
json.OK(w, map[string]int{"api_version": 3, "auth": 0})
return
}
if user == nil {
logger.Info("[Middleware:Fever] Fever authentication failure")
w.Header().Set("Content-Type", "application/json")
w.Write([]byte(`{"api_version": 3, "auth": 0}`))
json.OK(w, map[string]int{"api_version": 3, "auth": 0})
return
}

View file

@ -8,6 +8,7 @@ import (
"net/http"
"github.com/miniflux/miniflux/logger"
"github.com/tomasen/realip"
)

View file

@ -9,6 +9,8 @@ import (
"net/http"
"github.com/miniflux/miniflux/http/cookie"
"github.com/miniflux/miniflux/http/request"
"github.com/miniflux/miniflux/http/response"
"github.com/miniflux/miniflux/http/route"
"github.com/miniflux/miniflux/logger"
"github.com/miniflux/miniflux/model"
@ -19,17 +21,18 @@ import (
// UserSession handles the user session middleware.
func (m *Middleware) UserSession(next http.Handler) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
session := m.getSessionFromCookie(r)
session := m.getUserSessionFromCookie(r)
if session == nil {
logger.Debug("[Middleware:UserSession] Session not found")
if m.isPublicRoute(r) {
next.ServeHTTP(w, r)
} else {
http.Redirect(w, r, route.Path(m.router, "login"), http.StatusFound)
response.Redirect(w, r, route.Path(m.router, "login"))
}
} else {
logger.Debug("[Middleware:UserSession] %s", session)
ctx := r.Context()
ctx = context.WithValue(ctx, UserIDContextKey, session.UserID)
ctx = context.WithValue(ctx, IsAuthenticatedContextKey, true)
@ -58,13 +61,13 @@ func (m *Middleware) isPublicRoute(r *http.Request) bool {
}
}
func (m *Middleware) getSessionFromCookie(r *http.Request) *model.UserSession {
sessionCookie, err := r.Cookie(cookie.CookieUserSessionID)
if err == http.ErrNoCookie {
func (m *Middleware) getUserSessionFromCookie(r *http.Request) *model.UserSession {
cookieValue := request.Cookie(r, cookie.CookieUserSessionID)
if cookieValue == "" {
return nil
}
session, err := m.store.UserSessionByToken(sessionCookie.Value)
session, err := m.store.UserSessionByToken(cookieValue)
if err != nil {
logger.Error("[Middleware:UserSession] %v", err)
return nil