1// Copyright 2012 The Go Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style
3// license that can be found in the LICENSE file.
4
5package http_test
6
7import (
8	"context"
9	"fmt"
10	"io"
11	"log"
12	"net/http"
13	"os"
14	"os/signal"
15)
16
17func ExampleHijacker() {
18	http.HandleFunc("/hijack", func(w http.ResponseWriter, r *http.Request) {
19		hj, ok := w.(http.Hijacker)
20		if !ok {
21			http.Error(w, "webserver doesn't support hijacking", http.StatusInternalServerError)
22			return
23		}
24		conn, bufrw, err := hj.Hijack()
25		if err != nil {
26			http.Error(w, err.Error(), http.StatusInternalServerError)
27			return
28		}
29		// Don't forget to close the connection:
30		defer conn.Close()
31		bufrw.WriteString("Now we're speaking raw TCP. Say hi: ")
32		bufrw.Flush()
33		s, err := bufrw.ReadString('\n')
34		if err != nil {
35			log.Printf("error reading string: %v", err)
36			return
37		}
38		fmt.Fprintf(bufrw, "You said: %q\nBye.\n", s)
39		bufrw.Flush()
40	})
41}
42
43func ExampleGet() {
44	res, err := http.Get("http://www.google.com/robots.txt")
45	if err != nil {
46		log.Fatal(err)
47	}
48	body, err := io.ReadAll(res.Body)
49	res.Body.Close()
50	if res.StatusCode > 299 {
51		log.Fatalf("Response failed with status code: %d and\nbody: %s\n", res.StatusCode, body)
52	}
53	if err != nil {
54		log.Fatal(err)
55	}
56	fmt.Printf("%s", body)
57}
58
59func ExampleFileServer() {
60	// Simple static webserver:
61	log.Fatal(http.ListenAndServe(":8080", http.FileServer(http.Dir("/usr/share/doc"))))
62}
63
64func ExampleFileServer_stripPrefix() {
65	// To serve a directory on disk (/tmp) under an alternate URL
66	// path (/tmpfiles/), use StripPrefix to modify the request
67	// URL's path before the FileServer sees it:
68	http.Handle("/tmpfiles/", http.StripPrefix("/tmpfiles/", http.FileServer(http.Dir("/tmp"))))
69}
70
71func ExampleStripPrefix() {
72	// To serve a directory on disk (/tmp) under an alternate URL
73	// path (/tmpfiles/), use StripPrefix to modify the request
74	// URL's path before the FileServer sees it:
75	http.Handle("/tmpfiles/", http.StripPrefix("/tmpfiles/", http.FileServer(http.Dir("/tmp"))))
76}
77
78type apiHandler struct{}
79
80func (apiHandler) ServeHTTP(http.ResponseWriter, *http.Request) {}
81
82func ExampleServeMux_Handle() {
83	mux := http.NewServeMux()
84	mux.Handle("/api/", apiHandler{})
85	mux.HandleFunc("/", func(w http.ResponseWriter, req *http.Request) {
86		// The "/" pattern matches everything, so we need to check
87		// that we're at the root here.
88		if req.URL.Path != "/" {
89			http.NotFound(w, req)
90			return
91		}
92		fmt.Fprintf(w, "Welcome to the home page!")
93	})
94}
95
96// HTTP Trailers are a set of key/value pairs like headers that come
97// after the HTTP response, instead of before.
98func ExampleResponseWriter_trailers() {
99	mux := http.NewServeMux()
100	mux.HandleFunc("/sendstrailers", func(w http.ResponseWriter, req *http.Request) {
101		// Before any call to WriteHeader or Write, declare
102		// the trailers you will set during the HTTP
103		// response. These three headers are actually sent in
104		// the trailer.
105		w.Header().Set("Trailer", "AtEnd1, AtEnd2")
106		w.Header().Add("Trailer", "AtEnd3")
107
108		w.Header().Set("Content-Type", "text/plain; charset=utf-8") // normal header
109		w.WriteHeader(http.StatusOK)
110
111		w.Header().Set("AtEnd1", "value 1")
112		io.WriteString(w, "This HTTP response has both headers before this text and trailers at the end.\n")
113		w.Header().Set("AtEnd2", "value 2")
114		w.Header().Set("AtEnd3", "value 3") // These will appear as trailers.
115	})
116}
117
118func ExampleServer_Shutdown() {
119	var srv http.Server
120
121	idleConnsClosed := make(chan struct{})
122	go func() {
123		sigint := make(chan os.Signal, 1)
124		signal.Notify(sigint, os.Interrupt)
125		<-sigint
126
127		// We received an interrupt signal, shut down.
128		if err := srv.Shutdown(context.Background()); err != nil {
129			// Error from closing listeners, or context timeout:
130			log.Printf("HTTP server Shutdown: %v", err)
131		}
132		close(idleConnsClosed)
133	}()
134
135	if err := srv.ListenAndServe(); err != http.ErrServerClosed {
136		// Error starting or closing listener:
137		log.Fatalf("HTTP server ListenAndServe: %v", err)
138	}
139
140	<-idleConnsClosed
141}
142
143func ExampleListenAndServeTLS() {
144	http.HandleFunc("/", func(w http.ResponseWriter, req *http.Request) {
145		io.WriteString(w, "Hello, TLS!\n")
146	})
147
148	// One can use generate_cert.go in crypto/tls to generate cert.pem and key.pem.
149	log.Printf("About to listen on 8443. Go to https://127.0.0.1:8443/")
150	err := http.ListenAndServeTLS(":8443", "cert.pem", "key.pem", nil)
151	log.Fatal(err)
152}
153
154func ExampleListenAndServe() {
155	// Hello world, the web server
156
157	helloHandler := func(w http.ResponseWriter, req *http.Request) {
158		io.WriteString(w, "Hello, world!\n")
159	}
160
161	http.HandleFunc("/hello", helloHandler)
162	log.Fatal(http.ListenAndServe(":8080", nil))
163}
164
165func ExampleHandleFunc() {
166	h1 := func(w http.ResponseWriter, _ *http.Request) {
167		io.WriteString(w, "Hello from a HandleFunc #1!\n")
168	}
169	h2 := func(w http.ResponseWriter, _ *http.Request) {
170		io.WriteString(w, "Hello from a HandleFunc #2!\n")
171	}
172
173	http.HandleFunc("/", h1)
174	http.HandleFunc("/endpoint", h2)
175
176	log.Fatal(http.ListenAndServe(":8080", nil))
177}
178
179func newPeopleHandler() http.Handler {
180	return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
181		fmt.Fprintln(w, "This is the people handler.")
182	})
183}
184
185func ExampleNotFoundHandler() {
186	mux := http.NewServeMux()
187
188	// Create sample handler to returns 404
189	mux.Handle("/resources", http.NotFoundHandler())
190
191	// Create sample handler that returns 200
192	mux.Handle("/resources/people/", newPeopleHandler())
193
194	log.Fatal(http.ListenAndServe(":8080", mux))
195}
196