(September 2019)
A client makes a request to a server. The server sends a response.
The HTTP protocol specifies that request/response exchange for web traffic. HTTP is a stateless, application-level protocol.
An client HTTP request consists of a few lines of text:
Like:
GET / HTTP/1.1
Host: example.org
User-Agent: curl/7.64.0
Accept: */*
…
The request line has:
The methods GET, HEAD, OPTIONS, and TRACE are considered “safe” because they’re not supposed to change anything on the server. The methods POST, PUT, and DELETE change stuff on the server, so they’re not “safe”.
A method is idempotent if calling it two or more times results in the same state as calling it once.
PUT and DELETE are idempotent but not safe. POST is not safe, and may or may not be idempotent, depending on what the server does.
The request headers are colon-separated name-value pairs. RFC 7231 describes a core set of header fields, but arbitrary custom headers abound. Common headers include “Content-Length” to specify the length of the body, “Referrer” to name the previous page that linked to this URI, and the client “User-Agent”.
A server HTTP response has:
HTTP/1.1 200 OK
Server: nginx/1.12.2
Date: Sat, 14 Sep 2019 01:57:22 GMT
Content-Type: text/html; charset=UTF-8
Content-Length: 7574
Last-Modified: Tue, 30 Apr 2019 21:29:18 GMT
Connection: keep-alive
ETag: "5cc8be2e-1d9b"
Accept-Ranges: bytes
<!DOCTYPE html>
…
The status line of the response gives status code (“200”) and a reason phrase (“OK”).
Various response headers follow the status line, including ones like “Set-Cookie”.
A URI:
<schema name>:<hierarchical parts>[?<query>][#<fragment>]
https://example.com/foo/bar.html?q1=bam&q2=bat#biff
While earlier versions of HTTP are text-based, HTTP/2 is a binary protocol. HTTP/2 is more efficient in terms of overhead, and designed for multiplexed communication between client and server. Go 1.6+ defaults to HTTP/2 for HTTPS connections.
A web app:
receives an HTTP request from a client
parses the request and does any work required
generates HTML and returns an HTTP response to the client
A handler processes the client request, and call the template engine. In MVC parlance, the handler acts as both the controller and the model.
A template engine generates HTML for the response.
In a Go web app, the handler name generally corresponds to the hierarchical parts of the URI — sometimes with the first part of the URI hierarchy corresponding to a Go module, and the next part corresponding to a submodule, and the final leafe corresponding to the handler.
When the server receives a request, the multiplexer inspects the request’s URI, and dispatches the request to the matching handler.
func main() {
mux := http.NewServeMux()
files := http.FileServer(http.Dir("/public"))
mux.Handle("/static/", http.StripPrefix("/static/", files))
mux.HandleFunc("/", index)
server := &http.Server{
Addr: "0.0.0.0:8080",
Handler: mux,
}
server.ListenAndServe()
}
package main
import (
"html/template"
"log"
"net/http"
)
func handler(w http.ResponseWriter, r *http.Request) {
tmpl, err := template.New("hello").Parse("Hello, {{.}}!")
if err != nil {
log.Println(err)
}
err = tmpl.Execute(w, r.URL.Path[1:])
if err != nil {
log.Println(err)
}
}
func main() {
http.HandleFunc("/", handler)
http.ListenAndServe(":8080", nil)
}