Как определить, достиг ли я предела размера через Go's MaxBytesReader
Я новичок в Go и использую Mux для приема данных HTTP POST. Я хотел бы использовать MaxBytesReader, чтобы клиент не перегружал мой сервер. Согласно кодексу, есть requestBodyLimit
логическое значение, которое указывает, был ли достигнут этот предел.
Мой вопрос: при использовании MaxBytesReader, как я могу определить, действительно ли я достиг максимума при обработке запроса?
Вот мой код:
package main
import (
"fmt"
"log"
"html/template"
"net/http"
"github.com/gorilla/mux"
)
func main() {
r := mux.NewRouter()
r.HandleFunc("/handle", maxBytes(PostHandler)).Methods("POST")
http.ListenAndServe(":8080", r)
}
// Middleware to enforce the maximum post body size
func maxBytes(f http.HandlerFunc) http.HandlerFunc {
return func(w http.ResponseWriter, r *http.Request) {
// As an example, limit post body to 10 bytes
r.Body = http.MaxBytesReader(w, r.Body, 10)
f(w, r)
}
}
func PostHandler(w http.ResponseWriter, r *http.Request) {
// How do I know if the form data has been truncated?
book := r.FormValue("email")
fmt.Fprintf(w, "You've requested the book: %s\n", book)
}
Как я могу:
Определите, что я достиг максимального предела POST (или имею доступ к
requestBodyLimit
Может ли мой код быть разветвленным при этом условии?
3 ответа
Вызовите ParseForm в начале обработчика. Если этот метод возвращает ошибку, то предел размера был нарушен или тело запроса каким-то образом недопустимо. Напишите статус ошибки и вернитесь из обработчика.
Нет простого способа определить, является ли ошибка результатом нарушения ограничения размера или какой-либо другой ошибки.
func PostHandler(w http.ResponseWriter, r *http.Request) {
if err := r.ParseForm(); err != nil {
http.Error(w, "Bad Request", http.StatusBadRequest)
return
}
book := r.FormValue("email")
fmt.Fprintf(w, "You've requested the book: %s\n", book)
}
В зависимости от ваших потребностей, может быть лучше поместить чек в промежуточное ПО:
func maxBytes(f http.HandlerFunc) http.HandlerFunc {
return func(w http.ResponseWriter, r *http.Request) {
r.Body = http.MaxBytesReader(w, r.Body, 10)
if err := r.ParseForm(); err != nil {
http.Error(w, "Bad Request", http.StatusBadRequest)
return
}
f(w, r)
}
}
Можно проверить, является ли возвращенная ошибкаhttp.MaxBytesError
так:
r.Body = http.MaxBytesReader(w, r.Body, 10)
if err := r.ParseForm(); err != nil {
if _, ok := err.(*http.MaxBytesError); ok {
// handle http.StatusRequestEntityTooLarge error
}
// handle http.StatusBadRequest error
}
errors.Is()
иerrors.As()
в этом случае работать не будет.
Вы можете определить, был ли предел превышен, проверяя, превышает ли длина прочитанных данных (или равна) MaxBytesSize:
maxBytesSize := 10
r.Body = http.MaxBytesReader(w, r.Body, maxBytesSize)
// check if request body is not too large
data, err := ioutil.ReadAll(r.Body)
if err != nil {
if len(data) >= maxBytesSize {
//exceeded
}
// some other error
}