git.iko.soy/typeable/pagerduty
on develop help sign in
Sharing HTTP code between REST and Integration API
commitdc8e92360088b3ae442de13846a0926cb1d4aa71 authorBrendan Hay <brendan.g.hay@gmail.com> dateTue 30 Sep 2014, 17:16 (12 years ago) parent5a9881f
4 files changed+105−61
pagerduty.cabal+5−3 src/Network/PagerDuty.hs+13−50 src/Network/PagerDuty/HTTP.hs+67 src/Network/PagerDuty/Integration.hs+20−8
pagerduty.cabal+5−3
@@ -31,11 +31,13 @@ library
3131
3232 exposed-modules:
3333 Network.PagerDuty
34− , Network.PagerDuty.Alerts
35− , Network.PagerDuty.EscalationPolicies
36− , Network.PagerDuty.Services
34+ -- , Network.PagerDuty.Alerts
35+ -- , Network.PagerDuty.EscalationPolicies
36+ -- , Network.PagerDuty.Services
3737 , Network.PagerDuty.Integration
3838
39+ , Network.PagerDuty.HTTP
40+
3941 -- , Network.PagerDuty.Incidents
4042 -- , Network.PagerDuty.Integration
4143 -- , Network.PagerDuty.LogEntries
src/Network/PagerDuty.hs+13−50
@@ -27,15 +27,15 @@ import Control.Lens
2727import Control.Monad
2828import Control.Monad.IO.Class
2929import Control.Monad.Trans
30−import Data.Aeson hiding (Error)
31−import qualified Data.ByteString.Lazy as LBS
30+import Data.Aeson hiding (Error)
31+import qualified Data.ByteString.Lazy as LBS
3232import Data.Conduit
3333import Data.Default
3434import Data.Monoid
35−import Network.HTTP.Client (Manager, httpLbs)
36−import qualified Network.HTTP.Client as Client
37−import qualified Network.HTTP.Client.Lens as Lens
35+import Network.HTTP.Client (Manager, applyBasicAuth)
36+import qualified Network.HTTP.Client.Lens as Lens
3837import Network.HTTP.Types
38+import Network.PagerDuty.HTTP
3939import Network.PagerDuty.Types
4040
4141-- data Env (s :: Security) = Env
@@ -73,49 +73,12 @@ http :: (MonadIO m, FromJSON b)
7373 -> Manager
7474 -> Request a s b
7575 -> m (Either Error (b, Maybe Pager))
76−http a (SubDomain h) m rq = liftIO (httpLbs raw m) >>= response rq
76+http a (SubDomain h) m rq = request m rq $ raw
77+ & Lens.host .~ h
78+ & Lens.path .~ renderPath (rq ^. path)
79+ & Lens.queryString .~ renderQuery False (rq ^. query)
7780 where
78− raw = authorise
79− & Lens.secure .~ True
80− & Lens.port .~ 443
81− & Lens.path .~ renderPath (rq ^. path)
82− & Lens.queryString .~ renderQuery False (rq ^. query)
83− & Lens.requestHeaders <>~ headers
84− & Lens.requestBody .~ Client.RequestBodyLBS (encode rq)
85−
86− authorise = case a of
87− AuthBasic u p -> Client.applyBasicAuth u p def & Lens.host .~ h
88− AuthToken t -> def & Lens.host .~ h & Lens.requestHeaders <>~ [token t]
89−
90− token t = ("Authorization", "Token token=" <> t)
91−
92− headers =
93− [ ("Content-Type", "application/json")
94− , ("Accept", "application/json")
95− ]
96−
97−response :: (MonadIO m, FromJSON b)
98− => Request a s b
99− -> Client.Response LBS.ByteString
100− -> m (Either Error (b, Maybe Pager))
101−response _ x = case statusCode (Client.responseStatus x) of
102− 200 -> success
103− 201 -> success
104− 400 -> failure
105− 500 -> failure
106− n -> return . Left $ unhandled n
107− where
108− success = maybe (Left unknown) Right `liftM` parse
109− failure = maybe (Left unknown) Left `liftM` parse
110−
111− unhandled n = Internal
112− $ "PagerDuty returned unhandled status code: " ++ show n
113−
114− unknown = Internal
115− $ "Unable to parse response into a PagerDuty API compatible type: "
116− ++ show body
117−
118− parse :: (Monad m, FromJSON a) => m (Maybe a)
119− parse = return (decode body)
120−
121− body = Client.responseBody x
81+ raw = case a of
82+ AuthBasic u p -> applyBasicAuth u p def
83+ AuthToken t -> def & Lens.requestHeaders <>~
84+ [("Authorization", "Token token=" <> t)]
src/Network/PagerDuty/HTTP.hsnew file+67
@@ -0,0 +1,67 @@
1+{-# LANGUAGE OverloadedStrings #-}
2+
3+-- Module : Network.PagerDuty.HTTP
4+-- Copyright : (c) 2013-2014 Brendan Hay <brendan.g.hay@gmail.com>
5+-- License : This Source Code Form is subject to the terms of
6+-- the Mozilla Public License, v. 2.0.
7+-- A copy of the MPL can be found in the LICENSE file or
8+-- you can obtain it at http://mozilla.org/MPL/2.0/.
9+-- Maintainer : Brendan Hay <brendan.g.hay@gmail.com>
10+-- Stability : experimental
11+-- Portability : non-portable (GHC extensions)
12+
13+module Network.PagerDuty.HTTP where
14+
15+import Control.Lens
16+import Control.Monad
17+import Control.Monad.IO.Class
18+import Data.Aeson hiding (Error)
19+import qualified Data.ByteString.Lazy as LBS
20+import Network.HTTP.Client (Manager, httpLbs)
21+import qualified Network.HTTP.Client as Client
22+import qualified Network.HTTP.Client.Lens as Lens
23+import Network.HTTP.Types
24+import Network.PagerDuty.Types
25+
26+request :: (MonadIO m, ToJSON a, FromJSON b)
27+ => Manager
28+ -> a
29+ -> Client.Request
30+ -> m (Either Error b)
31+request m x rq = liftIO (httpLbs raw m) >>= response
32+ where
33+ raw = rq
34+ & Lens.secure .~ True
35+ & Lens.port .~ 443
36+ & Lens.requestHeaders .~ headers
37+ & Lens.requestBody .~ Client.RequestBodyLBS (encode x)
38+
39+ headers =
40+ [ ("Content-Type", "application/json")
41+ , ("Accept", "application/json")
42+ ]
43+
44+response :: (MonadIO m, FromJSON b)
45+ => Client.Response LBS.ByteString
46+ -> m (Either Error b)
47+response rs = case statusCode (Client.responseStatus rs) of
48+ 200 -> success
49+ 201 -> success
50+ 400 -> failure
51+ 500 -> failure
52+ n -> return . Left $ unhandled n
53+ where
54+ success = maybe (Left unknown) Right `liftM` parse
55+ failure = maybe (Left unknown) Left `liftM` parse
56+
57+ unhandled n = Internal
58+ $ "PagerDuty returned unhandled status code: " ++ show n
59+
60+ unknown = Internal
61+ $ "Unable to parse response into a PagerDuty API compatible type: "
62+ ++ show body
63+
64+ parse :: (Monad m, FromJSON a) => m (Maybe a)
65+ parse = return (decode body)
66+
67+ body = Client.responseBody rs
src/Network/PagerDuty/Integration.hs+20−8
@@ -76,14 +76,19 @@ module Network.PagerDuty.Integration
7676
7777import Control.Applicative
7878import Control.Lens
79+import Control.Monad.IO.Class
7980import Data.Aeson
8081import Data.Aeson.Types
81−import qualified Data.HashMap.Strict as Map
82+import Data.Default
83+import qualified Data.HashMap.Strict as Map
8284import Data.Monoid
83−import Data.Text (Text)
84−import qualified Data.Text as Text
85+import Data.Text (Text)
86+import qualified Data.Text as Text
87+import Network.HTTP.Client (Manager)
88+import qualified Network.HTTP.Client.Lens as Lens
89+import Network.PagerDuty.HTTP
8590import Network.PagerDuty.TH
86−import Network.PagerDuty.Types (ServiceKey, IncidentKey)
91+import Network.PagerDuty.Types (ServiceKey, IncidentKey)
8792
8893data Response = Response
8994 { _rsStatus :: Text
@@ -264,7 +269,14 @@ rDescription = _Resolve.gDescription
264269rDetails :: Lens' Resolve Object
265270rDetails = _Resolve.gDetails
266271
267−submit :: (Monad m, Event a) => a -> m (Either Error Response)
268−submit = undefined
269− -- where
270− -- payload = Map.insert "event_type" (String (eventType x)) (eventPayload x)
272+submit :: (MonadIO m, Event a) => Manager -> a -> m (Either Error Response)
273+submit x m = request m (Object payload) $ def
274+ & Lens.host .~ "events.pagerduty.com"
275+ & Lens.path .~ "/generic/2010-04-15/create_event.json"
276+ where
277+ payload = Map.insert "event_type" (String (eventType x)) (eventPayload x)
278+
279+ headers =
280+ [ ("Content-Type", "application/json")
281+ , ("Accept", "application/json")
282+ ]