packages feed

http-query (empty) → 0.1.0

raw patch · 5 files changed

+196/−0 lines, 5 filesdep +aesondep +basedep +bytestring

Dependencies added: aeson, base, bytestring, http-conduit, network-uri, text

Files

+ ChangeLog.md view
@@ -0,0 +1,4 @@+# Revision history for simple-query++## 0.1 -- 2020-08-18+- initial release
+ LICENSE view
@@ -0,0 +1,30 @@+Copyright (c) 2020, Jens Petersen++All rights reserved.++Redistribution and use in source and binary forms, with or without+modification, are permitted provided that the following conditions are met:++    * Redistributions of source code must retain the above copyright+      notice, this list of conditions and the following disclaimer.++    * Redistributions in binary form must reproduce the above+      copyright notice, this list of conditions and the following+      disclaimer in the documentation and/or other materials provided+      with the distribution.++    * Neither the name of Jens Petersen nor the names of other+      contributors may be used to endorse or promote products derived+      from this software without specific prior written permission.++THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ README.md view
@@ -0,0 +1,15 @@+# simple-query++Very thin layer over http-conduit for simpler web API queries.++See the Network.HTTP.Query documentation for more details.++## Examples++A few projects use http-query already:++- https://github.com/juhp/bodhi-hs+- https://github.com/juhp/copr-hs+- https://github.com/juhp/pagure-hs+- https://github.com/juhp/pdc-hs+- https://github.com/juhp/fbrnch
+ http-query.cabal view
@@ -0,0 +1,46 @@+name:                http-query+version:             0.1.0+synopsis:            Simple http queries+description:+        Simple web API queries to JSON.+license:             BSD3+license-file:        LICENSE+author:              Jens Petersen <juhpetersen@gmail.com>+maintainer:          Jens Petersen <juhpetersen@gmail.com>+copyright:           2020  Jens Petersen <juhpetersen@gmail.com>+category:            Web+homepage:            https://github.com/juhp/http-query+bug-reports:         https://github.com/juhp/http-query/issues+build-type:          Simple+extra-doc-files:     README.md+                     ChangeLog.md+cabal-version:       1.18++source-repository head+  type:                git+  location:            https://github.com/juhp/http-query.git++library+  build-depends:       base < 5+                     , aeson+                     , bytestring+                     , network-uri+                     , http-conduit+                     , text+  exposed-modules:     Network.HTTP.Query+  hs-source-dirs:      src++  ghc-options:         -Wall+  if impl(ghc >= 8.0)+    ghc-options:       -Wcompat+                       -Widentities+                       -Wincomplete-uni-patterns+                       -Wincomplete-record-updates+                       -Wredundant-constraints+  if impl(ghc >= 8.2)+    ghc-options:       -fhide-source-paths+  if impl(ghc >= 8.4)+    ghc-options:       -Wmissing-export-lists+                       -Wpartial-fields++  default-language:    Haskell2010
+ src/Network/HTTP/Query.hs view
@@ -0,0 +1,101 @@+{-# LANGUAGE CPP #-}++{-|+A small library for querying a Web API.++@+{-# LANGUAGE OverloadedStrings #-}++import Network.HTTP.Query++main = do+  let api = "http://www.example.com/api/1"+      endpoint = api +/+ "search"+  res <- webAPIQuery endpoint $ makeKey "q" "needle"+  case lookupKey "results" res of+    Nothing -> putStrLn "Result not found"+    Just results -> print results+@+-}++module Network.HTTP.Query (+  Query,+  QueryItem,+  maybeKey,+  makeKey,+  makeItem,+  (+/+),+  webAPIQuery,+  lookupKey,+  lookupKeyEither,+  lookupKey'+  ) where++import Control.Monad.IO.Class (MonadIO)+import Data.Aeson.Types+#if !MIN_VERSION_http_conduit(2,3,3)+import Data.ByteString (ByteString)+#endif+import qualified Data.ByteString.Char8 as B+import Data.Text (Text)+import Network.HTTP.Client.Conduit+import Network.HTTP.Simple+import Network.URI++#if !MIN_VERSION_http_conduit(2,3,1)+type Query = [(ByteString, Maybe ByteString)]+#endif+#if !MIN_VERSION_http_conduit(2,3,3)+type QueryItem = (ByteString, Maybe ByteString)+#endif++-- | Maybe create a query key+maybeKey :: String -> Maybe String -> Query+maybeKey _ Nothing = []+maybeKey k mval = [(B.pack k, fmap B.pack mval)]++-- | Make a singleton key-value Query+makeKey :: String -> String -> Query+makeKey k val = [(B.pack k, Just (B.pack val))]++-- | Make a key-value QueryItem+makeItem :: String -> String -> QueryItem+makeItem k val = (B.pack k, Just (B.pack val))++-- | Combine two path segments with a slash+--+-- > "abc" +/+ "def" == "abc/def"+-- > "abc/" +/+ "def" == "abc/def"+-- > "abc" +/+ "/def" == "abc/def"+infixr 5 +/++(+/+) :: String -> String -> String+"" +/+ s = s+s +/+ "" = s+s +/+ t | last s == '/' = s ++ t+        | head t == '/' = s ++ t+s +/+ t = s ++ '/' : t++-- | Low-level web api query+webAPIQuery :: (MonadIO m, FromJSON a)+            => String -- ^ url of endpoint+            -> Query -- ^ query options+            -> m a -- ^ returned json+webAPIQuery url params =+  case parseURI url of+    Nothing -> error $ "Cannot parse uri: " ++ url+    Just uri ->+      let req = setRequestQueryString params $ requestFromURI_ uri+      in getResponseBody <$> httpJSON req++-- | Look up key in object+lookupKey :: FromJSON a => Text -> Object -> Maybe a+lookupKey k = parseMaybe (.: k)++-- | Like lookupKey but returns error message if not found+lookupKeyEither :: FromJSON a => Text -> Object -> Either String a+lookupKeyEither k = parseEither (.: k)++-- | Like lookupKey but raises an error if no key found+lookupKey' :: FromJSON a => Text -> Object -> a+lookupKey' k =+  either error id . parseEither (.: k)