2
votes

I am currently developing a web api using f#, I am totally new to it as I am coming from a c# background, and I would like to fetch datas from a reactjs application. But I need to allow cors on my f# webapi. I am totally lost when I am trying to allow cors. So far, I added :

member this.ConfigureServices(services: IServiceCollection) =
    services.AddCors() |> ignore

and I have tried to add

app.UseCors() |> ignore

to the configure member, but I don't understand how to implement this method to allow cors in my application. I have also tried to add

[<EnableCors("...")>]

on my controller but I don't know what to put inside it

Any help would be very appreciate

Edit 1: So far here is what I have :

module ConfigurationCors =
    let ConfigureCors(corsBuilder: CorsPolicyBuilder): unit =        
        corsBuilder.AllowAnyOrigin()
                    .AllowAnyHeader()
                    .AllowAnyMethod()
                    .AllowCredentials() |> ignore

open ConfigurationCors

type Startup private () =
    new (configuration: IConfiguration) as this =
        Startup() then
        this.Configuration <- configuration 

    // This method gets called by the runtime. Use this method to add services to the container.
    member this.ConfigureServices(services: IServiceCollection) =
        // Add framework services.
        services.AddCors() |> ignore


services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_1) |> ignore


// This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
member this.Configure(app: IApplicationBuilder, env: IHostingEnvironment) =
    if (env.IsDevelopment()) then
        app.UseDeveloperExceptionPage() |> ignore
    else
        app.UseHsts() |> ignore
    app.UseHttpsRedirection() |> ignore
    app.UseMvc() |> ignore
    app.UseCors(Action<CorsPolicyBuilder> ConfigureCors) |> ignore

member val Configuration : IConfiguration = null with get, set

I have instanciate a module and a function inside it that I am passing to UseCors but it seems it's not working, is it the good way ? If someone has a hint and could help me.

Here is my fetch method in my react app :

 fetch('https://localhost:44323/api/values')
    .then(response => response.json())
    .then(data => {
      console.log(data)
    })
1
What library are you using? That looks like Giraffe, but is it Giraffe or something else? - rmunn
I am not using any library, just the defaut asp net f# project - Lucas Tambarin

1 Answers

0
votes

According to the MSDN doc, I suspect you should call UseCors middleware before UseMvc:

app.UseCors(Action<CorsPolicyBuilder> ConfigureCors)
   .UseMvc()
   .UseHttpsRedirection()

Below is my first answer, so I'd like to leave it as a general solution to server-side CORS.

To allow CORS on the server side, you'll have to set the response's headers "Access-Control-Allow-Origin" to "*" (or limit to a set of allowed origins).

Here is a barebone HttpListener that sets the headers to HttpListenerResponse:

module Server

open System
open System.Net

type HttpHandler = (HttpListenerRequest -> HttpListenerResponse -> Async<unit>)

type HttpListener with
    static member Run (url: string, handler: HttpHandler) =
        let listener = new HttpListener ()
        listener.Prefixes.Add url
        listener.Start ()
        let asynctask = Async.FromBeginEnd(listener.BeginGetContext, listener.EndGetContext)
        async {
            while true do
                let! ctx = asynctask
                // Add the headers here
                ctx.Response.AddHeader ("Access-Control-Allow-Origin", "*")
                Async.Start (handler ctx.Request ctx.Response)
        } |> Async.Start
        listener

let run port = 
    HttpListener.Run ("http://localhost" + port + "/", fun req res ->
        async {
            let out = Text.Encoding.ASCII.GetBytes "Hello, Mars!"
            res.OutputStream.Write (out, 0, out.Length)
            res.OutputStream.Close()
        }
    ) |> ignore
    printfn "Running server on localhost:%s" port
    Console.Read () |> ignore

// Main.fs

open Server

[<EntryPoint>]
let main argv =
    Server.run ":3000"
    0

If you run a curl client with curl http://localhost:3000 -v you should be able to inspect the CORS headers in the response.