하스켈 책 보충 자료
박준규 @curry@hackers.pub
책 《하스켈 병렬 및 동시성 프로그래밍(원제: Parallel and Concurrent Programming in Haskell)》 8장을 읽다 보면 다음과 같은 문구가 나옵니다.
We will use the following function to download a web page:
getURL :: String -> IO ByteStringThis function is provided by the module GetURL in GetURL.hs, which is a small wrapper around the API provided by the HTTP package.
그런데 GetURL.hs라는 파일을 찾을 수가 없어요. 저처럼 예제 코드 하나라도 실행 안 되면 진도를 못나가는 사람을 위해서 안내를 남깁니다.(사실은 미래의 저를 위한 글입니다.)
인터넷에서 검색을 좀 해보면(예전에 찾아 놓은 거고 지금은 원본 링크를 찾을 수가 없지만) 메릴랜드 대학의 CSMC 433이라는 과정에서 공교롭게 책과 같은 내용이 있고 그곳에서 다음과 같은 코드를 소개합니다.
-- For the example to work you need to have
-- the `bytestring` and the `download-curl`
-- haskell packages installed
import Data.ByteString as B
import Network.Curl.Download
getURL :: String -> IO ByteString
getURL uri = do
res <- openURI uri
case res of
Left _ -> error "Oh no..."
Right bs -> return bs
'됐다! 이거다!' 싶지만 막상 이 코드를 넣고 8장의 예제를 실행하면 기대했던대로 결과가 안 나오고 다음과 같이 페이지 응답 본문의 크기가 0으로 나옵니다.
(0,0)
이건 왜 그럴까? curl로 응답 헤더를 보니 https로 리다이렉트하고 있었네요.
$ curl -I http://www.wikipedia.org/wiki/Shovel
HTTP/1.1 301 Moved Permanently
content-length: 0
location: https://www.wikipedia.org/wiki/Shovel
server: HAProxy
x-cache: cp5024 int
x-cache-status: int-tls
connection: close
그래서 본문 내용이 없었기 때문에 크기가 0으로 나온 것입니다. 이때는 openURI 대신 openURIWithOpts를 쓰면 됩니다. 여러 옵션이 있는데 그중 CurlFollowLocation True를 사용합니다.
res <- openURIWithOpts opts uri
...
where
opts =
[ CurlFollowLocation True
]
'와, 이제 진짜 되겠지?' 해도 안 되는데 이번에는 404 응답이 옵니다.
'어? 브라우저랑 curl로 요청했을 때는 존재하는 페이지인데 왜 404래?'
아마 위키백과에서 요청 헤더에 User-Agent가 없으면 차단을 하는 것 같습니다. 마지막으로 다음과 같이 옵션을 추가합니다.(이건 GPT가 알려줬어요.)
opts =
[ CurlFollowLocation True
, CurlUserAgent "foo bar"
]
여기까지 하면 이제 책에 나온 예제가 잘 실행됩니다.
즐거운 하스켈 코딩 하세요!
