-
Notifications
You must be signed in to change notification settings - Fork 103
Expand file tree
/
Copy pathexample_test.go
More file actions
80 lines (68 loc) · 2.17 KB
/
example_test.go
File metadata and controls
80 lines (68 loc) · 2.17 KB
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
// Copyright 2020 Marc-Antoine Ruel. All rights reserved.
// Use of this source code is governed under the Apache License, Version 2.0
// that can be found in the LICENSE file.
package webstack_test
import (
"log"
"net"
"net/http"
"strings"
"sync"
"time"
"github.com/maruel/panicparse/v2/stack/webstack"
)
func ExampleSnapshotHandler() {
http.HandleFunc("/debug/panicparse", webstack.SnapshotHandler)
// Access as http://localhost:6060/debug/panicparse
log.Println(http.ListenAndServe("localhost:6060", nil))
}
func ExampleSnapshotHandler_complex() {
// This example does a few things:
// - Diables "augment" by default, can be enabled manually with "?augment=1".
// - Forces the "maxmem" value to reduce memory pressure in worst case.
// - Serializes handler to one at a time.
// - Throttles requests to once per second.
// - Limit request source IP to localhost and 100.64.x.x/10. (e.g.
// Tailscale).
const delay = time.Second
mu := sync.Mutex{}
var last time.Time
http.HandleFunc("/debug/panicparse", func(w http.ResponseWriter, req *http.Request) {
// Only allow requests from localhost or in the 100.64.x.x/10 IPv4 range.
ok := false
if i := strings.LastIndexByte(req.RemoteAddr, ':'); i != -1 {
switch ip := req.RemoteAddr[:i]; ip {
case "localhost", "127.0.0.1", "[::1]", "::1":
ok = true
default:
p := net.ParseIP(ip).To4()
ok = p != nil && p[0] == 100 && p[1] >= 64 && p[1] < 128
}
}
if !ok {
http.Error(w, "forbidden", http.StatusForbidden)
return
}
// Serialize the handler.
mu.Lock()
defer mu.Unlock()
// Throttle requests.
if time.Since(last) < delay {
http.Error(w, "retry later", http.StatusTooManyRequests)
return
}
// Must be called before touching req.Form.
req.ParseForm()
// Disables source scanning by default since it's heavy.
if req.FormValue("augment") == "" {
req.Form.Set("augment", "0")
}
// Reduces maximum memory usage to 32MiB (from 64MiB) for the goroutines
// snapshot.
req.Form.Set("maxmem", "33554432")
webstack.SnapshotHandler(w, req)
last = time.Now()
})
// Access as http://localhost:6060/debug/panicparse
log.Println(http.ListenAndServe("localhost:6060", nil))
}