@@ -17,23 +17,22 @@ module Distribution.Server (
17
17
initState ,
18
18
) where
19
19
20
- import Distribution.Package
21
- ( PackageIdentifier (.. ), packageName , PackageId )
22
- import Distribution.Text
23
- ( display , simpleParse )
20
+ import Distribution.Package (packageName )
24
21
import Happstack.Server hiding (port , host )
25
22
import qualified Happstack.Server
26
23
import Happstack.State hiding (Version )
27
24
28
- import Distribution.Server.ServerParts
29
- (guardAuth )
25
+ import Distribution.Server.ServerParts (guardAuth )
30
26
import qualified Distribution.Server.Import as Import ( importTar )
31
27
32
28
import Distribution.Server.Packages.ServerParts
33
29
import Distribution.Server.Users.ServerParts
34
30
import Distribution.Server.Distributions.ServerParts
35
31
import Distribution.Server.Users.Permissions (GroupName (.. ))
36
32
33
+ import qualified Distribution.Server.Feature as Feature
34
+ import qualified Distribution.Server.Features as Features
35
+
37
36
import Distribution.Server.State as State
38
37
import Distribution.Server.Packages.State as State hiding (buildReports , bulkImport )
39
38
import Distribution.Server.Users.State as State
@@ -43,30 +42,32 @@ import Distribution.Server.Packages.Types
43
42
import qualified Distribution.Server.ResourceTypes as Resource
44
43
import qualified Distribution.Server.Util.BlobStorage as BlobStorage
45
44
import Distribution.Server.Util.BlobStorage (BlobStorage )
46
- import Distribution.Server.Util.Happstack (remainingPath )
47
45
import qualified Distribution.Server.BulkImport as BulkImport
48
46
import qualified Distribution.Server.BulkImport.UploadLog as UploadLog
49
47
50
48
import qualified Distribution.Server.Users.Users as Users
51
49
import qualified Distribution.Server.Users.Types as Users
52
50
53
51
import Distribution.Server.Export.ServerParts (export )
54
-
55
52
import Distribution.Server.Auth.Types (PasswdPlain (.. ))
56
53
54
+ import Distribution.Server.Resource (addResponse , serverTreeEmpty , renderServerTree , spiffyResources )
55
+ import Data.List (foldl' )
56
+
57
57
import System.FilePath ((</>) )
58
- import qualified System.FilePath.Posix as Posix (joinPath , splitExtension )
59
58
import System.Directory
60
59
( createDirectoryIfMissing , doesDirectoryExist )
61
60
import Control.Concurrent.MVar (MVar )
62
61
import Control.Monad.Trans
63
- import Control.Monad (when ,msum , mzero )
62
+ import Control.Monad (when , msum )
64
63
import Data.ByteString.Lazy.Char8 (ByteString )
65
64
import Network.URI
66
65
( URIAuth (URIAuth ) )
67
66
import Network.BSD
68
67
( getHostName )
68
+ import qualified Data.Map as Map (empty )
69
69
70
+ import qualified Data.ByteString.Lazy.Char8 as BS
70
71
71
72
import Paths_hackage_server (getDataDir )
72
73
@@ -75,7 +76,7 @@ data Config = Config {
75
76
confPortNum :: Int ,
76
77
confStateDir :: FilePath ,
77
78
confStaticDir :: FilePath
78
- }
79
+ } deriving ( Show )
79
80
80
81
confHappsStateDir , confBlobStoreDir :: Config -> FilePath
81
82
confHappsStateDir config = confStateDir config </> " db"
@@ -93,12 +94,10 @@ defaultConfig = do
93
94
}
94
95
95
96
data Server = Server {
96
- serverStore :: BlobStorage ,
97
- serverStaticDir :: FilePath ,
98
- serverTxControl :: MVar TxControl ,
99
- serverCache :: Cache. Cache ,
100
- serverURI :: URIAuth ,
101
- serverPort :: Int
97
+ serverTxControl :: MVar TxControl ,
98
+ serverFeatureConfig :: Feature. Config ,
99
+ serverPort :: Int ,
100
+ serverCache :: Cache. Cache
102
101
}
103
102
104
103
-- | If we made a server instance from this 'Config', would we find some
@@ -130,12 +129,14 @@ initialise config@(Config hostName portNum stateDir staticDir) = do
130
129
cache <- Cache. new =<< stateToCache hostURI =<< query GetPackagesState
131
130
132
131
return Server {
133
- serverStore = store,
134
- serverStaticDir = staticDir,
135
132
serverTxControl = txCtl,
136
- serverCache = cache,
137
- serverURI = hostURI,
138
- serverPort = portNum
133
+ serverFeatureConfig = Feature. Config {
134
+ Feature. serverStore = store,
135
+ Feature. serverStaticDir = staticDir,
136
+ Feature. serverURI = hostURI
137
+ },
138
+ serverPort = portNum,
139
+ serverCache = cache
139
140
}
140
141
141
142
where
@@ -151,9 +152,16 @@ hackageEntryPoint = Proxy
151
152
-- | Actually run the server, i.e. start accepting client http connections.
152
153
--
153
154
run :: Server -> IO ()
154
- run server = simpleHTTP conf $ msum ( impl server)
155
+ run server = simpleHTTP conf $ mungeRequest $ impl server
155
156
where
156
157
conf = nullConf { Happstack.Server. port = serverPort server }
158
+ mungeRequest = localRq mungeMethod
159
+ mungeMethod req = case (rqMethod req, lookup " _method" (rqInputs req)) of
160
+ (POST , Just input) -> case reads (BS. unpack (inputValue input)) of
161
+ [(newMethod, " " )] -> req { rqMethod = newMethod }
162
+ _ -> req
163
+ _ -> req
164
+ -- todo: given a .json or .html suffix, munge it into an Accept header
157
165
158
166
-- | Perform a clean shutdown of the server.
159
167
--
@@ -173,7 +181,7 @@ bulkImport :: Server
173
181
-> Maybe String -- users
174
182
-> Maybe String -- admin users
175
183
-> IO [UploadLog. Entry ]
176
- bulkImport (Server store _ _ cache host _ )
184
+ bulkImport (Server _ ( Feature. Config store _ host) _ cache )
177
185
indexFile logFile archiveFile htPasswdFile adminsFile = do
178
186
pkgIndex <- either fail return (BulkImport. importPkgIndex indexFile)
179
187
uploadLog <- either fail return (BulkImport. importUploadLog logFile)
@@ -213,7 +221,7 @@ bulkImport (Server store _ _ cache host _)
213
221
Just uid -> Right uid
214
222
215
223
importTar :: Server -> ByteString -> IO (Maybe String )
216
- importTar (Server store _ _ cache host _ ) tar = do
224
+ importTar (Server _ ( Feature. Config store _ host) _ cache ) tar = do
217
225
res <- Import. importTar store tar
218
226
case res of
219
227
Nothing -> updateCache cache host
@@ -223,7 +231,7 @@ importTar (Server store _ _ cache host _) tar = do
223
231
-- An alternative to an import.
224
232
-- Starts the server off to a sane initial state.
225
233
initState :: MonadIO m => Server -> m ()
226
- initState (Server _ _ _ cache host _ ) = do
234
+ initState (Server _ ( Feature. Config _ _ host) _ cache ) = do
227
235
-- clear off existing state
228
236
update $ BulkImport [] Users. empty
229
237
update $ BulkImportPermissions []
@@ -239,89 +247,13 @@ initState (Server _ _ _ cache host _) = do
239
247
240
248
updateCache cache host
241
249
242
- -- Support the same URL scheme as the first version of hackage.
243
- legacySupport :: ServerPart Response
244
- legacySupport
245
- = msum [ legPackagesPath, legCgiScripts]
246
250
247
- where
251
+ impl :: Server -> ServerPart Response
252
+ impl server = flip renderServerTree Map. empty $ spiffyResources $ foldl' (flip $ uncurry addResponse) serverTreeEmpty $ ([] , core server): concatMap (Feature. serverParts) Features. hackageFeatures
248
253
249
- -- the old "packages/archive" directory
250
- legPackagesPath
251
- = dir " packages" $
252
- dir " archive" $
253
- msum
254
- [ path $ \ name ->
255
- path $ \ version ->
256
- let pkgid = PackageIdentifier {pkgName = name, pkgVersion = version}
257
- in msum
258
- [ let dirName = display pkgid ++ " .tar.gz"
259
- in dir dirName $ methodSP GET $
260
- movedPermanently (packageTarball pkgid) (toResponse " " )
261
-
262
- , let fileName = display name ++ " .cabal"
263
- in dir fileName $ methodSP GET $
264
- movedPermanently (cabalPath pkgid) (toResponse " " )
265
-
266
- , dir " doc" $ dir " html" $ remainingPath $ \ paths ->
267
- let doc = Posix. joinPath paths
268
- in methodSP GET $
269
- movedPermanently (docPath pkgid doc) (toResponse " " )
270
- ]
271
-
272
- , dir " package" $ path $ \ fileName -> methodSP GET $
273
- do packageStr <- splitExtensions fileName [" .gz" , " .tar" ]
274
- case simpleParse packageStr of
275
- Just pkgid -> movedPermanently (packageTarball pkgid) $ toResponse " "
276
- _ -> mzero
277
-
278
- , dir " 00-index.tar.gz" $
279
- methodSP GET $
280
- movedPermanently " /00-index.tar.gz" (toResponse " " )
281
- ]
282
-
283
- -- the old "cgi-bin/hackage-scripts" directory
284
- legCgiScripts =
285
- dir " cgi-bin" $
286
- dir " hackage-scripts" $
287
- msum
288
- [ dir " check-pkg" $
289
- methodSP POST $
290
- movedPermanently " /check" $
291
- toResponse " "
292
- , dir " upload-pkg" $
293
- methodSP POST $
294
- movedPermanently " /upload" $
295
- toResponse " "
296
- , dir " package" $ path $
297
- \ packageId ->
298
- methodSP GET $
299
- movedPermanently (" /package/" ++ display (packageId :: PackageId )) $
300
- toResponse " "
301
- ]
302
-
303
-
304
- packageTarball :: PackageId -> String
305
- packageTarball pkgid
306
- = " /package/" ++ display pkgid ++ " .tar.gz"
307
-
308
- docPath pkgid file = " /package/" ++ display pkgid ++ " /"
309
- ++ " documentation/" ++ file
310
-
311
- cabalPath pkgid = " /package/" ++ display pkgid ++ " /"
312
- ++ display (packageName pkgid) ++ " .cabal"
313
-
314
- splitExtensions fp [] = return fp
315
- splitExtensions fp (x: xs) =
316
- case Posix. splitExtension fp of
317
- (fp', ext) | ext == x -> splitExtensions fp' xs
318
- _ -> mzero
319
-
320
-
321
- impl :: Server -> [ServerPartT IO Response ]
322
- impl (Server store static _ cache host _) =
323
- [ legacySupport
324
- , dir " packages" $
254
+ core :: Server -> ServerPart Response
255
+ core (Server _ (Feature. Config store static host) _ cache) = msum
256
+ [ dir " packages" $
325
257
methodSP GET $
326
258
ok . Cache. packagesPage =<< Cache. get cache
327
259
, dir " package" $ msum
@@ -341,24 +273,24 @@ impl (Server store static _ cache host _) =
341
273
cacheState <- Cache. get cache
342
274
ok $ toResponse $ Resource. IndexTarball (Cache. indexTarball cacheState)
343
275
]
344
- , dir " admin" $ admin store
276
+ , dir " admin" $ admin static store
345
277
, dir " check" checkPackage
346
278
, dir " htpasswd" $ msum
347
279
[ changePassword ]
348
280
, dir " distro" distros
349
281
, fileServe [" hackage.html" ] static
350
282
]
351
283
352
-
353
284
-- Top level server part for administrative actions under the "admin"
354
285
-- directory
355
- admin :: BlobStorage -> ServerPart Response
356
- admin storage = do
286
+ admin :: FilePath -> BlobStorage -> ServerPart Response
287
+ admin static storage = do
357
288
358
289
guardAuth [Administrator ]
359
290
360
291
msum
361
292
[ dir " users" userAdmin
362
293
, dir " export.tar.gz" (export storage)
363
294
, adminDist
295
+ , fileServe [" admin.html" ] static
364
296
]
0 commit comments