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 +4/−0
- LICENSE +30/−0
- README.md +15/−0
- http-query.cabal +46/−0
- src/Network/HTTP/Query.hs +101/−0
+ 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)