Initial commit
This commit is contained in:
commit
3441ab2bbb
2
.gitignore
vendored
Normal file
2
.gitignore
vendored
Normal file
@ -0,0 +1,2 @@
|
||||
result
|
||||
dist/
|
5
ChangeLog.md
Normal file
5
ChangeLog.md
Normal file
@ -0,0 +1,5 @@
|
||||
# Revision history for rauhala-api
|
||||
|
||||
## 0.1.0.0 -- YYYY-mm-dd
|
||||
|
||||
* First version. Released on an unsuspecting world.
|
30
LICENSE
Normal file
30
LICENSE
Normal file
@ -0,0 +1,30 @@
|
||||
Copyright (c) 2018, Mats Rauhala
|
||||
|
||||
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 Mats Rauhala 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.
|
3
default.nix
Normal file
3
default.nix
Normal file
@ -0,0 +1,3 @@
|
||||
{ haskellPackages, haskell }:
|
||||
|
||||
haskellPackages.callCabal2nix "rauhala-api" ./. {}
|
8
executables/api.hs
Normal file
8
executables/api.hs
Normal file
@ -0,0 +1,8 @@
|
||||
module Main where
|
||||
|
||||
import Server
|
||||
import Network.Wai.Handler.Warp
|
||||
import Network.Wai.Middleware.Cors (simpleCors)
|
||||
|
||||
main :: IO ()
|
||||
main = run 8081 (simpleCors application)
|
11
executables/generator.hs
Normal file
11
executables/generator.hs
Normal file
@ -0,0 +1,11 @@
|
||||
{-# Language TypeApplications #-}
|
||||
{-# Language NoImplicitPrelude #-}
|
||||
module Main where
|
||||
|
||||
import API
|
||||
import Servant.JS
|
||||
import Data.Proxy (Proxy(..))
|
||||
import ClassyPrelude
|
||||
|
||||
main :: IO ()
|
||||
main = putStrLn $ jsForAPI (Proxy @API) vanillaJS
|
66
rauhala-api.cabal
Normal file
66
rauhala-api.cabal
Normal file
@ -0,0 +1,66 @@
|
||||
-- Initial rauhala-api.cabal generated by cabal init. For further
|
||||
-- documentation, see http://haskell.org/cabal/users-guide/
|
||||
|
||||
name: rauhala-api
|
||||
version: 0.1.0.0
|
||||
-- synopsis:
|
||||
-- description:
|
||||
license: BSD3
|
||||
license-file: LICENSE
|
||||
author: Mats Rauhala
|
||||
maintainer: mats@rauhala.info
|
||||
-- copyright:
|
||||
category: Web
|
||||
build-type: Simple
|
||||
extra-source-files: ChangeLog.md
|
||||
cabal-version: >=1.10
|
||||
|
||||
library
|
||||
exposed-modules: API
|
||||
, API.IPFS
|
||||
, Server
|
||||
, Server.IPFS
|
||||
-- other-modules:
|
||||
-- other-extensions:
|
||||
build-depends: base >=4.10
|
||||
, servant
|
||||
, servant-server
|
||||
, servant-docs
|
||||
, classy-prelude
|
||||
, aeson
|
||||
, pandoc
|
||||
, http-media
|
||||
, dns
|
||||
, lens
|
||||
hs-source-dirs: src
|
||||
default-language: Haskell2010
|
||||
|
||||
executable rauhala-api
|
||||
main-is: api.hs
|
||||
-- other-modules:
|
||||
-- other-extensions:
|
||||
build-depends: base >=4.10
|
||||
, rauhala-api
|
||||
, servant-server
|
||||
, wai
|
||||
, wai-cors
|
||||
, warp
|
||||
, mtl
|
||||
, classy-prelude
|
||||
, text
|
||||
, wai
|
||||
hs-source-dirs: executables
|
||||
default-language: Haskell2010
|
||||
|
||||
executable generator
|
||||
main-is: generator.hs
|
||||
-- other-modules:
|
||||
-- other-extensions:
|
||||
build-depends: base >=4.10
|
||||
, rauhala-api
|
||||
, servant-js
|
||||
, mtl
|
||||
, classy-prelude
|
||||
, text
|
||||
hs-source-dirs: executables
|
||||
default-language: Haskell2010
|
28
release.nix
Normal file
28
release.nix
Normal file
@ -0,0 +1,28 @@
|
||||
{ pkgs ? import <nixpkgs> {} }:
|
||||
|
||||
let
|
||||
_pkgs = import (pkgs.fetchFromGitHub {
|
||||
owner = "NixOS";
|
||||
repo = "nixpkgs";
|
||||
rev = "234a24cbeb66f70afaab9f13a5a9973c2fb956e0"; # LTS 12.10
|
||||
sha256 = "1n0n6dwyllkddl4nxjhkr1cq7mpk786dsr6v36589c7flj8inbwf";
|
||||
}) {};
|
||||
inherit (_pkgs) haskellPackages haskell buildEnv;
|
||||
pkg = import ./default.nix { inherit haskellPackages haskell; };
|
||||
shell = buildEnv {
|
||||
name = "shell";
|
||||
paths = [];
|
||||
buildInputs = [
|
||||
_pkgs.binutils-unwrapped
|
||||
haskellPackages.ghcid
|
||||
haskellPackages.hasktags
|
||||
(haskellPackages.ghcWithHoogle (_: pkg.buildInputs ++ pkg.propagatedBuildInputs))
|
||||
];
|
||||
};
|
||||
|
||||
in
|
||||
|
||||
{
|
||||
"rauhala-api" = pkg;
|
||||
"shell" = shell;
|
||||
}
|
35
src/API.hs
Normal file
35
src/API.hs
Normal file
@ -0,0 +1,35 @@
|
||||
{-# Language DataKinds #-}
|
||||
{-# Language NoImplicitPrelude #-}
|
||||
{-# Language TypeOperators #-}
|
||||
{-# Language MultiParamTypeClasses #-}
|
||||
{-# Language OverloadedStrings #-}
|
||||
module API where
|
||||
|
||||
import Servant.API
|
||||
import ClassyPrelude
|
||||
|
||||
import qualified API.IPFS as IPFS
|
||||
|
||||
import Text.Pandoc.Readers.Markdown (readMarkdown)
|
||||
import Text.Pandoc.Writers.HTML (writeHtml5String)
|
||||
import Text.Pandoc.Class (runPure, PandocMonad)
|
||||
import Text.Pandoc.Options (def)
|
||||
import Network.HTTP.Media ((//), (/:))
|
||||
|
||||
data HTML
|
||||
|
||||
newtype Docs = Docs Text
|
||||
|
||||
instance MimeRender PlainText Docs where
|
||||
mimeRender _ (Docs d) = fromStrict $ encodeUtf8 d
|
||||
|
||||
instance MimeRender HTML Docs where
|
||||
mimeRender _ (Docs d) = either (encodeUtf8 . pack . show) (fromStrict . encodeUtf8) $ runPure (writeHtml5String def <=< readMarkdown def $ d)
|
||||
|
||||
instance Accept HTML where
|
||||
contentType _ = "text" // "html" /: ("charset", "utf-8")
|
||||
|
||||
type API = "ipfs" :> IPFS.API
|
||||
|
||||
type DocumentedAPI = API
|
||||
:<|> "help" :> Get '[PlainText, HTML] Docs
|
24
src/API/IPFS.hs
Normal file
24
src/API/IPFS.hs
Normal file
@ -0,0 +1,24 @@
|
||||
{-# Language DataKinds #-}
|
||||
{-# Language TypeOperators #-}
|
||||
{-# Language GeneralizedNewtypeDeriving #-}
|
||||
{-# Language MultiParamTypeClasses #-}
|
||||
{-# Language NoImplicitPrelude #-}
|
||||
{-# Language DeriveGeneric #-}
|
||||
{-# Language OverloadedStrings #-}
|
||||
module API.IPFS where
|
||||
|
||||
import ClassyPrelude
|
||||
import Servant.API
|
||||
import Data.Aeson
|
||||
import Servant.Docs (singleSample, ToSample(..))
|
||||
|
||||
newtype VersionHash = VersionHash Text
|
||||
deriving (Show, ToJSON)
|
||||
|
||||
instance ToSample VersionHash where
|
||||
toSamples _ = singleSample (VersionHash "QmQdyH1o6g7Q1p4rJCWABTup5KgxYK1T9AZxBWpnhgMQQQ")
|
||||
|
||||
instance MimeRender PlainText VersionHash where
|
||||
mimeRender _ (VersionHash h) = fromStrict . encodeUtf8 $ h
|
||||
|
||||
type API = "current" :> Get '[JSON, PlainText] VersionHash
|
21
src/Server.hs
Normal file
21
src/Server.hs
Normal file
@ -0,0 +1,21 @@
|
||||
{-# Language NoImplicitPrelude #-}
|
||||
{-# Language TypeApplications #-}
|
||||
{-# Language OverloadedStrings #-}
|
||||
{-# Language GeneralizedNewtypeDeriving #-}
|
||||
module Server where
|
||||
|
||||
import API
|
||||
import ClassyPrelude
|
||||
import Servant
|
||||
import qualified Servant.Docs as Docs
|
||||
|
||||
import qualified Server.IPFS as IPFS
|
||||
|
||||
|
||||
server :: Server DocumentedAPI
|
||||
server = IPFS.handler :<|> pure mkDocs
|
||||
where
|
||||
mkDocs = Docs $ pack $ Docs.markdown $ Docs.docs (Proxy @API)
|
||||
|
||||
application :: Application
|
||||
application = serve (Proxy @DocumentedAPI) server
|
28
src/Server/IPFS.hs
Normal file
28
src/Server/IPFS.hs
Normal file
@ -0,0 +1,28 @@
|
||||
{-# Language NoImplicitPrelude #-}
|
||||
{-# Language OverloadedStrings #-}
|
||||
{-# Language ViewPatterns #-}
|
||||
{-# Language FlexibleContexts #-}
|
||||
module Server.IPFS where
|
||||
|
||||
import API.IPFS
|
||||
import Servant
|
||||
import ClassyPrelude
|
||||
|
||||
import Network.DNS
|
||||
|
||||
import Control.Lens (over, _Left)
|
||||
|
||||
handler :: Server API
|
||||
handler = liftIO getHash >>= either (const (throwError err500)) return
|
||||
where
|
||||
getHash :: IO (Either String VersionHash)
|
||||
getHash =
|
||||
makeResolvSeed defaultResolvConf >>=
|
||||
\rs -> withResolver rs $ \resolver -> do
|
||||
eTxt <- over _Left show <$> lookupTXT resolver "rauhala.info"
|
||||
-- This is terrible
|
||||
return (eTxt >>= maybe (Left "Could not find dnslink") Right . hash)
|
||||
hash [x] = case x of
|
||||
(stripPrefix "dnslink" -> Just h) -> Just . VersionHash . decodeUtf8 $ h
|
||||
_ -> Nothing
|
||||
hash _ = Nothing
|
Loading…
Reference in New Issue
Block a user