아래 4개의 파일과 디렉토리에 주안점을 두고 본 튜토리얼을 진행한다. 현재 구성은 다음 이미지와 같다.
- config/routes
- Handler/
- templates/
- config/models
config/routes 는 URL → Code 로 매핑하는 설정을 하는 파일이다.
config/models 은 데이터베이스 테이블 같은 지속성 객체에 대한 설정을 다룬다.
templates/ HTML, js, 그리고 CSS 템플릿 파일을 포함한다.
Handler/ 디렉토리는 URL 을 통해 접근되는 코드를 포함한 파일이 들어있다.
Yesod framework의 보안성을 평가하기 위해 아래와 같이 간단한 echo 어플리케이션을 만든다.
/echo/[some text]로 접속했을 때 h1 블럭 안에 있는 "some text"를 반환하는 웹페이지를 만들어보자.
먼저 config/routes 파일에 /echo/#String EchoR GET 을 추가한다.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 | -- By default this file is used by `parseRoutesFile` in Foundation.hs -- Syntax for this file here: https://www.yesodweb.com/book/routing-and-handlers /static StaticR Static appStatic /auth AuthR Auth getAuth /favicon.ico FaviconR GET /robots.txt RobotsR GET / HomeR GET POST /comments CommentR POST /profile ProfileR GET /echo/#String EchoR GET | cs |
추가된 /echo/#String EchoR GET 는 다음의 3가지 요소 - URL pattern, handler name, HTTP method - 를 포함한다.
- Handler/Echo.hs 파일 생성
- 메인 Application.hs 파일에서 Handler.Echo 를 가져온다.
- 어플리케이션 빌딩을 위해 cabla 파일에 Handler.Echo 를 선언한다.
이제 localhost:3000/echo/foo 로 이동해보자. getEchoR 이 아직 구현되지 않았다는 메시지를 보게 될 것이다.
그러면 다음과 같은 src/Handler/Echo.hs 파일을 만들자.
1 2 3 4 5 6 | module Handler.Echo where import Import getEchoR :: String -> Handler Html getEchoR = error "Not yet implemented: getEchoR" | cs |
이 경우 아래와 같이 페이지가 호출된다.
너무 직관적이다. 다음과 같이 변경해보자. 너무 복잡할 것 없다. 간단히 말해서 String 타입의 theText 라는 하나의 인수를 가진 getEchoR 이라는 함수를 선언하는 것이다. 해당 함수가 호출되었을 때, Handler Html 을 반환한다.
1 2 3 4 5 6 | module Handler.Echo where import Import getEchoR :: String -> Handler Html getEchoR theText = defaultLayout [whamlet|<h1>#{theText}|] | cs |
src/Application.hs 에 import Handler.Echo 를 추가한다.
1 2 3 4 5 6 7 | -- Import all relevant handler modules here. -- Don't forget to add new modules to your cabal file! import Handler.Common import Handler.Home import Handler.Comment import Handler.Profile import Handler.Echo | cs |
cabal 파일 blackbriar.cabal 에 Handler.Echo 모듈을 추가한다.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 | exposed-modules: Application Foundation Handler.Comment Handler.Common Handler.Home Handler.Profile Handler.Echo Import Import.NoFoundation Model Settings Settings.StaticFiles default-language: Haskell2010 | cs |
src/Foundation.hs 에 localhost/echo 루트에 모든 사람이 접속할 수 있도록 isAuthorized EchoR _= return Authorized 를 추가한다.
1 2 3 4 5 6 7 8 9 10 | -- Routes not requiring authentication. isAuthorized (AuthR _) _ = return Authorized isAuthorized CommentR _ = return Authorized isAuthorized HomeR _ = return Authorized isAuthorized FaviconR _ = return Authorized isAuthorized RobotsR _ = return Authorized isAuthorized (StaticR _) _ = return Authorized isAuthorized ProfileR _ = isAuthenticated isAuthorized EchoR _ = return Authorized | cs |
스페이스가 아닌 탭이 사용된 경우 다음의 에러가 발생할 수 있으니 유의한다.
1 2 | yesod: blackbriar.cabal: 73: user error (Do not use tabs for indentation (use spaces instead) Tabs were used at (line,column): [(73,0)]) | cs |
rebuild 를 해보면 다음과 같은 오류가 발생한다.
1 2 3 4 5 6 7 | [ 5 of 12] Compiling Foundation ( src/Foundation.hs, .stack-work/dist/x86_64-linux/Cabal-1.24.2.0/build/Foundation.o ) [config/routes changed] /root/blackbriar/blackbriar/src/Foundation.hs:158:18: error: • The constructor ‘EchoR’ should have 1 argument, but has been given none • In the pattern: EchoR In an equation for ‘isAuthorized’: isAuthorized EchoR _ = return Authorized In the instance declaration for ‘Yesod App’ | cs |
앞서 src/Foundation.hs 에 추가했던 isAuthorized EchoR _ = return Authorized 를 isAuthorized (EchoR _) _ = return Authorized 로 고쳐서 실행해보자.
1 2 3 4 5 6 7 8 9 10 | -- Routes not requiring authentication. isAuthorized (AuthR _) _ = return Authorized isAuthorized CommentR _ = return Authorized isAuthorized HomeR _ = return Authorized isAuthorized FaviconR _ = return Authorized isAuthorized RobotsR _ = return Authorized isAuthorized (StaticR _) _ = return Authorized isAuthorized (EchoR _) _ = return Authorized isAuthorized ProfileR _ = isAuthenticated | cs |
또 탭이 사용된 모양이다. 스페이스로 고친 후 다시 실행한다.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 | blackbriar-0.0.0: build (lib) Preprocessing library blackbriar-0.0.0... [ 5 of 12] Compiling Foundation ( src/Foundation.hs, .stack-work/dist/x86_64-linux/Cabal-1.24.2.0/build/Foundation.o ) /root/blackbriar/blackbriar/src/Foundation.hs:159:1: warning: [-Wtabs] Tab character found here. Please use spaces instead. [ 6 of 12] Compiling Import ( src/Import.hs, .stack-work/dist/x86_64-linux/Cabal-1.24.2.0/build/Import.o ) [Foundation changed] [ 7 of 12] Compiling Handler.Comment ( src/Handler/Comment.hs, .stack-work/dist/x86_64-linux/Cabal-1.24.2.0/build/Handler/Comment.o ) [Foundation changed] [ 8 of 12] Compiling Handler.Common ( src/Handler/Common.hs, .stack-work/dist/x86_64-linux/Cabal-1.24.2.0/build/Handler/Common.o ) [Foundation changed] [ 9 of 12] Compiling Handler.Echo ( src/Handler/Echo.hs, .stack-work/dist/x86_64-linux/Cabal-1.24.2.0/build/Handler/Echo.o ) /root/blackbriar/blackbriar/src/Handler/Echo.hs:6:48: error: parse error on input ‘{’ -- While building package blackbriar-0.0.0 using: /root/.stack/setup-exe-cache/x86_64-linux/Cabal-simple_mPHDZzAJ_1.24.2.0_ghc-8.0.2 --builddir=.stack-work/dist/x86_64-linux/Cabal-1.24.2.0 build lib:blackbriar --ghc-options " -ddump-hi -ddump-to-file" Process exited with code: ExitFailure 1 Type help for available commands. Press enter to force a rebuild. | cs |
이번에는 Illegal view pattern 이라는 에러가 뜬다. 이 경우 다음과 같이 처리한다.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 | blackbriar-0.0.0: build (lib) Preprocessing library blackbriar-0.0.0... [11 of 12] Compiling Handler.Echo ( src/Handler/Echo.hs, .stack-work/dist/x86_64-linux/Cabal-1.24.2.0/build/Handler/Echo.o ) [12 of 12] Compiling Application ( src/Application.hs, .stack-work/dist/x86_64-linux/Cabal-1.24.2.0/build/Application.o ) /src/Application.hs:50:1: error: Illegal view pattern: fromPathPiece -> Just dyn_anHx Use ViewPatterns to enable view patterns -- While building package blackbriar-0.0.0 using: /root/.stack/setup-exe-cache/x86_64-linux/Cabal-simple_mPHDZzAJ_1.24.2.0_ghc-8.0.2 --builddir=.stack-work/dist/x86_64-linux/Cabal-1.24.2.0 build lib:blackbriar --ghc-options " -ddump-hi -ddump-to-file" Process exited with code: ExitFailure 1 Type help for available commands. Press enter to force a rebuild. ^Cuser interrupt yesod: Received ExitFailure 1 when running Raw command: stack build --fast --file-watch blackbriar:lib --exec "/root/.stack/snapshots/x86_64-linux/lts-9.14/8.0.2/bin/yesod devel-signal" --flag blackbriar:dev --flag blackbriar:library-only | cs |
스택오버플로우에 따르면, 먼저 yesod 버전이 오래되었으면 업데이트를 하고, view pattern 을 추가해야한다. 먼저 버전을 확인해보자. 1.4.17로 업데이트가 필요없다.
1 2 | (blackbriar) root@gcloudx:~/blackbriar/blackbriar# yesod version yesod-bin version: 1.4.17 | cs |
그러면 package.yaml 파일을 열어 다음과 같이 dependencies 섹션 다음에 default-extensions: ViewPatterns 를 추가한다.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 | name: blackbriar version: "0.0.0" dependencies: # Due to a bug in GHC 8.0.1, we block its usage # See: https://ghc.haskell.org/trac/ghc/ticket/12130 - base >=4.8.2.0 && <4.9 || >=4.9.1.0 && <5 # version 1.0 had a bug in reexporting Handler, causing trouble - classy-prelude-yesod >=0.10.2 && <1.0 || >=1.1 - yesod >=1.4.3 && <1.5 - yesod-core >=1.4.30 && <1.5 . . . - case-insensitive - wai default-extensions: ViewPatternsr Scripter | cs |
실행하면 다음과 같은 파싱에러가 발생한다. 이는 quasiquote 구문인 [whamlet|<h1>#{theText}|]
를 추가해놓고 QuasiQuotes GHC extension 이 사용가능하도록 설정하지 않았기 때문이다.
1 2 3 4 5 6 7 | [11 of 12] Compiling Handler.Echo ( src/Handler/Echo.hs, .stack-work/dist/x86_64-linux/Cabal-1.24.2.0/build/Handler/Echo.o ) /src/Handler/Echo.hs:6:48: error: parse error on input ‘{’ -- While building package blackbriar-0.0.0 using: /root/.stack/setup-exe-cache/x86_64-linux/Cabal-simple_mPHDZzAJ_1.24.2.0_ghc-8.0.2 --builddir=.stack-work/dist/x86_64-linux/Cabal-1.24.2.0 build lib:blackbriar --ghc-options " -ddump-hi -ddump-to-file" Process exited with code: ExitFailure 1 | cs |
아래와 같이 Echo.hs 최상단에 {-# LANGUAGE QuasiQuotes #-} 를 추가한다.
1 2 3 4 5 6 7 8 | {-# LANGUAGE QuasiQuotes #-} module Handler.Echo where import Import getEchoR :: String -> Handler Html getEchoR theText = defaultLayout [whamlet|<h1>#{theText}|] | cs |
여기까지 했으면 이제 실행해보자. 어떻게 될까?
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 | # stack exec -- yesod devel Yesod devel server. Enter 'quit' or hit Ctrl-C to quit. Application can be accessed at: http://localhost:3000 https://localhost:3443 If you wish to test https capabilities, you should set the following variable: export APPROOT=https://localhost:3443 blackbriar-0.0.0: configure (lib) Configuring blackbriar-0.0.0... blackbriar-0.0.0: build (lib) Preprocessing library blackbriar-0.0.0... [ 1 of 12] Compiling Settings ( src/Settings.hs, .stack-work/dist/x86_64-linux/Cabal-1.24.2.0/build/Settings.o ) [flags changed] [ 2 of 12] Compiling Settings.StaticFiles ( src/Settings/StaticFiles.hs, .stack-work/dist/x86_64-linux/Cabal-1.24.2.0/build/Settings/StaticFiles.o ) [flags changed] [ 3 of 12] Compiling Model ( src/Model.hs, .stack-work/dist/x86_64-linux/Cabal-1.24.2.0/build/Model.o ) [flags changed] [ 4 of 12] Compiling Import.NoFoundation ( src/Import/NoFoundation.hs, .stack-work/dist/x86_64-linux/Cabal-1.24.2.0/build/Import/NoFoundation.o ) [flags changed] [ 6 of 12] Compiling Import ( src/Import.hs, .stack-work/dist/x86_64-linux/Cabal-1.24.2.0/build/Import.o ) [flags changed] [ 7 of 12] Compiling Handler.Comment ( src/Handler/Comment.hs, .stack-work/dist/x86_64-linux/Cabal-1.24.2.0/build/Handler/Comment.o ) [flags changed] [ 8 of 12] Compiling Handler.Common ( src/Handler/Common.hs, .stack-work/dist/x86_64-linux/Cabal-1.24.2.0/build/Handler/Common.o ) [flags changed] [ 9 of 12] Compiling Handler.Echo ( src/Handler/Echo.hs, .stack-work/dist/x86_64-linux/Cabal-1.24.2.0/build/Handler/Echo.o ) [flags changed] [10 of 12] Compiling Handler.Home ( src/Handler/Home.hs, .stack-work/dist/x86_64-linux/Cabal-1.24.2.0/build/Handler/Home.o ) [flags changed] [11 of 12] Compiling Handler.Profile ( src/Handler/Profile.hs, .stack-work/dist/x86_64-linux/Cabal-1.24.2.0/build/Handler/Profile.o ) [flags changed] [12 of 12] Compiling Application ( src/Application.hs, .stack-work/dist/x86_64-linux/Cabal-1.24.2.0/build/Application.o ) blackbriar-0.0.0: copy/register Installing library in /.stack-work/install/x86_64-linux/lts-9.14/8.0.2/lib/x86_64-linux-ghc-8.0.2/blackbriar-0.0.0-18HzyIwvGfYDpXww1S7q4t Registering blackbriar-0.0.0... ExitSuccess Type help for available commands. Press enter to force a rebuild. Starting devel application Devel application launched: http://localhost:3000 19/Jan/2018:11:41:47 +0900 [Debug#SQL] SELECT "id", "message", "user_id" FROM "comment" ORDER BY "id"; [] GET / Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8 Status: 200 OK 0.089492s | cs |
'프로그래밍 Programming' 카테고리의 다른 글
Yesod의 위젯에 대해서 (1) (0) | 2018.01.27 |
---|---|
하스켈 익스텐션 사용법 How to Enable Extensions (0) | 2018.01.26 |
하스켈 Yesod Illegal view pattern: fromPathPiece -> Just dyn_anHx (0) | 2018.01.19 |
하스켈 Yesod Echo.hs:6:48: error: parse error on input ‘{’ (0) | 2018.01.19 |
하스켈 Starting out - (9) 타입 변수 Type variables (0) | 2017.12.05 |