0

I have looked at the similar questions here related to CORS issues with Gin and Tus; none addresses the problem I am currently having.

The current implementation works with the standard net/http package by adding a small wrapper.


// The wrapping function
func enableCors(w *http.ResponseWriter) {
    (*w).Header().Set("Access-Control-Allow-Origin", "*")
}


// Simplified version of the code
composer := tusd.NewStoreComposer()
    store.UseIn(composer)

    handler, err := tusd.NewHandler(tusd.Config{
        BasePath:              "/files/",
        StoreComposer:         composer,
        NotifyCompleteUploads: true,
    })

    if err != nil {
        panic(fmt.Errorf("Unable to create handler %s", err))
    }

    go func() {
        for {
            fmt.Println("Waiting for upload to complete")
            event := <-handler.CompleteUploads
            fmt.Printf("Uploads %s finished\n", event.Upload.Storage)
        }
    }()

    http.Handle("/files/", func(next http.Handler) http.Handler {
        return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
            enableCors(&w)
            next.ServeHTTP(w, r)
        })
    }(http.StripPrefix("/files/", handler)))


    err = http.ListenAndServe(":8080", nil)
    if err != nil {
        panic(fmt.Errorf("unable to listen: %s", err))
    }
    

Here is what I have tried with Gin. I wrapped the handler in gin.WrapH(). I added the default Gin CORS library middleware, and still, the cors error refused to go away. This is not working

func TusHandler() http.Handler {

    store := filestore.FileStore{
        Path: "./uploads",
    }

    composer := tusd.NewStoreComposer()
    store.UseIn(composer)

    handler, err := tusd.NewHandler(tusd.Config{
        BasePath:              "/upload/tus/",
        StoreComposer:         composer,
        NotifyCompleteUploads: true,
    })

    if err != nil {
        panic(err) // This is to simplify the code
    }

    return handler

}

// The routing
import "github.com/gin-contrib/cors"

router :=  gin.Default()
router.Use(cors.Default())
router.GET("/upload/tuts", gin.WrapH(uploader.TusHandler()))

Here is my browser output. When I tried to upload a file pointing to the Gin version

The gin integration keep showing CORS error. That is the problem I am trying to solve.

Abah
  • 1
  • 1
  • 3
  • Could you be more specific regarding what it is that you would like the community help with? – Cninroh Sep 21 '20 at 08:58
  • @Cninroh Thank you for responding. I am trying to integrate with Gin and the CORS error keep coming up. The image I attached shows the error message. I am looking for a solution to the CORS problem. – Abah Sep 21 '20 at 11:35
  • I am not a golang expert, but since its not complaining about the origin, but the header specifically, it might have by default disabled HEAD requests. You should probably extend the CORS with additional permissions. https://stackoverflow.com/questions/29418478/go-gin-framework-cors – Cninroh Sep 24 '20 at 14:15
  • have you solved this? – medBouzid Jan 16 '21 at 15:20
  • @medBouzid Not really. I deployed the application using the Go http server instead of the NGINX proxy. It worked that way. – Abah Jan 18 '21 at 08:04

2 Answers2

2

tus.io is sending a bunch of headers to the server so you need to add these headers to your cors config. The error message is saying that a header called tus-resumable is not allowed, you need to add this header along with other headers tus.io is sending. And expose some headers so tus-js-client can read it.

router.Use(cors.New(cors.Config{
        AllowAllOrigins: true,
        // AllowOrigins:  []string{"http://example.com"},
        AllowMethods:  []string{"GET", "POST", "PUT", "PATCH", "DELETE", "HEAD", "OPTIONS"},
        AllowHeaders:  []string{"Authorization", "X-Requested-With", "X-Request-ID", "X-HTTP-Method-Override", "Upload-Length", "Upload-Offset", "Tus-Resumable", "Upload-Metadata", "Upload-Defer-Length", "Upload-Concat", "User-Agent", "Referrer", "Origin", "Content-Type", "Content-Length"},
        ExposeHeaders: []string{"Upload-Offset", "Location", "Upload-Length", "Tus-Version", "Tus-Resumable", "Tus-Max-Size", "Tus-Extension", "Upload-Metadata", "Upload-Defer-Length", "Upload-Concat", "Location", "Upload-Offset", "Upload-Length"},
    }))

Also if you already have a running app, you can use NewUnroutedHandler instead of NewHandler.

handler := dTusHandler()
router.POST("/files/", gin.WrapF(handler.PostFile))
router.HEAD("/files/:id", gin.WrapF(handler.HeadFile))
router.PATCH("/files/:id", gin.WrapF(handler.PatchFile))
router.GET("/files/:id", gin.WrapF(handler.GetFile))

Here's dTusHandler func:

func dTusHandler() *tusd.UnroutedHandler {
    store := filestore.FileStore{
        Path: "./uploads",
    }

    composer := tusd.NewStoreComposer()
    store.UseIn(composer)

    h, err := tusd.NewUnroutedHandler(tusd.Config{
        BasePath:              "/files/",
        StoreComposer:         composer,
        NotifyCompleteUploads: true,
    })

    if err != nil {
        panic(fmt.Errorf("Unable to create handler: %s", err))
    }

    go func() {
        for {
            event := <-h.CompleteUploads
            fmt.Printf("Upload %s finished\n", event.Upload.ID)
        }
    }()

    return h

}
ginad
  • 1,863
  • 2
  • 27
  • 42
0

In asp net 6 I fixed this with:

// Default CORS Policy
builder.Services.AddCors(options =>
{
    options.AddDefaultPolicy(
        policyBuilder =>
        {
            policyBuilder.AllowAnyOrigin()
                .AllowAnyHeader()
                .AllowAnyMethod()
        .WithExposedHeaders(CorsHelper.GetExposedHeaders());
        });
});
Edi
  • 1,900
  • 18
  • 27