1package main
2
3import (
4	"bufio"
5	"bytes"
6	"context"
7	"crypto/ed25519"
8	"encoding/json"
9	"encoding/pem"
10	"flag"
11	"fmt"
12	"io/ioutil"
13	"net/url"
14	"os"
15
16	"github.com/matrix-org/gomatrixserverlib"
17)
18
19var requestFrom = flag.String("from", "", "the server name that the request should originate from")
20var requestKey = flag.String("key", "matrix_key.pem", "the private key to use when signing the request")
21var requestPost = flag.Bool("post", false, "send a POST request instead of GET (pipe input into stdin or type followed by Ctrl-D)")
22
23func main() {
24	flag.Parse()
25
26	if requestFrom == nil || *requestFrom == "" {
27		fmt.Println("expecting: furl -from origin.com [-key matrix_key.pem] https://path/to/url")
28		fmt.Println("supported flags:")
29		flag.PrintDefaults()
30		os.Exit(1)
31	}
32
33	data, err := ioutil.ReadFile(*requestKey)
34	if err != nil {
35		panic(err)
36	}
37
38	var privateKey ed25519.PrivateKey
39	keyBlock, _ := pem.Decode(data)
40	if keyBlock == nil {
41		panic("keyBlock is nil")
42	}
43	if keyBlock.Type == "MATRIX PRIVATE KEY" {
44		_, privateKey, err = ed25519.GenerateKey(bytes.NewReader(keyBlock.Bytes))
45		if err != nil {
46			panic(err)
47		}
48	} else {
49		panic("unexpected key block")
50	}
51
52	client := gomatrixserverlib.NewFederationClient(
53		gomatrixserverlib.ServerName(*requestFrom),
54		gomatrixserverlib.KeyID(keyBlock.Headers["Key-ID"]),
55		privateKey,
56	)
57
58	u, err := url.Parse(flag.Arg(0))
59	if err != nil {
60		panic(err)
61	}
62
63	var bodyObj interface{}
64	var bodyBytes []byte
65	method := "GET"
66	if *requestPost {
67		method = "POST"
68		fmt.Println("Waiting for JSON input. Press Enter followed by Ctrl-D when done...")
69
70		scan := bufio.NewScanner(os.Stdin)
71		for scan.Scan() {
72			bytes := scan.Bytes()
73			bodyBytes = append(bodyBytes, bytes...)
74		}
75		fmt.Println("Done!")
76		if err = json.Unmarshal(bodyBytes, &bodyObj); err != nil {
77			panic(err)
78		}
79	}
80
81	req := gomatrixserverlib.NewFederationRequest(
82		method,
83		gomatrixserverlib.ServerName(u.Host),
84		u.RequestURI(),
85	)
86
87	if *requestPost {
88		if err = req.SetContent(bodyObj); err != nil {
89			panic(err)
90		}
91	}
92
93	if err = req.Sign(
94		gomatrixserverlib.ServerName(*requestFrom),
95		gomatrixserverlib.KeyID(keyBlock.Headers["Key-ID"]),
96		privateKey,
97	); err != nil {
98		panic(err)
99	}
100
101	httpReq, err := req.HTTPRequest()
102	if err != nil {
103		panic(err)
104	}
105
106	var res interface{}
107	err = client.DoRequestAndParseResponse(
108		context.TODO(),
109		httpReq,
110		&res,
111	)
112	if err != nil {
113		panic(err)
114	}
115
116	j, err := json.MarshalIndent(res, "", "  ")
117	if err != nil {
118		panic(err)
119	}
120
121	fmt.Println(string(j))
122}
123