-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathmain.go
85 lines (66 loc) · 2.4 KB
/
main.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
package main
import (
"fmt"
"io"
"net/http"
"time"
)
const (
proxyPort = 8000
servicePort = 80
)
type Proxy struct{}
func (p *Proxy) ServeHTTP(w http.ResponseWriter, req *http.Request) {
// Forward the HTTP request to the destination service.
res, duration, err := p.forwardRequest(req)
// Notify the client if there was an error while forwarding the request.
if err != nil {
http.Error(w, err.Error(), http.StatusBadGateway)
return
}
// If the request was forwarded successfully, write the response back to
// the client.
p.writeResponse(w, res)
// Print request and response statistics.
p.printStats(req, res, duration)
}
func (p *Proxy) forwardRequest(req *http.Request) (*http.Response, time.Duration, error) {
// Prepare the destination endpoint to forward the request to.
proxyUrl := fmt.Sprintf("http://127.0.0.1:%d%s", servicePort, req.RequestURI)
// Print the original URL and the proxied request URL.
fmt.Printf("Original URL: http://%s:%d%s\n", req.Host, servicePort, req.RequestURI)
fmt.Printf("Proxy URL: %s\n", proxyUrl)
// Create an HTTP client and a proxy request based on the original request.
httpClient := http.Client{}
proxyReq, err := http.NewRequest(req.Method, proxyUrl, req.Body)
// Capture the duration while making a request to the destination service.
start := time.Now()
res, err := httpClient.Do(proxyReq)
duration := time.Since(start)
// Return the response, the request duration, and the error.
return res, duration, err
}
func (p *Proxy) writeResponse(w http.ResponseWriter, res *http.Response) {
// Copy all the header values from the response.
for name, values := range res.Header {
w.Header()[name] = values
}
// Set a special header to notify that the proxy actually serviced the request.
w.Header().Set("Server", "amazing-proxy")
// Set the status code returned by the destination service.
w.WriteHeader(res.StatusCode)
// Copy the contents from the response body.
io.Copy(w, res.Body)
// Finish the request.
res.Body.Close()
}
func (p *Proxy) printStats(req *http.Request, res *http.Response, duration time.Duration) {
fmt.Printf("Request Duration: %v\n", duration)
fmt.Printf("Request Size: %d\n", req.ContentLength)
fmt.Printf("Response Size: %d\n", res.ContentLength)
fmt.Printf("Response Status: %d\n\n", res.StatusCode)
}
func main() {
// Listen on the predefined proxy port.
http.ListenAndServe(fmt.Sprintf(":%d", proxyPort), &Proxy{})
}