packages feed

http-directory (empty) → 0.1.0

raw patch · 6 files changed

+163/−0 lines, 6 filesdep +basedep +bytestringdep +html-conduitsetup-changed

Dependencies added: base, bytestring, html-conduit, http-client, http-types, semigroups, text, xml-conduit

Files

+ CHANGELOG.md view
@@ -0,0 +1,6 @@+# Changelog++`http-directory` uses [PVP Versioning](https://pvp.haskell.org).++## 0.1.0+- initial release with httpDirectory, httpFileSize, and httpRedirect(s)
+ LICENSE view
@@ -0,0 +1,21 @@+MIT License++Copyright (c) 2019 Jens Petersen++Permission is hereby granted, free of charge, to any person obtaining a copy+of this software and associated documentation files (the "Software"), to deal+in the Software without restriction, including without limitation the rights+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell+copies of the Software, and to permit persons to whom the Software is+furnished to do so, subject to the following conditions:++The above copyright notice and this permission notice shall be included in all+copies or substantial portions of the Software.++THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE+SOFTWARE.
+ README.md view
@@ -0,0 +1,9 @@+# http-directory++[![Hackage](https://img.shields.io/hackage/v/http-directory.svg)](https://hackage.haskell.org/package/http-directory)+[![MIT license](https://img.shields.io/badge/license-MIT-blue.svg)](LICENSE)+[![Stackage Lts](http://stackage.org/package/http-directory/badge/lts)](http://stackage.org/lts/package/http-directory)+[![Stackage Nightly](http://stackage.org/package/http-directory/badge/nightly)](http://stackage.org/nightly/package/http-directory)+[![Build status](https://secure.travis-ci.org/juhp/http-directory.svg)](https://travis-ci.org/juhp/http-directory)++A simple library for reading http directories.
+ Setup.hs view
@@ -0,0 +1,2 @@+import Distribution.Simple+main = defaultMain
+ http-directory.cabal view
@@ -0,0 +1,45 @@+cabal-version:       1.18+name:                http-directory+version:             0.1.0+synopsis:            http directory listing library+description:+            Library for listing http directories of files (links).+            Also it can check the size of files, and url redirects.+homepage:            https://github.com/juhp/http-directory+bug-reports:         https://github.com/juhp/http-directory/issues+license:             MIT+license-file:        LICENSE+author:              Jens Petersen+maintainer:          juhpetersen@gmail.com+copyright:           2019 Jens Petersen+category:            Network+build-type:          Simple+extra-doc-files:     README.md+                   , CHANGELOG.md+tested-with:         GHC == 7.6.3, GHC == 7.8.4, GHC == 7.10.3, GHC == 8.0.2,+                     GHC == 8.2.2, GHC == 8.4.4, GHC == 8.6.4++source-repository head+  type:                git+  location:            https://github.com/juhp/http-directory.git++library+  hs-source-dirs:      src+  exposed-modules:     Network.HTTP.Directory+                       ++  build-depends:       base < 5,+                       bytestring,+                       html-conduit,+                       http-client,+                       http-types,+                       text,+                       xml-conduit+  if impl(ghc<8.0)+      Build-depends: semigroups++  ghc-options:         -fwarn-missing-signatures+                       -Wall++  default-language:    Haskell2010+  default-extensions:  OverloadedStrings
+ src/Network/HTTP/Directory.hs view
@@ -0,0 +1,80 @@+{-# LANGUAGE CPP #-}++{-|+A library for listing "files" in an http "directory".++@+import Network.HTTP.Directory+import qualified Data.Text as T++main = do+  files <- httpDirectory "https://example.com/some/dir/"+  mapM_ T.putStrLn files+  httpFileSize (head files) >>= print+@+-}++module Network.HTTP.Directory+       ( httpDirectory,+         httpFileSize,+         httpRedirect,+         httpRedirects+       ) where++#if (defined(MIN_VERSION_base) && MIN_VERSION_base(4,8,0))+#else+import Control.Applicative ((<$>))+#endif++import qualified Data.ByteString.Char8 as B+import Data.Maybe+import Data.Text (Text)++import Network.HTTP.Client (hrRedirects, httpLbs, httpNoBody, Manager, method,+                            parseRequest, responseBody, responseHeaders,+                            responseOpenHistory, responseStatus)+import Network.HTTP.Types (hContentLength, hLocation, statusCode)++import Text.HTML.DOM (parseLBS)+import Text.XML.Cursor++-- | List the file links (hrefs) in an http directory+--+-- Note if the directory (webpage) url is redirected you may need to use+-- 'httpRedirect' to determine the actual final url prefix for relative links+-- (files).+httpDirectory :: Manager -> String -> IO [Text]+httpDirectory mgr url = do+  request <- parseRequest url+  response <- httpLbs request mgr+  if statusCode (responseStatus response) /= 200+    then error $ show $ responseStatus response+    else do+    let body = responseBody response+        doc = parseLBS body+        cursor = fromDocument doc+    return $ concatMap (attribute "href") $ cursor $// element "a"++-- | Try to get the filesize (Content-Length) of an http file+httpFileSize :: Manager -> String -> IO (Maybe Integer)+httpFileSize mgr url = do+  request <- parseRequest url+  response <- httpNoBody (request {method = "HEAD"}) mgr+  if statusCode (responseStatus response) /= 200+    then error $ show $ responseStatus response+    else do+    let headers = responseHeaders response+    return $ read . B.unpack <$> lookup hContentLength headers++-- | Returns the list of http redirects for an url in reverse order+-- (ie last redirect is first)+httpRedirects :: Manager -> String -> IO [B.ByteString]+httpRedirects mgr url = do+  request <- parseRequest url+  respHist <- responseOpenHistory (request {method = "HEAD"}) mgr+  return $ reverse $ mapMaybe (lookup hLocation . responseHeaders . snd) $ hrRedirects respHist++-- | Return final redirect for an url+httpRedirect :: Manager -> String -> IO (Maybe B.ByteString)+httpRedirect mgr url =+  listToMaybe <$> httpRedirects mgr url