本章为 scotty 系列教程的第二篇,读者可先阅读 第一篇 学习如何使用 stack
构建一个 Haskell 的项目。
本章的目标是使用 scotty 构建一个 echo server,用 curl
测试如下:
$ curl http://127.0.0.1:3000/?echo=abc
abc
$ curl http://127.0.0.1:3000/ -d echo=cdf
cdf
我们继续使用 上篇 所建立的 helloworld
为基础建立 echo server
。
修改 src/Lib.hs
如下:
{-# LANGUAGE OverloadedStrings #-}
module Lib
( someFunc
) where
import Web.Scotty
someFunc :: IO ()
someFunc = scotty 3000 $ do
get "/" $ do
echo <- param "echo"
text echo
post "/" $ do
echo <- param "echo"
text echo
这里用了 get
和 post
的方法,然后通过 param
获取 echo
的信息然后输出。
编译一下:
$ stack build --system-ghc
Warning: File listed in helloworld.cabal file does not exist: README.md
helloworld-0.1.0.0: build (lib + exe)
Preprocessing library helloworld-0.1.0.0...
[1 of 1] Compiling Lib ( src/Lib.hs, .stack-work/dist/x86_64-osx/Cabal-1.24.2.0/build/Lib.o )
/Users/lmj/repo/dispatch/helloworld/src/Lib.hs:7:1: error:
Failed to load interface for ‘Web.Scotty’
Use -v to see a list of the files searched for.
Warning: File listed in helloworld.cabal file does not exist: README.md
-- While building package helloworld-0.1.0.0 using:
/Users/lmj/.stack/setup-exe-cache/x86_64-osx/Cabal-simple_mPHDZzAJ_1.24.2.0_ghc-8.0.2 --builddir=.stack-work/dist/x86_64-osx/Cabal-1.24.2.0 build lib:helloworld exe:helloworld-exe --ghc-options " -ddump-hi -ddump-to-file"
Process exited with code: ExitFailure 1
编译器抱怨没有找到 Web.Scotty
,这是缺少依赖 scotty
导致的。
打开 helloworld.cabal
, 将 scotty
添加到 library
的 build-depends
, 如下:
library
hs-source-dirs: src
exposed-modules: Lib
build-depends: base >= 4.7 && < 5
, scotty
default-language: Haskell2010
重新编译一下:
$ stack build --system-ghc
Warning: File listed in helloworld.cabal file does not exist: README.md
fail-4.9.0.0: using precompiled package
nats-1.1.1: using precompiled package
regex-base-0.93.2: using precompiled package
regex-posix-0.95.2: using precompiled package
regex-compat-0.95.1: using precompiled package
scotty-0.11.0: using precompiled package
helloworld-0.1.0.0: configure (lib + exe)
Configuring helloworld-0.1.0.0...
helloworld-0.1.0.0: build (lib + exe)
Preprocessing library helloworld-0.1.0.0...
[1 of 1] Compiling Lib ( src/Lib.hs, .stack-work/dist/x86_64-osx/Cabal-1.24.2.0/build/Lib.o )
Preprocessing executable 'helloworld-exe' for helloworld-0.1.0.0...
[1 of 1] Compiling Main ( app/Main.hs, .stack-work/dist/x86_64-osx/Cabal-1.24.2.0/build/helloworld-exe/helloworld-exe-tmp/Main.o ) [Lib changed]
Linking .stack-work/dist/x86_64-osx/Cabal-1.24.2.0/build/helloworld-exe/helloworld-exe ...
Warning: File listed in helloworld.cabal file does not exist: README.md
helloworld-0.1.0.0: copy/register
Installing library in
/Users/lmj/repo/dispatch/helloworld/.stack-work/install/x86_64-osx/lts-8.5/8.0.2/lib/x86_64-osx-ghc-8.0.2/helloworld-0.1.0.0-1f3dj2GjzoiFgLQm1bUvr4
Installing executable(s) in
/Users/lmj/repo/dispatch/helloworld/.stack-work/install/x86_64-osx/lts-8.5/8.0.2/bin
Registering helloworld-0.1.0.0...
Completed 7 action(s).
接下来运行测试一下:
$ stack exec --system-ghc helloworld-exe
Setting phasers to stun... (port 3000) (ctrl-c to quit)
打开另外一个终端测试:
$ curl http://127.0.0.1:3000/?echo=abc
abc
$ curl http://127.0.0.1:3000/ -d echo=cdf
cdf
到这里整个 echo server
基本完成。
继续看 src/Lib.hs
的代码,get
和 post
的处理代码是一样的,我们是否写成一个函数呢? 答案是可以的。
阅读文档发现 get
和 post
定义如下:
get :: RoutePattern -> ActionM () -> ScottyM ()
post :: RoutePattern -> ActionM () -> ScottyM ()
所以可以定义一个 echoHandler
如下:
echoHandler :: ActionM ()
echoHandler = do
echo <- param "echo"
text echo
修改 src/Lib.hs 如下:
{-# LANGUAGE OverloadedStrings #-}
module Lib
( someFunc
) where
import Web.Scotty
someFunc :: IO ()
someFunc = scotty 3000 $ do
get "/" echoHandler
post "/" echoHandler
echoHandler :: ActionM ()
echoHandler = do
echo <- param "echo"
text echo
编译测试如上,由读者自行完成。