[mirror] Scalable static site server for Git forges (like GitHub Pages)
1package main
2
3import (
4 "archive/tar"
5 "bytes"
6 "flag"
7 "fmt"
8 "io"
9 "net/http"
10 "sync"
11 "time"
12)
13
14func makeInit() []byte {
15 writer := bytes.NewBuffer(nil)
16 archive := tar.NewWriter(writer)
17 archive.WriteHeader(&tar.Header{
18 Typeflag: tar.TypeReg,
19 Name: "index.html",
20 })
21 archive.Write([]byte{})
22 archive.Flush()
23 return writer.Bytes()
24}
25
26func initSite() {
27 req, err := http.NewRequest(http.MethodPut, "http://localhost:3000",
28 bytes.NewReader(makeInit()))
29 if err != nil {
30 panic(err)
31 }
32
33 req.Header.Add("Content-Type", "application/x-tar")
34 resp, err := http.DefaultClient.Do(req)
35 if err != nil {
36 panic(err)
37 }
38 defer resp.Body.Close()
39}
40
41func makePatch(n int) []byte {
42 writer := bytes.NewBuffer(nil)
43 archive := tar.NewWriter(writer)
44 archive.WriteHeader(&tar.Header{
45 Typeflag: tar.TypeReg,
46 Name: fmt.Sprintf("%d.txt", n),
47 })
48 archive.Write([]byte{})
49 archive.Flush()
50 return writer.Bytes()
51}
52
53func patchRequest(n int) int {
54 req, err := http.NewRequest(http.MethodPatch, "http://localhost:3000",
55 bytes.NewReader(makePatch(n)))
56 if err != nil {
57 panic(err)
58 }
59
60 req.Header.Add("Atomic", "no")
61 req.Header.Add("Content-Type", "application/x-tar")
62 resp, err := http.DefaultClient.Do(req)
63 if err != nil {
64 panic(err)
65 }
66 defer resp.Body.Close()
67
68 data, err := io.ReadAll(resp.Body)
69 if err != nil {
70 panic(err)
71 }
72
73 fmt.Printf("%d: %s %q\n", n, resp.Status, string(data))
74 return resp.StatusCode
75}
76
77func concurrentWriter(wg *sync.WaitGroup, n int) {
78 for {
79 if patchRequest(n) == 200 {
80 break
81 }
82 }
83 wg.Done()
84}
85
86var count = flag.Int("count", 10, "request count")
87
88func main() {
89 flag.Parse()
90
91 initSite()
92 time.Sleep(time.Second)
93
94 wg := &sync.WaitGroup{}
95 for n := range *count {
96 wg.Add(1)
97 go concurrentWriter(wg, n)
98 }
99 wg.Wait()
100
101 success := 0
102 for n := range *count {
103 resp, err := http.Get(fmt.Sprintf("http://localhost:3000/%d.txt", n))
104 if err != nil {
105 panic(err)
106 }
107 if resp.StatusCode == 200 {
108 success++
109 }
110 }
111 fmt.Printf("written: %d of %d\n", success, *count)
112}