2015-02-02 3 views
13

Я искал вокруг и, насколько я могу судить, запросы формы POST уже ограничены 10 МБ (http://golang.org/src/net/http/request.go#L721).Целесообразно ли (далее) ограничить размер форм при использовании golang?

Если бы я хотел уменьшить это в моем методе ServeHTTP, я не уверен, как правильно это сделать. Я бы попробовал что-то вроде этого:

r.Body = http.MaxBytesReader(w, r.Body, MaxFileSize) 
err := r.ParseForm() 
if err != nil { 
    //redirect to some error page 
    return 
} 

Но вернулось бы при ошибке закрыть соединение? Как я мог бы запретить читать все? Я нашел это: https://stackoverflow.com/a/26393261/2202497, но что, если длина контента не установлена ​​и в середине чтения я понимаю, что файл слишком большой.

Я использую это как меру безопасности, чтобы не допустить, чтобы кто-то извратил ресурсы моего сервера.

+1

Способ, которым вы предлагаете, выглядит хорошо. Не прочитает все, или ограничение на 10 МБ stdlib тоже будет неэффективным. Огромный POST без Content-Length не будет генерироваться большинством браузеров/пользовательских агентов, и я думаю, что зависание запроса является разумным ответом, если это произойдет. – twotwotwo

+0

Я думаю, что это преждевременная оптимизация. Пока вы не заметите, что вы получаете необычно высокий трафик, вы должны просто оставить его как можно проще.Уверен, у вас много других приоритетных задач, которые вам нужно выполнить. : P – Populus

+0

@Populus Я понял. На данный момент я не слишком обеспокоен этим. Однако я постараюсь ответить на этот вопрос. – John

ответ

22

Правильный способ ограничить размер тела запроса должен сделать, как Вы предложили:

r.Body = http.MaxBytesReader(w, r.Body, MaxFileSize) 
err := r.ParseForm() 
if err != nil { 
// redirect or set error status code. 
return 
} 

MaxBytesReader устанавливает flag on the response при достижении предела. Когда этот флаг установлен, сервер не считывает оставшуюся часть тела запроса, и сервер закрывает соединение при возврате из обработчика.

Если вас беспокоят злонамеренные клиенты, вы также должны установить Server.ReadTimeout, Server.WriteTimeout и, возможно, Server.MaxHeaderBytes.

Если вы хотите установить предел тела запроса для всех обработчиков, затем оберните корневой обработчик с обработчиком, который устанавливает предел до передачи в корневом обработчик:

type maxBytesHandler struct { 
    h http.Handler 
    n int64 
} 

func (h *maxBytesHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) { 
    r.Body = http.MaxBytesReader(w, r.Body, h.n) 
    h.h.ServeHTTP(w, r) 
} 

Wrap корень обработчик при вызове ListenAndServe:

log.Fatal(http.ListenAndServe(":8080", &maxBytesHandler{h:mux, n:4096)) 

или при настройке сервера:

s := http.Server{ 
    Addr: ":8080", 
    Handler: &maxBytesReader{h:mux, n:4096}, 
} 
log.Fatal(s.ListenAndServe()) 

Нет необходимости в патче, как предлагается в другом ответе. MaxBytesReader является официальным способом ограничения размера тела запроса.

0

Редактировать: Как упоминалось выше, MaxByteReader поддерживается. Интересно, что вместо этого используется читатель по умолчанию, limitreader после утверждения типа для максимального байтового считывателя.

Отправить патч к исходному коду Go и настроить его! В конце концов, вы работаете с проектом с открытым исходным кодом. Добавление сеттера в http.Request и некоторые модульные тесты для него - это, вероятно, всего 20 минут работы. Имея твердое значение здесь немного неудобно, верните его и исправьте :).

Вы можете, конечно, реализовать свой собственный метод ParseForm(r *http.Request), если вам действительно нужно переопределить это. Go - это по существу BSD, поэтому вы можете скопировать вставку библиотеки ParseForm и изменить предел, но это немного уродливое нет?

Смежные вопросы