0
votes

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.

1
Could you be more specific regarding what it is that you would like the community help with?Cninroh
@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
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. stackoverflow.com/questions/29418478/go-gin-framework-corsCninroh
have you solved this?medBouzid
@medBouzid Not really. I deployed the application using the Go http server instead of the NGINX proxy. It worked that way.Abah

1 Answers

0
votes

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

}