вторник, 5 февраля 2019 г.

Веб-приложение на Go: валидация

Как вы могли заметить, у нашего приложения есть серьезный недостаток безопасности: пользователь может предоставить произвольный путь для чтения/записи на сервере. Для снижения вероятности некорректного действия мы можем написать функцию для проверки заголовка с помощью регулярного выражения.

Сначала добавьте "regexp" в список import. Затем мы можем создать глобальную переменную для хранения нашей проверочного выражения:

var validPath = regexp.MustCompile(
                   "^/(edit|save|view)/([a-zA-Z0-9]+)$")

Функция regexp.MustCompile проанализирует и скомпилирует регулярное выражение и вернет regexp.Regexp. MustCompile отличается от Compile тем, что он вызывает panic, если компиляция выражения не удается, а Compile возвращает error в качестве второго параметра.

Теперь давайте напишем функцию, которая использует validPath выражение для проверки пути и извлечения заголовка страницы:

func getTitle(w http.ResponseWriter, 
              r *http.Request) (string, error) {
    m := validPath.FindStringSubmatch(r.URL.Path)
    if m == nil {
        http.NotFound(w, r)
        return "", errors.New("Invalid Page Title")
    }
    return m[2], nil // title это второе подвыражение.
}

Если заголовок действителен, он будет возвращен вместе с ошибкой со значением nil. Если заголовок недействителен, функция напишет ошибку «404 Not Found» для HTTP-соединения и вернет ошибку обработчику. Чтобы создать новую ошибку, мы должны импортировать errors пакет.

Давайте поместим вызов getTitle в каждом из обработчиков:

func viewHandler(w http.ResponseWriter, r *http.Request) {
    title, err := getTitle(w, r)
    if err != nil {
        return
    }
    p, err := loadPage(title)
    if err != nil {
        http.Redirect(w, r, 
             "/edit/"+title, http.StatusFound)
        return
    }
    renderTemplate(w, "view", p)
}

func editHandler(w http.ResponseWriter, r *http.Request) {
    title, err := getTitle(w, r)
    if err != nil {
        return
    }
    p, err := loadPage(title)
    if err != nil {
        p = &Page{Title: title}
    }
    renderTemplate(w, "edit", p)
}

func saveHandler(w http.ResponseWriter, r *http.Request) {
    title, err := getTitle(w, r)
    if err != nil {
        return
    }
    body := r.FormValue("body")
    p := &Page{Title: title, Body: []byte(body)}
    err = p.save()
    if err != nil {
        http.Error(w, err.Error(), 
                   http.StatusInternalServerError)
        return
    }
    http.Redirect(w, r, 
         "/view/"+title, http.StatusFound)
}


Читайте также:


Комментариев нет:

Отправить комментарий