Skip to content

Commit

Permalink
Merge pull request SuaveIO#138 from SuaveIO/feature/parametise-files
Browse files Browse the repository at this point in the history
[breaking] Feature/parametise files
  • Loading branch information
Henrik Feldt committed Nov 9, 2014
2 parents c599c8f + 5a06847 commit 7af1401
Show file tree
Hide file tree
Showing 5 changed files with 57 additions and 27 deletions.
4 changes: 2 additions & 2 deletions Example/Program.fs
Original file line number Diff line number Diff line change
Expand Up @@ -82,8 +82,8 @@ choose [
OK "First time")
basic_auth // from here on it will require authentication
GET >>= url "/events" >>= request (fun r -> EventSource.hand_shake (CounterDemo.counter_demo r))
GET >>= browse //serves file if exists
GET >>= dir //show directory listing
GET >>= browse' //serves file if exists
GET >>= dir' //show directory listing
HEAD >>= url "/head" >>= sleep 100 "Nice sleep .."
POST >>= url "/upload" >>= OK "Upload successful."
POST >>= url "/upload2"
Expand Down
5 changes: 5 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -108,6 +108,11 @@ with the NuGet so that others can read your code's intentions easily.

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

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

## Testing

Run Tests as a console app. Return status code = 0 means success.
Expand Down
29 changes: 24 additions & 5 deletions Suave/Http.fs
Original file line number Diff line number Diff line change
Expand Up @@ -453,7 +453,12 @@ module Http =
if fs.Length > 0L then
do! transfer_x conn fs
}
{ ctx with response = { ctx.response with status = HTTP_200; content = SocketTask (write_file file_name)}} |> succeed
{ ctx with
response =
{ ctx.response with
status = HTTP_200
content = SocketTask (write_file file_name) } }
|> succeed

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

let browse_file file_name =
fun ({request = r; runtime = q} as h) -> file (local_file file_name q.home_directory) h
fun ({request = r; runtime = q} as h) ->
file (local_file file_name q.home_directory) h

let browse root_path : WebPart =
warbler (fun { request = r; runtime = { logger = l } } ->
Log.verbose l
"Suave.Http.Files.browse"
Log.TraceHeader.empty
(sprintf "Files.browse trying file (local_file url:'%s' root:'%s')"
r.url root_path)
file (local_file r.url root_path))

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

let dir (ctx : HttpContext) =
let dir root_path (ctx : HttpContext) =
let req = ctx.request

let url = req.url

let dirname = local_file url (ctx.runtime.home_directory)
let dirname = local_file url root_path
let result = new StringBuilder()

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

let dir' ctx =
dir ctx.runtime.home_directory ctx

module Embedded =

open System
Expand Down
46 changes: 26 additions & 20 deletions Suave/Http.fsi
Original file line number Diff line number Diff line change
Expand Up @@ -1309,6 +1309,9 @@ module Http =
/// Responses to this method are not cacheable.
val OPTIONS : WebPart

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

/// <summary><para>
Expand All @@ -1318,60 +1321,63 @@ module Http =
/// </para></summary>
/// <remarks>
/// </remarks>
val send_file : filename:string -> compression:bool -> WebPart
val send_file : file_name:string -> compression:bool -> WebPart

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

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

/// <summary><para>
/// 'browse' the file given as the filename, by sending it to the browser with a
/// MIME-type/Content-Type header based on its extension. Will service from the
/// current directory.
/// </para><para>
/// </para><para>
/// </para></summary>
/// <remarks>
/// </remarks>
val browse_file : filename:string -> WebPart
val browse_file : file_name:string -> WebPart

/// <summary><para>
/// 'browse' the file in the sense that the contents of the file are sent based on the
/// request's Url property. Will serve from the current directory.
/// </para><para>
/// </para><para>
/// request's Url property. Will serve from the passed root path/directory.
/// </para></summary>
/// <remarks>
/// The current implementation doesn't take kindly to relative paths.
/// </remarks>
val browse : WebPart
val browse : root_path:string -> WebPart

/// <summary><para>
/// Serve a 'file browser' for a directory
/// </para><para>
/// </para><para>
/// 'browse' the file in the sense that the contents of the file are sent based on the
/// request's Url property. Will serve from the current as configured in directory.
/// Suave's runtime.
/// </para></summary>
val browse' : WebPart

/// <summary><para>
/// Serve a 'file browser' for a root_path
/// </para></summary>
/// <remarks>
/// The current implementation doesn't take kindly to relative paths.
/// </remarks>
val dir : WebPart
val dir : root_path:string -> WebPart

/// <summary><para>
/// Serve a 'file browser' for the current directory
/// </para></summary>
val dir' : WebPart

module Embedded =

Expand Down
Binary file removed tools/http-headers-status-v3.png
Binary file not shown.

0 comments on commit 7af1401

Please sign in to comment.