Устранение странной проблемы с кодировкой символов в библиотеке веб-очистки req от Haskell

#haskell

#haskell

Вопрос:

Я не могу понять ошибку, возникающую в этом коде:

 import Network.URI.Encode as EN

downloadFile :: (MonadHttp m) => String -> m ()
downloadFile url = do

    traceShowM (T.pack url)

    -- Pull them into memory
    contents <- req GET (https (T.pack $ EN.encode url)) NoReqBody bsResponse mempty

    -- debug read file wrote file etc

    -- Get the filename itself
    let fileName = head $ reverse $ T.splitOn "/" (T.pack url)
  

Это результат основной функции ( eatChunks ):

 
*Main UsCensusDataLodesScraper> eatChunks
"https://lehd.ces.census.gov/data/lodes/LODES7/ak/od/ak_od_aux_JT00_2003.csv.gz"
"https://lehd.ces.census.gov/data/lodes/LODES7/ak/od/ak_od_aux_JT00_2002.csv.gz"
"https://lehd.ces.census.gov/data/lodes/LODES7/ak/od/ak_od_aux_JT00_2004.csv.gz"
"https://lehd.ces.census.gov/data/lodes/LODES7/ak/od/ak_od_aux_JT00_2006.csv.gz"
"https://lehd.ces.census.gov/data/lodes/LODES7/ak/od/ak_od_aux_JT00_2008.csv.gz"
"https://lehd.ces.census.gov/data/lodes/LODES7/ak/od/ak_od_aux_JT00_2009.csv.gz"
"https://lehd.ces.census.gov/data/lodes/LODES7/ak/od/ak_od_aux_JT00_2007.csv.gz"
"https://lehd.ces.census.gov/data/lodes/LODES7/ak/od/ak_od_aux_JT00_2010.csv.gz"
"https://lehd.ces.census.gov/data/lodes/LODES7/ak/od/ak_od_aux_JT00_2011.csv.gz"
*** Exception: VanillaHttpException (HttpExceptionRequest Request {
  host                 = "https%3A%2F%2Flehd.ces.census.gov%2Fdata%2Flodes%2FLODES7%2Fak%2Fod%2Fak_od_aux_JT00_2002.csv.gz"
  port                 = 443
  secure               = True
  requestHeaders       = []
  path                 = ""
  queryString          = ""
  method               = "GET"
  proxy                = Nothing
  rawBody              = False
  redirectCount        = 10
  responseTimeout      = ResponseTimeoutDefault
  requestVersion       = HTTP/1.1
}
 (ConnectionFailure Network.Socket.getAddrInfo (called with preferred socket type/protocol: AddrInfo {addrFlags = [AI_ADDRCONFIG], addrFamily = AF_UNSPEC, addrSocketType = Stream, addrProtocol = 6, addrAddress = <assumed to be undefined>, addrCanonName = <assumed to be undefined>}, host name: Just "https%3A%2F%2Flehd.ces.census.gov%2Fdata%2Flodes%2FLODES7%2Fak%2Fod%2Fak_od_aux_JT00_2002.csv.gz", service name: Just "443"): does not exist (nodename nor servname provided, or not known)))
  

Ответ №1:

Вы не Url правильно создаете. Из документов на

http://hackage.haskell.org/package/req-2.0.1/docs/Network-HTTP-Req.html#g:5

мы видим, что Url можно создать несколькими способами.

  1. Вручную:
 https "lehd.ces.census.gov"
      /~ "data"
      /~ "lodes"
      /~ "LODES7"
      /~ "ak"
      /~ "od"
      /~ "ak_od_aux_JT00_2003.csv.gz"
  
  1. Путем синтаксического анализа:
 -- Don't actually use fromJust, this is just an example
fst . fromJust $ parseUrlHttps "https://lehd.ces.census.gov/data/lodes/LODES7/ak/od/ak_od_aux_JT00_2003.csv.gz"
  

В частности, обратите внимание, что https на самом деле делает: учитывая имя хоста, он создает a Url со схемой HTTPS, этим именем хоста и пустым путем. https someUrlString создаст Url подобное

 https://<the fully url-encoded version of someUrlString>
  

это не то, что вы хотите.

Ответ №2:

Вы почти наверняка не хотите вызывать EN.encode . Вероятно, просто удалите это.

Комментарии:

1. Конечно, но это просто приводит к другой проблеме с кодировкой: host = "https://lehd.ces.census.gov/data/lodes/LODES7/ak/od/ak_od_aux_JT00_2002.csv.gz"

2. Я попробовал это: contents <- req GET (https (EN.decodeText $ T.pack url)) NoReqBody bsResponse mempty и я получаю ту же ошибку.

3. Кто-то на другом канале сказал: «В ваше имя хоста добавлен путь, вызывающий удаление NXDOMAIN из DNS» — пытаюсь выяснить, как это решить.