Go chi.URLParam returning empty string

196 views Asked by At

I'm new to Go so I'm trying to build a simple CRUD API using Chi. In the GetById handler I'm using chi.URLParam() method to retrieve data from the URL, but this method is returning an empty string "". Check the code:

func GetBookByIDHandler(w http.ResponseWriter, r *http.Request) {
    db, err := repository.OpenConnection()
    if err != nil {
        http.Error(w, err.Error(), http.StatusInternalServerError)
        log.Printf("Error while opening connection: %v", err)
        return
    }
    defer db.Close()

    repo := repository.NewBookSQLRepository(db)
    useCase := usecases.NewFindBookByIDUseCase(repo)

    idParam := chi.URLParam(r, "id")
    //idParams = ""

    var input usecases.FindBookByIDInput
    input.ID = idParam

    output, err := useCase.FindBookByID(input)
    if err != nil {
        http.Error(w, err.Error(), http.StatusInternalServerError)
        log.Printf("Error while getting book by id: %v", err)
        return
    }

    w.WriteHeader(http.StatusOK)
    w.Header().Set("Content-Type", "application/json")
    json.NewEncoder(w).Encode(output)
}

My router is built as follows:

    r := chi.NewRouter()
    r.Get("/books", handlers.GetAllBooksHandler)
    r.Get("/books/{id}", handlers.GetBookByIDHandler)
    r.Post("/books", handlers.CreateBookHandler)

I'm using Insomnia for the HTTP requests, in the following URL: http://localhost:8080/books/10

I already tried to make the request passing query params as "?id=10" but it did not work.

1

There are 1 answers

0
user1792794 On

I'm having the exact same issue and there's no answers for me, but I do I have a workaround which extracts the id in the conventional way, below is the working version of your code:

func GetBookByIDHandler(w http.ResponseWriter, r *http.Request) {
    db, err := repository.OpenConnection()
    if err != nil {
        http.Error(w, err.Error(), http.StatusInternalServerError)
        log.Printf("Error while opening connection: %v", err)
        return
    }
    defer db.Close()

    repo := repository.NewBookSQLRepository(db)
    useCase := usecases.NewFindBookByIDUseCase(repo)

    // Split the URL path and extract the book id
    parts := strings.Split(r.URL.Path, "/")
    if len(parts) < 2 {
        logger.Error(fmt.Sprintf("GetBookByID, Book ID not found"))
        WriteJSON(w, http.StatusBadRequest, models.Response[any]{
            Success: false,
            Message: fmt.Sprintf("Book ID not found"),
        })
        return
    }

    idParams := parts[2]

    // Assuming your book id is defined as integer in your database
    id, err := strconv.Atoi(idParams)
    if err != nil {
        logger.Error(fmt.Sprintf("GetBookByID, invalid ID: %s", id))
        WriteJSON(w, http.StatusBadRequest, models.Response[any]{
            Success: false,
            Message: fmt.Sprintf("invalid ID: %s", id),
        })
        return
    }

    var input usecases.FindBookByIDInput
    input.ID = id

    output, err := useCase.FindBookByID(input)
    if err != nil {
        http.Error(w, err.Error(), http.StatusInternalServerError)
        log.Printf("Error while getting book by id: %v", err)
        return
    }

    w.WriteHeader(http.StatusOK)
    w.Header().Set("Content-Type", "application/json")
    json.NewEncoder(w).Encode(output)
   }
}