A RESTful Server
Let’s learn how to develop a RESTful server.
The purpose of the presented implementation is to understand how things work behind the scenes because the principles behind REST services remain the same. The logic behind each handler function is simple: read user input and decide whether the given input and HTTP method are the desired ones. The principles of each client interaction are also simple: the server should send appropriate error messages and HTTP codes back to the client so that everyone knows what really happened. Lastly, everything should be documented to communicate in a common language.
Coding example
The code of the server, which is saved as rServer.go
, is the following:
package mainimport ("encoding/json""fmt""io""log""net/http""os""time")type User struct {Username string `json:"user"`Password string `json:"password"`}
This is a structure that holds user data. The use of JSON tags is crucial.
var user User
This global variable holds user data—this is the input for the /add
, /get
, and /delete
endpoints and their simplistic implementations. As this global variable is shared by the entire program, our code is not concurrently safe, which is fine for a RESTful server used as a proof of concept.
The real-world RESTful server that is implemented in the Creating a Functional RESTful Server lesson is going to be concurrently safe.
// PORT is where the web server listens tovar PORT = ":1234"
A RESTful server is just an HTTP server, so we define the TCP port number the server listens to.
// DATA is the map that holds User recordsvar DATA = make(map[string]string)
The preceding is another global variable that contains the data of the service.
func defaultHandler(w http.ResponseWriter, r *http.Request) {log.Println("Serving:", r.URL.Path, "from", r.Host)w.WriteHeader(http.StatusNotFound)Body := "Thanks for visiting!\n"fmt.Fprintf(w, "%s", Body)}
This is the default handler. On a production server, the default handler might print instructions about the operation of the server as well as the list of available endpoints.
func timeHandler(w http.ResponseWriter, r *http.Request) {log.Println("Serving:", r.URL.Path, "from", r.Host)t := time.Now().Format(time.RFC1123)Body := "The current time is: " + t + "\n"fmt.Fprintf(w, "%s", Body)}
This is another simple handler that returns the current date and time—such simple handlers are usually used for ...
Get hands-on with 1400+ tech skills courses.