leylandski
leylandski

Reputation: 458

Why can't I write an HTTP response from a seperate package in Go?

I'm using httprouter to set up an API endpoint, but I'm having some trouble getting it to output a response correctly.

My main file as it stands:

package main

import (
    "fmt"
    "github.com/julienschmidt/httprouter"
    "infrastructure/routing"
    "log"
    "net/http"
)

func testPrint(w http.ResponseWriter, r *http.Request, p httprouter.Params) {
    fmt.Fprint(w, "Test output.")
}

func main() {

    fmt.Printf("\n************************************\n")
    fmt.Printf("MySite Application Server\n")
    fmt.Printf("Version: %s", "Unversioned Development Build\n")
    fmt.Printf("************************************\n\n")

    router := httprouter.New()

    //////Records//////
    router.GET("/test", testPrint)
    router.GET("/records", routing.RecordList)
    router.GET("/records/id/:id", routing.RecordGetById)
    router.GET("/records/name/:name", routing.RecordGetByName)
    router.GET("/records/search/*search-string", routing.RecordSearch)
    router.HEAD("/records/:id", routing.RecordGetExists)
    router.POST("/records", routing.RecordCreate)
    router.PATCH("/records", routing.RecordUpdate)
    router.PUT("/records", routing.RecordUpsert)
    router.DELETE("/records/:id", routing.RecordDelete)
    router.DELETE("/records/:id/undelete", routing.RecordUndelete)
    router.DELETE("/records/:id/purge", routing.RecordPurge)

    fmt.Printf("Listening on port 8080...\n")
    log.Fatal(http.ListenAndServe(":8080", router))

}

Most of the handler functions are located in infrastructure/routing, but this is where the problem starts. The code for routing is currently:

package routing

import (
    "fmt"
    "github.com/julienschmidt/httprouter"
    "net/http"
)

func RecordList(w http.ResponseWriter, r *http.Request, _ httprouter.Params) {
    //Returns a list of records.
    fmt.Fprint(w, "Returned a list of records.")
}

func RecordGetById(w http.ResponseWriter, r *http.Request, params httprouter.Params) {
    //Return a record with the specified ID.
    w.Write([]byte("Returned a record by its ID."))
}

func RecordGetByName(w http.ResponseWriter, r *http.Request, params httprouter.Params) {
    //Returns a record with the specified string in the name field.
    w.Write([]byte("Returned a record by its name."))
}

func RecordSearch(w http.ResponseWriter, r *http.Request, params httprouter.Params) {
    //Full text search for the search term provided.
    w.Write([]byte("Search results."))
}

func RecordGetExists(w http.ResponseWriter, r *http.Request, params httprouter.Params) {
    //Returns whether a record exists.
    w.Write([]byte("Returns whether a record exists. Should usually return 200 or 404."))
}

func RecordCreate(w http.ResponseWriter, r *http.Request, params httprouter.Params) {
    //Creates new records from JSON data in request body.
    w.Write([]byte("Creates new records."))
}

func RecordUpdate(w http.ResponseWriter, r *http.Request, params httprouter.Params) {
    //Updates records using JSON data in request body.
    w.Write([]byte("Updates existing records."))
}

func RecordUpsert(w http.ResponseWriter, r *http.Request, params httprouter.Params) {
    //Updates existing records and creates new ones using JSON data in request body.
    w.Write([]byte("Upserts records."))
}

func RecordDelete(w http.ResponseWriter, r *http.Request, params httprouter.Params) {
    //Marks the record with the specified ID as deleted.
    w.Write([]byte("Marks records as deleted."))
}

func RecordUndelete(w http.ResponseWriter, r *http.Request, params httprouter.Params) {
    //Marks the record with the specified ID as undeleted.
    w.Write([]byte("Marks deleted records as undeleted."))
}

func RecordPurge(w http.ResponseWriter, r *http.Request, params httprouter.Params) {
    //Permanently deletes the record with the specified ID.
    w.Write([]byte("Permanently deletes record with given ID."))
}

When I make a request to localhost:8080/test, it calls the handler function in the main package and prints "Test output.". But any of the other defined URLs return a 200 OK status code and an empty (0 bytes) response body instead of the expected text.

I'm fairly sure this is something to do with the ResponseWriter object being passed through but I can't figure out why it works for one function in the same package but not another function in a different package, even though both functions have a copy of the writer passed through. I've tried a few different ways of writing including fmt.FPrintf, io.WriteString, and w.Write, to no avail.

Upvotes: 0

Views: 178

Answers (1)

leylandski
leylandski

Reputation: 458

Well, as it turns out when I was building my code for whatever reason it wasn't keeping the object files updated. I've been using LiteIDE for a while and this is the first time clicking Build on all relevant packages individually hasn't worked.

I cleaned it and then used Build All, now it works.

Upvotes: 1

Related Questions