Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add an API for CORS handling in Sitelets #999

Closed
Tarmil opened this issue Aug 1, 2018 · 1 comment
Closed

Add an API for CORS handling in Sitelets #999

Tarmil opened this issue Aug 1, 2018 · 1 comment

Comments

@Tarmil
Copy link
Member

Tarmil commented Aug 1, 2018

Remoting already handles CORS; we need to add an API to indicate that a Sitelet endpoint should handle CORS. Maybe with a [<Cors>] attribute on the endpoint?

Requested on the forums.

@Tarmil Tarmil self-assigned this Aug 1, 2018
@Tarmil Tarmil added this to next minor in Releases Aug 1, 2018
@Tarmil
Copy link
Member Author

Tarmil commented Sep 19, 2018

After looking in more detail into CORS, this is what I now believe would be a good API:

/// Use as an endpoint to indicate that it must check for Cross-Origin Resource Sharing headers.
/// In addition to matching the same endpoints as 'EndPoint does, this also matches preflight OPTIONS requests.
/// The corresponding Content should use Content.Cors.
type Cors<'EndPoint> =
    internal {
        DefaultAllows : CorsAllows
        /// If None, then this is a preflight OPTIONS request.
        EndPoint : option<'EndPoint>
    }

/// Indicates the "Access-Control-Xyz" headers to send.
and CorsAllows =
    {
        Origins : seq<string>
        Methods : seq<string>
        Headers : seq<string>
        ExposeHeaders : seq<string>
        MaxAge : option<int>
        Credentials : bool
    }

module Content =

    /// Respond to a Cross-Origin checked request.
    val Cors : Cors<'EndPoint>
            -> (CorsAllows -> CorsAllows)
            -> ('EndPoint -> Async<Content<'OuterEndPoint>>)
            -> Async<Content<'OuterEndPoint>>

Example use:

type ApiEndPoint =
    | [<EndPoint "GET /item">] GetItem of int
    | [<EndPoint "POST /item"; Json "data">] PostItem of data: Data
    | [<EndPoint "PUT /item"; Json "data">] PutItem of data: Data

type MainEndPoint =
    | [<EndPoint "GET /">] Home
    | [<EndPoint "/">] Api of Cors<ApiEndPoint>

let Website = Application.MultiPage (fun ctx endpoint ->
    match endpoint with
    | Home -> // ...
    | Api cors ->
        Content.Cors cors
        <| fun allows -> // [1]
            { allows with
                Origins = ["*"]
                Headers = ["Content-Type"; "Authorization"] }
        <| function
            | GetItem it -> // ...
            | PostItem it -> // ...
            | PutItem it -> // ...
)

[1]: The allows passed here by Content.Cors is a record of empty values, except for Methods which is inferred from the router to be ["GET"; "POST"; "PUT"].

@Tarmil Tarmil closed this as completed in 167ec73 Sep 19, 2018
@Jand42 Jand42 removed this from next minor in Releases Oct 26, 2018
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

2 participants