Haskell Monads msum в HappStack

От

http://happstack.com/docs/crashcourse/HappstackState.html

Когда я запускаю сервер, счетчик просмотров увеличивается на

  • 1, когда я заглядываю
  • 2 когда я не заглядываю

Соответствующий код:

handlers :: ServerPart Response
handlers = 
    msum [ dir "peek" $ do c <- query PeekCounter
                       ok $ toResponse $ "peeked at the count and saw: " ++ show (unCounter c)
         , do c <- update (AddCounter 1)
           ok $ toResponse $ "New count is: " ++ show (unCounter c)
         ]

Тем не менее, когда я изменяю его

handlers :: ServerPart Response
handlers = 
    msum [ dir "peek" $ do c <- query PeekCounter
                           ok $ toResponse $ "peeked at the count and saw: " ++ show (unCounter c)
         , do ok $ toResponse $ "Stop here."
         , do c <- update (AddCounter 1)
              ok $ toResponse $ "New count is: " ++ show (unCounter c)
         ]

Счетчик увеличивается на

  • 0 когда я заглядываю
  • 1, когда я не заглядываю

Это предполагаемое поведение? Такое ощущение, что вторая монада в msum "протекает", даже когда я заглядываю.

1 ответ

Решение

Счет увеличивается на дополнительное время, потому что браузер запрашивает /favicon.ico каждый раз, когда загружает страницу. Поскольку последний маршрут является универсальным, запрос к /favicon.ico вызывает приращение.

Самое простое решение - добавить nullDir, чтобы он делал приращение только для /,

handlers :: ServerPart Response
handlers = 
msum [ dir "peek" $ do c <- query PeekCounter
                   ok $ toResponse $ "peeked at the count and saw: " ++ show (unCounter c)
     , do nullDir
          c <- update (AddCounter 1)
          ok $ toResponse $ "New count is: " ++ show (unCounter c)
     ]

Я обновил учебник с этим изменением, чтобы избежать дальнейшей путаницы. Чтобы подтвердить, что это действительно запрос /favicon.ico, который запутывает вещи, мы могли бы явно обработать запрос для значка:

handlers :: ServerPart Response
handlers = 
    msum [ dir "peek" $ do c <- query PeekCounter
                           ok $ toResponse $ "peeked at the count and saw: " ++ show (unCounter c)
         , dir "favicon.ico" $ notFound (toResponse "sorry, no favicon.ico")
         , do c <- update (AddCounter 1)
              ok $ toResponse $ "New count is: " ++ show (unCounter c)
         ]

Теперь мы видим ожидаемое поведение.

Таким образом, с Happstack все в порядке. Браузер делал 1 или 2 запроса к URL, которые не были /peek, и поэтому счетчик увеличивался один или два раза. Это было предполагаемое поведение приложения. Но, поскольку люди не ожидают запроса /favicon.ico, это также приводит к удивительному поведению. Так что теперь приложение было изменено, чтобы иметь только два действительных URL, /peek и /. Все остальное приводит к 404.

Спасибо за отчет!

Другие вопросы по тегам