I am creating a simple crud webapp using gin library.I have a route setup which checks for a param id
and if its add
a admin-employee-add.html
should be rendered ,else return the employee with the id if exists When i am rendering a template of admin-employee-add.html
the error message of 404 not found
gets leaked into it. Here is a snapshot
admin-employee-add.html
{{template "pageStart.html" .}}
<form class="form-horizontal admin-employee">
<div class="row form-group">
<label for="employeeNumber" class="col-lg-2 control-label text-right">Employee #</label>
<div class="col-lg-4">
<span>new</span>
</div>
<label for="status" class="col-lg-2 control-label text-right">Status</label>
<div class="col-lg-4">
<span>new</span>
</div>
</div>
<div class="row form-group">
<label for="firstName" class="col-lg-2 control-label text-right">Name</label>
<div class="col-lg-2">
<input type="text" id="firstName" name="firstName" class="form-control">
</div>
<div class="col-lg-2">
<input type="text" id="lastName" name="lastName" class="form-control">
</div>
</div>
<div class="row form-group">
<label for="startDate" class="col-lg-2 control-label text-right">Start Date</label>
<div class="col-lg-2">
<input type="date" id="startDate" name="startDate" class="form-control">
</div>
<label for="pto" class="control-label col-lg-2 col-lg-offset-2 text-right">PTO</label>
<div class="col-lg-3">
<input type="number" id="pto" name="pto" class="form-control">
</div>
<div class="col-lg-1">
days
</div>
</div>
<div class="row form-group">
<label for="position" class="col-lg-2 control-label text-right">Position</label>
<div class="col-lg-2">
<select name="position" id="position" class="form-control">
<option value="CEO">CEO</option>
<option value="CTO">CTO</option>
<option value="COO">COO</option>
<option value="WorkerBee">Worker Bee</option>
</select>
</div>
</div>
<div class="col-lg-3 col-lg-offset-8">
<button type="submit" class="btn btn-lg admin-primary">Create</button>
</div>
</form>
the route which is creating an the error
r.GET("/employee/:id/", func(c *gin.Context) {
id := c.Param("id")
if id == "add" {
c.HTML(http.StatusOK, "admin-employee-add.html", nil)
}
employee, ok := employees[id]
if !ok {
c.String(http.StatusNotFound, "404 not found", nil)
} else {
c.HTML(http.StatusOK, "admin-employee-edit.html", map[string]interface{}{
"Employee": employee,
})
}
})
The error seems to occur because gin is trying to redirect /add
-> /add/
but i am already using the /add/
route in the browser.
the debug logs of gin
[GIN-debug] GET /login --> main.registerRoutes.func2 (3 handlers)
[GIN-debug] GET /employee/:id/ --> main.registerRoutes.func3 (3 handlers)
[GIN-debug] GET /employee/:id/vacation --> main.registerRoutes.func4 (3 handlers)
[GIN-debug] GET /admin/ --> main.registerRoutes.func5 (4 handlers)
[GIN-debug] Listening and serving HTTP on :3000
[GIN-debug] [WARNING] Headers were already written. Wanted to override status code 200 with
404
[GIN] 2016/05/01 - 14:12:13 | 404 | 1.101426ms | 127.0.0.1 | GET /employee/add/
I tried changing the route to /:id
then the error showed.
redirecting request 301: /employee/add/ --> /employee/add
[GIN-debug] [WARNING] Headers were already written. Wanted to override status code 200 with
404
NOTE : This error can be easily resolved by adding a return
at the end of the if id == "add"
. but this pattern makes the code look less dry. This seems to be more of a httprouter
issue.
As you said, this error can easily be resolved by adding a return
at the end of if id == "add"
.
c.String
and c.HTML
use the same Context
c
. Internally they are writing to the same socket ( you can think of it as a file pointer ). Hence, if you call c.String
and then c.HTML
or vice versa, it will append the outputs in the order called.
Looking at your code, I'd assume you want to add an employee when you see /employee/add
i.e. present a html page to do that. And /employee/<something-other-than-add-as-id>
which will get that and display it - in this case html to edit the employee info.
It makes sense here to add the return after the if id == "add"
since the html generated for the two scenarios is different ( they are using different templates ). Adding a separate handler purely for /employee/add/
is another option as well.