gogo-httpimagekitgo-context

Imagekit - Golang | How to use Context


Im trying to upload images from my Golang backend to imagekit via the imagekit sdk. Im facing problems with understanding what the context api is used for.

Currently I don't really use context in my backend and pass all dependencies in the constructor.

Im running into an exception:

2023/01/04 09:53:56 http: panic serving 127.0.0.1:50780: runtime error: invalid memory address or nil pointer dereference
goroutine 20 [running]:
net/http.(*conn).serve.func1()
        /usr/local/Cellar/go/1.19.3/libexec/src/net/http/server.go:1850 +0xbf
panic({0x1005836c0, 0x10092b820})
        /usr/local/Cellar/go/1.19.3/libexec/src/runtime/panic.go:890 +0x262
github.com/bolzfieber/bolzfieber-backend/internal/controllers.PitchesController.CreateAndUpdatePitch({0xc0001f7530?, 0x0?}, {0x1006a94e8, 0xc0000ca000}, 0xc0000d4000)
        /Users/pbahr/DEV/Bolzfieber/BE/bolzfieber-backend/internal/controllers/pitches.go:91 +0x5ae
net/http.HandlerFunc.ServeHTTP(0x100580980?, {0x1006a94e8?, 0xc0000ca000?}, 0xc0000be048?)
        /usr/local/Cellar/go/1.19.3/libexec/src/net/http/server.go:2109 +0x2f
github.com/go-chi/chi/v5.(*Mux).routeHTTP(0xc00007c600, {0x1006a94e8, 0xc0000ca000}, 0xc0000d4000)
        /Users/pbahr/go/pkg/mod/github.com/go-chi/chi/v5@v5.0.7/mux.go:442 +0x216
net/http.HandlerFunc.ServeHTTP(0xc0000b00c0?, {0x1006a94e8?, 0xc0000ca000?}, 0xc00011b918?)
        /usr/local/Cellar/go/1.19.3/libexec/src/net/http/server.go:2109 +0x2f
github.com/go-chi/chi/v5.(*Mux).ServeHTTP(0xc00007c600, {0x1006a94e8, 0xc0000ca000}, 0xc0000d4000)
        /Users/pbahr/go/pkg/mod/github.com/go-chi/chi/v5@v5.0.7/mux.go:71 +0x355
github.com/go-chi/chi/v5.(*Mux).Mount.func1({0x1006a94e8, 0xc0000ca000}, 0xc0000d4000)
        /Users/pbahr/go/pkg/mod/github.com/go-chi/chi/v5@v5.0.7/mux.go:314 +0x19c
net/http.HandlerFunc.ServeHTTP(0x100580980?, {0x1006a94e8?, 0xc0000ca000?}, 0xc0000aa005?)
        /usr/local/Cellar/go/1.19.3/libexec/src/net/http/server.go:2109 +0x2f
github.com/go-chi/chi/v5.(*Mux).routeHTTP(0xc00007c420, {0x1006a94e8, 0xc0000ca000}, 0xc0000d4000)
        /Users/pbahr/go/pkg/mod/github.com/go-chi/chi/v5@v5.0.7/mux.go:442 +0x216
net/http.HandlerFunc.ServeHTTP(0x1006a9bf8?, {0x1006a94e8?, 0xc0000ca000?}, 0x10092b640?)
        /usr/local/Cellar/go/1.19.3/libexec/src/net/http/server.go:2109 +0x2f
github.com/go-chi/chi/v5.(*Mux).ServeHTTP(0xc00007c420, {0x1006a94e8, 0xc0000ca000}, 0xc000332000)
        /Users/pbahr/go/pkg/mod/github.com/go-chi/chi/v5@v5.0.7/mux.go:88 +0x310
net/http.serverHandler.ServeHTTP({0x1006a84d0?}, {0x1006a94e8, 0xc0000ca000}, 0xc000332000)
        /usr/local/Cellar/go/1.19.3/libexec/src/net/http/server.go:2947 +0x30c
net/http.(*conn).serve(0xc00032c000, {0x1006a9ca0, 0xc000318270})
        /usr/local/Cellar/go/1.19.3/libexec/src/net/http/server.go:1991 +0x607
created by net/http.(*Server).Serve
        /usr/local/Cellar/go/1.19.3/libexec/src/net/http/server.go:3102 +0x4db

Whereas line 91 is the upload line of the imagekit. So I suppose the null pointer is the context.

My current approach looks like this:

func (c PitchesController) CreateAndUpdatePitch(w http.ResponseWriter, r *http.Request) {
    var pitchUpload models.PitchUpload
    err := json.NewDecoder(r.Body).Decode(&pitchUpload)

    if err != nil {
        fmt.Printf("Error: %v\n", err)
        utils.RespondWithError(w, http.StatusBadRequest, "Bad request")
        return
    }

    var pitch = models.Pitch{
        Name:            pitchUpload.Name,
        Address:         pitchUpload.Address,
        Author:          pitchUpload.Author,
        PitchType:       pitchUpload.PitchType,
        PitchSize:       pitchUpload.PitchSize,
        GoalSize:        pitchUpload.GoalSize,
        GoalType:        pitchUpload.GoalType,
        LocationScopeId: pitchUpload.LocationScopeId,
        Coordinates:     pitchUpload.Coordinates,
        Rating:          pitchUpload.Rating,
    }

    for i, image := range pitchUpload.Images {
        fmt.Printf("pitch: %v\n", pitchUpload.Name)
        response, uploadErr := c.Ik.Uploader.Upload(r.Context(), image, uploader.UploadParam{
            FileName:          pitchUpload.Name + "_" + string(rune(i)),
            UseUniqueFileName: newTrue(),
            Tags:              "pitch",
            Folder:            "/pitches/" + pitchUpload.Name,
        })

        if uploadErr != nil {
            fmt.Printf("Error: %v\n", uploadErr)
            utils.RespondWithError(w, http.StatusBadRequest, "Bad request")
            return
        }

        pitch.Images = append(pitch.Images, models.PitchImage{FileUrl: response.Data.Url})
    }

    c.Db.Save(&pitch)

    utils.RespondWithJSON(w, http.StatusCreated, "Created successfully")
}

Following steps apply:

  1. receiving post body and decode to valid go struct
  2. creating a new struct that later should be saved to db
  3. looping over the images of the struct (base64 strings)
  4. for each image upload to imagekit
  5. append imagekit responses to struct that should be saved to db
  6. save to db

Solution

  • Getting a nil pointer at this line probably means c.Ik. or c.Ik.Uploader. or r. or uploader. are nils. We can easily remove some of suspects.