Add server-unix-socket config option (#1303)
Add ncat workaround to test socket connection on CircleCI
This commit is contained in:
committed by
Steve Chávez
parent
e292fb5eb9
commit
78e5677fbe
@@ -66,6 +66,11 @@ jobs:
|
||||
- restore_cache:
|
||||
keys:
|
||||
- v1-stack-dependencies-{{ checksum "postgrest.cabal" }}-{{ checksum "stack.yaml" }}
|
||||
- run:
|
||||
name: install ncat
|
||||
command: |
|
||||
# utility needed to test socket connection with curl < 7.40
|
||||
sudo apt-get install nmap
|
||||
- run:
|
||||
name: install stack & dependencies
|
||||
command: |
|
||||
|
||||
@@ -7,6 +7,7 @@ This project adheres to [Semantic Versioning](http://semver.org/).
|
||||
|
||||
### Added
|
||||
|
||||
- #1186, Add support for user defined unix socket via `server-unix-socket` config option
|
||||
- #690, Add `?columns` query parameter for faster bulk inserts, also ignores unspecified json keys in a payload - @steve-chavez
|
||||
- #1239, Add support for resource embedding on materialized views - @vitorbaptista
|
||||
- #1264, Add support for bulk RPC call - @steve-chavez
|
||||
|
||||
+49
-16
@@ -15,13 +15,22 @@ import Control.Retry (RetryStatus, capDelay,
|
||||
import Data.IORef (IORef, atomicWriteIORef, newIORef,
|
||||
readIORef)
|
||||
import Data.String (IsString (..))
|
||||
import Data.Text (pack, replace, strip, stripPrefix)
|
||||
import Data.Text (pack, replace, strip, stripPrefix,
|
||||
unpack)
|
||||
import Data.Text.Encoding (decodeUtf8, encodeUtf8)
|
||||
import Data.Text.IO (hPutStrLn, readFile)
|
||||
import Data.Time.Clock (getCurrentTime)
|
||||
import Network.Socket (Family (AF_UNIX),
|
||||
SockAddr (SockAddrUnix), Socket,
|
||||
SocketType (Stream), bind, close,
|
||||
defaultProtocol, listen,
|
||||
maxListenQueue, socket)
|
||||
import Network.Wai.Handler.Warp (defaultSettings, runSettings,
|
||||
setHost, setPort, setServerName)
|
||||
runSettingsSocket, setHost, setPort,
|
||||
setServerName)
|
||||
import System.Directory (removeFile)
|
||||
import System.IO (BufferMode (..), hSetBuffering)
|
||||
import System.IO.Error (isDoesNotExistError)
|
||||
|
||||
import PostgREST.App (postgrest)
|
||||
import PostgREST.Config (AppConfig (..), configPoolTimeout',
|
||||
@@ -153,6 +162,7 @@ main = do
|
||||
let host = configHost conf
|
||||
port = configPort conf
|
||||
proxy = configProxyUri conf
|
||||
maybeSocketAddr = configSocket conf
|
||||
pgSettings = toS (configDatabase conf) -- is the db-uri
|
||||
roleClaimKey = configRoleClaimKey conf
|
||||
appSettings =
|
||||
@@ -170,7 +180,6 @@ main = do
|
||||
when (isLeft roleClaimKey) $
|
||||
panic $ show roleClaimKey
|
||||
|
||||
putStrLn $ ("Listening on port " :: Text) <> show (configPort conf)
|
||||
--
|
||||
-- create connection pool with the provided settings, returns either
|
||||
-- a 'Connection' or a 'ConnectionError'. Does not throw.
|
||||
@@ -222,19 +231,31 @@ main = do
|
||||
-- ask for the OS time at most once per second
|
||||
getTime <- mkAutoUpdate defaultUpdateSettings {updateAction = getCurrentTime}
|
||||
|
||||
-- run the postgrest application
|
||||
runSettings appSettings $
|
||||
postgrest
|
||||
conf
|
||||
refDbStructure
|
||||
pool
|
||||
getTime
|
||||
(connectionWorker
|
||||
mainTid
|
||||
pool
|
||||
(configSchema conf)
|
||||
refDbStructure
|
||||
refIsWorkerOn)
|
||||
let postgrestApplication =
|
||||
postgrest
|
||||
conf
|
||||
refDbStructure
|
||||
pool
|
||||
getTime
|
||||
(connectionWorker
|
||||
mainTid
|
||||
pool
|
||||
(configSchema conf)
|
||||
refDbStructure
|
||||
refIsWorkerOn)
|
||||
in case maybeSocketAddr of
|
||||
Nothing -> do
|
||||
-- run the postgrest application
|
||||
putStrLn $ ("Listening on port " :: Text) <> show (configPort conf)
|
||||
runSettings appSettings postgrestApplication
|
||||
Just socketAddr -> do
|
||||
-- run postgrest application with user defined socket
|
||||
sock <- createAndBindSocket (unpack socketAddr)
|
||||
listen sock maxListenQueue
|
||||
putStrLn $ ("Listening on unix socket " :: Text) <> show socketAddr
|
||||
runSettingsSocket appSettings sock postgrestApplication
|
||||
-- clean socket up when done
|
||||
close sock
|
||||
|
||||
{-|
|
||||
The purpose of this function is to load the JWT secret from a file if
|
||||
@@ -302,3 +323,15 @@ loadDbUriFile conf = extractDbUri mDbUri
|
||||
Nothing -> return dbUri
|
||||
Just filename -> strip <$> readFile (toS filename)
|
||||
setDbUri dbUri = conf {configDatabase = dbUri}
|
||||
|
||||
createAndBindSocket :: FilePath -> IO Socket
|
||||
createAndBindSocket filePath = do
|
||||
deleteSocketFileIfExist filePath
|
||||
sock <- socket AF_UNIX Stream defaultProtocol
|
||||
bind sock $ SockAddrUnix filePath
|
||||
return sock
|
||||
where
|
||||
deleteSocketFileIfExist path = removeFile path `catch` handleDoesNotExist
|
||||
handleDoesNotExist e
|
||||
| isDoesNotExistError e = return ()
|
||||
| otherwise = throwIO e
|
||||
|
||||
+5
-2
@@ -33,17 +33,20 @@ executable postgrest
|
||||
default-language: Haskell2010
|
||||
build-depends: auto-update
|
||||
, base >= 4.8 && < 4.10
|
||||
, base64-bytestring
|
||||
, bytestring
|
||||
, hasql >= 1.3 && < 1.4
|
||||
, hasql-pool >= 0.5 && < 0.6
|
||||
, hasql-transaction >= 0.7 && < 0.8
|
||||
, network == 2.6.3.2
|
||||
, postgrest
|
||||
, protolude == 0.2.2
|
||||
, retry
|
||||
, text
|
||||
, time
|
||||
, warp
|
||||
, bytestring
|
||||
, base64-bytestring
|
||||
, retry
|
||||
, directory
|
||||
if !os(windows)
|
||||
build-depends: unix
|
||||
|
||||
|
||||
@@ -70,6 +70,7 @@ data AppConfig = AppConfig {
|
||||
, configSchema :: Text
|
||||
, configHost :: Text
|
||||
, configPort :: Int
|
||||
, configSocket :: Maybe Text
|
||||
|
||||
, configJwtSecret :: Maybe B.ByteString
|
||||
, configJwtSecretIsBase64 :: Bool
|
||||
@@ -149,6 +150,7 @@ readOptions = do
|
||||
<*> reqString "db-schema"
|
||||
<*> (fromMaybe "!4" . mfilter (/= "") <$> optString "server-host")
|
||||
<*> (fromMaybe 3000 . join . fmap coerceInt <$> optValue "server-port")
|
||||
<*> optString "server-unix-socket"
|
||||
<*> (fmap encodeUtf8 . mfilter (/= "") <$> optString "jwt-secret")
|
||||
<*> (fromMaybe False . join . fmap coerceBool <$> optValue "secret-is-base64")
|
||||
<*> parseJwtAudience "jwt-aud"
|
||||
@@ -231,6 +233,10 @@ readOptions = do
|
||||
|server-host = "!4"
|
||||
|server-port = 3000
|
||||
|
|
||||
|## unix socket location
|
||||
|## if specified it takes precedence over server-port
|
||||
|# server-unix-socket = "/tmp/pgrst.sock"
|
||||
|
|
||||
|## base url for swagger output
|
||||
|# server-proxy-uri = ""
|
||||
|
|
||||
|
||||
@@ -64,6 +64,8 @@ getEnvVarWithDefault var def = toS <$>
|
||||
_baseCfg :: AppConfig
|
||||
_baseCfg = -- Connection Settings
|
||||
AppConfig mempty "postgrest_test_anonymous" Nothing "test" "localhost" 3000
|
||||
-- No user configured Unix Socket
|
||||
Nothing
|
||||
-- Jwt settings
|
||||
(Just $ encodeUtf8 "reallyreallyreallyreallyverysafe") False Nothing
|
||||
-- Connection Modifiers
|
||||
|
||||
@@ -181,6 +181,30 @@ ensureAppSettings(){
|
||||
pgrStop
|
||||
}
|
||||
|
||||
getSocketStatus() {
|
||||
curl -sL -w "%{http_code}\\n" -o /dev/null localhost:54321
|
||||
}
|
||||
|
||||
socketConnection(){
|
||||
# map port 54321 traffic to unix socket as workaround for curl below 7.40
|
||||
# not supporting --unix-socket flag
|
||||
ncat -vlk 54321 -c 'ncat -U /tmp/postgrest.sock' &
|
||||
pgrStart "./configs/unix-socket.config"
|
||||
while pgrStarted && test "$( getSocketStatus )" -ne 200
|
||||
do
|
||||
# wait for the server to start
|
||||
sleep 0.1 \
|
||||
|| sleep 1 # fallback: subsecond sleep is not standard and may fail
|
||||
done
|
||||
if test $( getSocketStatus ) -eq 200
|
||||
then
|
||||
ok "Succesfully connected through unix socket"
|
||||
else
|
||||
ko "Failed to connect through unix socket"
|
||||
fi
|
||||
pgrStop
|
||||
}
|
||||
|
||||
# PRE: curl must be available
|
||||
test -n "$(command -v curl)" || bailOut 'curl is not available'
|
||||
|
||||
@@ -191,6 +215,8 @@ setUp
|
||||
|
||||
echo "Running IO tests.."
|
||||
|
||||
socketConnection
|
||||
|
||||
readSecretFromFile word.noeol 'simple (no EOL)'
|
||||
readSecretFromFile word.txt 'simple'
|
||||
readSecretFromFile ascii.noeol 'ASCII (no EOL)'
|
||||
@@ -224,6 +250,7 @@ invalidRoleClaimKey 1234
|
||||
ensureIatClaimWorks
|
||||
ensureAppSettings
|
||||
|
||||
|
||||
cleanUp
|
||||
|
||||
exit $failedTests
|
||||
|
||||
@@ -0,0 +1,7 @@
|
||||
db-uri = "postgres:///postgrest_test"
|
||||
db-schema = "test"
|
||||
db-anon-role = "postgrest_test_anonymous"
|
||||
db-pool = 1
|
||||
server-host = "127.0.0.1"
|
||||
server-unix-socket = "/tmp/postgrest.sock"
|
||||
jwt-secret = "reallyreallyreallyreallyverysafe"
|
||||
Reference in New Issue
Block a user