Haskell的Persistent sometmes返回500内部服务器错误

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Haskell的Persistent sometmes返回500内部服务器错误相关的知识,希望对你有一定的参考价值。

以下代码在localhost:3000上启动Web服务器。

#!/usr/bin/env stack
-- stack script --resolver=lts-12.16

{-# LANGUAGE EmptyDataDecls             #-}
{-# LANGUAGE FlexibleContexts           #-}
{-# LANGUAGE GADTs                      #-}
{-# LANGUAGE GeneralizedNewtypeDeriving #-}
{-# LANGUAGE MultiParamTypeClasses      #-}
{-# LANGUAGE OverloadedStrings          #-}
{-# LANGUAGE QuasiQuotes                #-}
{-# LANGUAGE TemplateHaskell            #-}
{-# LANGUAGE TypeFamilies               #-}
{-# LANGUAGE ViewPatterns               #-}
import Yesod
import Database.Persist.Sqlite
import Control.Monad.Trans.Resource (runResourceT)
import Control.Monad.Logger (runStderrLoggingT)
import Data.Text

-- Define our entities as usual
share [mkPersist sqlSettings, mkMigrate "migrateAll"] [persistLowerCase|
Book
    title Text
    author Text
    publisher Text
    date Text
    price Int
    deriving Show
|]

-- We keep our connection pool in the foundation. At program initialization, we
-- create our initial pool, and each time we need to perform an action we check
-- out a single connection from the pool.
data SQLi = SQLi ConnectionPool

-- We'll create a single route, to access a person. It's a very common
-- occurrence to use an Id type in routes.
mkYesod "SQLi" [parseRoutes|
/ HomeR GET
/book/#BookId BookR GET
|]

-- Nothing special here
instance Yesod SQLi

-- Now we need to define a YesodPersist instance, which will keep track of
-- which backend we're using and how to run an action.
instance YesodPersist SQLi where
    type YesodPersistBackend SQLi = SqlBackend

    runDB action = do
        SQLi pool <- getYesod
        runSqlPool action pool

searchFrame :: [Entity Book] -> Widget
searchFrame books = 
  [whamlet|
    <table border=1>
      <tr>
        <th>ID
        <th>Title
        <th>Author
        <th>Publisher
        <th>Publication date
        <th>Price
      $forall Entity bookid book <- books
        <tr>
          <td>
            <a href=@{BookR bookid}>#{show bookid}
          <td>
            #{bookTitle book}
          <td>
            #{bookAuthor book}
          <td>
            #{bookPublisher book}
          <td>
            #{bookDate book}
          <td>
            #{bookPrice book}
  |]

-- List all people in the database
getHomeR :: Handler html
getHomeR = do
  mBookAuthor <- lookupGetParam "author"
  maybe (do
    books <- runDB $ selectList [] [Asc BookId]
    defaultLayout $ searchFrame books)
    (¥author -> do
       books <- runDB $ selectList [BookAuthor ==. author] [Asc BookId]

       defaultLayout $ [whamlet|
         <h1>Search books manually
         ^{searchFrame books}
       |]) $ mBookAuthor

-- We'll just return the show value of a person, or a 404 if the Person doesn't
-- exist.
getBookR :: BookId -> Handler String
getBookR bookId = do
    book <- runDB $ get404 bookId
    return $ show book

openConnectionCount :: Int
openConnectionCount = 10

main :: IO ()
main = runStderrLoggingT $ withSqlitePool ":memory:" openConnectionCount $ ¥pool -> liftIO $ do
    runResourceT $ flip runSqlPool pool $ do
        runMigration migrateAll
        insert $ Book "A Midsummer Night's Dream" "Shakespeare" "A bookstore"   "1979/01" 600
        insert $ Book "Hamlet"    "Shakespeare" "B bookstore"   "1997/04" 1260
        insert $ Book "Macbeth"   "Shakespeare" "C bookstore"   "2001/05" 1530
        insert $ Book "King Lear"     "Shakespeare" "D bookstore" "2004/07" 1890
    warp 3000 $ SQLi pool

然后,加载http://localhost:3000/?author=' AND EXTRACTVALUE(0, (SELECT CONCAT('$', id, ':', pwd) FROM users LIMIT 0, 1)) #有时会导致500内部服务器错误,即使我们加载正常页面,如http://localhost:3000/,也会发出此错误消息

实际上,这可能是SQL注入的攻击媒介。所以,我对天气感到困惑,这是由攻击或其他原因造成的。有人可以解释这种行为吗?

答案

哎呀。我错过了withSqlitePool should not be used with :memory:。通过给它一个文件名,问题得到解决。

以上是关于Haskell的Persistent sometmes返回500内部服务器错误的主要内容,如果未能解决你的问题,请参考以下文章

使用 Persistent Haskell 来自现有数据库的外键

“类型变量不明确”在 Haskell Yesod 中使用 Persistent

Haskell Persistent 上的 CRUD 模式

Haskell Persistent:可以按包含指定值的字段选择所有行

Haskell Persistent Library - 如何从我的数据库中获取数据到我的前端?

使用 Persistent 输入与数据库的关系