Skip to content

Commit 7af1401

Browse files
author
Henrik Feldt
committed
Merge pull request #138 from SuaveIO/feature/parametise-files
[breaking] Feature/parametise files
2 parents c599c8f + 5a06847 commit 7af1401

File tree

5 files changed

+57
-27
lines changed

5 files changed

+57
-27
lines changed

Example/Program.fs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -82,8 +82,8 @@ choose [
8282
OK "First time")
8383
basic_auth // from here on it will require authentication
8484
GET >>= url "/events" >>= request (fun r -> EventSource.hand_shake (CounterDemo.counter_demo r))
85-
GET >>= browse //serves file if exists
86-
GET >>= dir //show directory listing
85+
GET >>= browse' //serves file if exists
86+
GET >>= dir' //show directory listing
8787
HEAD >>= url "/head" >>= sleep 100 "Nice sleep .."
8888
POST >>= url "/upload" >>= OK "Upload successful."
8989
POST >>= url "/upload2"

README.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -108,6 +108,11 @@ with the NuGet so that others can read your code's intentions easily.
108108

109109
Don't put unnecessary parenthesis unless it makes the code more clear.
110110

111+
When writing functions that take some sort of 'configuration' or that you can
112+
imagine would like to be called with a parameter which is almost always the same
113+
value for another function body's call-site, put that parameter before
114+
more-often-varying parameters in the function signature.
115+
111116
## Testing
112117

113118
Run Tests as a console app. Return status code = 0 means success.

Suave/Http.fs

Lines changed: 24 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -453,7 +453,12 @@ module Http =
453453
if fs.Length > 0L then
454454
do! transfer_x conn fs
455455
}
456-
{ ctx with response = { ctx.response with status = HTTP_200; content = SocketTask (write_file file_name)}} |> succeed
456+
{ ctx with
457+
response =
458+
{ ctx.response with
459+
status = HTTP_200
460+
content = SocketTask (write_file file_name) } }
461+
|> succeed
457462

458463
let file file_name =
459464
resource
@@ -475,16 +480,27 @@ module Http =
475480
else raise <| Exception("File canonalization issue.")
476481

477482
let browse_file file_name =
478-
fun ({request = r; runtime = q} as h) -> file (local_file file_name q.home_directory) h
483+
fun ({request = r; runtime = q} as h) ->
484+
file (local_file file_name q.home_directory) h
485+
486+
let browse root_path : WebPart =
487+
warbler (fun { request = r; runtime = { logger = l } } ->
488+
Log.verbose l
489+
"Suave.Http.Files.browse"
490+
Log.TraceHeader.empty
491+
(sprintf "Files.browse trying file (local_file url:'%s' root:'%s')"
492+
r.url root_path)
493+
file (local_file r.url root_path))
479494

480-
let browse : WebPart = warbler (fun {request = r; runtime = q } -> file (local_file r.url q.home_directory))
495+
let browse' : WebPart =
496+
warbler (fun { runtime = q } -> browse q.home_directory)
481497

482-
let dir (ctx : HttpContext) =
498+
let dir root_path (ctx : HttpContext) =
483499
let req = ctx.request
484500

485501
let url = req.url
486502

487-
let dirname = local_file url (ctx.runtime.home_directory)
503+
let dirname = local_file url root_path
488504
let result = new StringBuilder()
489505

490506
let filesize (x : FileSystemInfo) =
@@ -506,6 +522,9 @@ module Http =
506522
OK (result.ToString()) ctx
507523
else fail
508524

525+
let dir' ctx =
526+
dir ctx.runtime.home_directory ctx
527+
509528
module Embedded =
510529

511530
open System

Suave/Http.fsi

Lines changed: 26 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -1309,6 +1309,9 @@ module Http =
13091309
/// Responses to this method are not cacheable.
13101310
val OPTIONS : WebPart
13111311

1312+
/// The files module can be used to serve from the file system. It encapsulates
1313+
/// common patterns like verifying that back-symlinks or keywords aren't used
1314+
/// to gain access outside the intended folder.
13121315
module Files =
13131316

13141317
/// <summary><para>
@@ -1318,60 +1321,63 @@ module Http =
13181321
/// </para></summary>
13191322
/// <remarks>
13201323
/// </remarks>
1321-
val send_file : filename:string -> compression:bool -> WebPart
1324+
val send_file : file_name:string -> compression:bool -> WebPart
13221325

13231326
/// <summary><para>
13241327
/// Send the file by the filename given. Will search relative to the current directory for
13251328
/// the file path, unless you pass it a file with a slash at the start of its name, in which
13261329
/// case it will search the root of the file system that is hosting the current directory.
13271330
/// Will also set the MIME type based on the file extension.
1328-
/// </para><para>
1329-
/// </para><para>
13301331
/// </para></summary>
13311332
/// <remarks>
13321333
/// </remarks>
1333-
val file : filename:string -> WebPart
1334+
val file : file_name:string -> WebPart
13341335

13351336
/// <summary><para>
13361337
/// Format a string with a local file path given a file name 'fileName'. You should
13371338
/// use this helper method to find the current directory and concatenate that current
13381339
/// directory to the filename which should be absolute and start with a path separator.
1339-
/// </para><para>
1340-
/// </para><para>
13411340
/// </para></summary>
13421341
/// <remarks>
1342+
/// The current implementation doesn't take kindly to relative paths.
13431343
/// </remarks>
1344-
val local_file : fileName:string -> rootDir:string -> string
1344+
val local_file : file_name:string -> root_path:string -> string
13451345

13461346
/// <summary><para>
13471347
/// 'browse' the file given as the filename, by sending it to the browser with a
13481348
/// MIME-type/Content-Type header based on its extension. Will service from the
13491349
/// current directory.
1350-
/// </para><para>
1351-
/// </para><para>
13521350
/// </para></summary>
1353-
/// <remarks>
1354-
/// </remarks>
1355-
val browse_file : filename:string -> WebPart
1351+
val browse_file : file_name:string -> WebPart
13561352

13571353
/// <summary><para>
13581354
/// 'browse' the file in the sense that the contents of the file are sent based on the
1359-
/// request's Url property. Will serve from the current directory.
1360-
/// </para><para>
1361-
/// </para><para>
1355+
/// request's Url property. Will serve from the passed root path/directory.
13621356
/// </para></summary>
13631357
/// <remarks>
1358+
/// The current implementation doesn't take kindly to relative paths.
13641359
/// </remarks>
1365-
val browse : WebPart
1360+
val browse : root_path:string -> WebPart
13661361

13671362
/// <summary><para>
1368-
/// Serve a 'file browser' for a directory
1369-
/// </para><para>
1370-
/// </para><para>
1363+
/// 'browse' the file in the sense that the contents of the file are sent based on the
1364+
/// request's Url property. Will serve from the current as configured in directory.
1365+
/// Suave's runtime.
1366+
/// </para></summary>
1367+
val browse' : WebPart
1368+
1369+
/// <summary><para>
1370+
/// Serve a 'file browser' for a root_path
13711371
/// </para></summary>
13721372
/// <remarks>
1373+
/// The current implementation doesn't take kindly to relative paths.
13731374
/// </remarks>
1374-
val dir : WebPart
1375+
val dir : root_path:string -> WebPart
1376+
1377+
/// <summary><para>
1378+
/// Serve a 'file browser' for the current directory
1379+
/// </para></summary>
1380+
val dir' : WebPart
13751381

13761382
module Embedded =
13771383

tools/http-headers-status-v3.png

-403 KB
Binary file not shown.

0 commit comments

Comments
 (0)