git.s-ol.nu json-hopper / 30eff50
Redirect POST/PUT requests using config file s-ol 1 year, 2 months ago
1 changed file(s) with 62 addition(s) and 22 deletion(s). Raw diff Collapse all Expand all
00 package main
11
22 import (
3 "bytes"
34 "encoding/json"
4 "github.com/google/uuid"
5 jsonschema "github.com/santhosh-tekuri/jsonschema/v5"
65 "log"
76 "net/http"
87 "os"
98 "path/filepath"
9 "regexp"
1010 "strconv"
1111 "strings"
12 "text/template"
1213 "time"
14
15 "github.com/google/uuid"
16 jsonschema "github.com/santhosh-tekuri/jsonschema/v5"
1317 )
1418
1519 type HTTPError struct {
2630 }
2731
2832 type SiteHandler struct {
29 name string
30 path string
31 schema *jsonschema.Schema
33 name string
34 path string
35 schema *jsonschema.Schema
36 referer_pat *regexp.Regexp
37 redirect_tpl *template.Template
38 }
39
40 type SiteConfig struct {
41 RefererPattern string
42 RedirectTemplate string
43 }
44
45 type TemplateParams struct {
46 Id string
47 Key string
3248 }
3349
3450 func NewSiteHandler(site_name string, site_path string) (*SiteHandler, error) {
3652 if err != nil {
3753 return nil, err
3854 }
39 return &SiteHandler{site_name, site_path, schema}, nil
55
56 var cfg SiteConfig
57 cfg_data, err := os.ReadFile(filepath.Join(site_path, ".config.json"))
58 if err != nil {
59 return nil, err
60 }
61 if err := json.Unmarshal(cfg_data, &cfg); err != nil {
62 return nil, err
63 }
64
65 referer := regexp.MustCompile(cfg.RefererPattern)
66 template := template.Must(template.New(site_name + "_redirect").Parse(cfg.RedirectTemplate))
67
68 return &SiteHandler{site_name, site_path, schema, referer, template}, nil
4069 }
4170
4271 func NewMeta() (map[string]interface{}, error) {
139168 }
140169 data["$meta"] = meta
141170
142 bytes, err := json.Marshal(data)
143 if err != nil {
144 return err
145 }
146
171 raw_data, err := json.Marshal(data)
172 if err != nil {
173 return err
174 }
175
176 id, key := meta["id"].(string), meta["key"].(string)
147177 if err := os.WriteFile(
148 filepath.Join(h.path, meta["id"].(string)+".json"),
149 bytes,
178 filepath.Join(h.path, id+".json"),
179 raw_data,
150180 0644,
151181 ); err != nil {
152182 return err
153183 }
154184
155185 log.Printf("%s %s", r.Method, meta["id"])
186
187 var redirect_buf bytes.Buffer
188 h.redirect_tpl.Execute(&redirect_buf, TemplateParams{id, key})
189
156190 w.Header().Set("Content-Type", "application/json")
157 w.Write(bytes)
191 w.Header().Set("Location", redirect_buf.String())
192 w.WriteHeader(http.StatusCreated)
193 w.Write(raw_data)
158194 return nil
159195 }
160196
163199
164200 if len(parts) != 3 || parts[1] != h.name {
165201 return &HTTPError{http.StatusInternalServerError, nil}
202 }
203
204 if !h.referer_pat.MatchString(r.Header.Get("Referer")) {
205 return &HTTPError{http.StatusUnauthorized, nil}
166206 }
167207
168208 id := parts[2]
176216 }
177217
178218 var data map[string]interface{}
179 bytes, err := os.ReadFile(filepath.Join(h.path, id+".json"))
219 raw_data, err := os.ReadFile(filepath.Join(h.path, id+".json"))
180220 if err != nil {
181221 return &HTTPError{http.StatusNotFound, nil}
182222 }
183223
184 if err := json.Unmarshal(bytes, &data); err != nil {
224 if err := json.Unmarshal(raw_data, &data); err != nil {
185225 return err
186226 }
187227
195235 return h.handlePUTPOST(w, r, meta)
196236 } else if r.Method == "GET" {
197237 w.Header().Set("Content-Type", "application/json")
198 w.Write(bytes)
238 w.Write(raw_data)
199239 return nil
200240 }
201241
210250
211251 switch e := err.(type) {
212252 case *HTTPError:
213 code = e.code
214 if e.root != nil {
215 log.Printf("Error: %#v", err)
216 }
253 code = e.code
254 if e.root != nil {
255 log.Printf("Error: %#v", err)
256 }
217257 default:
218258 code = http.StatusInternalServerError
219 log.Printf("Error: %#v", err)
259 log.Printf("Error: %#v", err)
220260 }
221261
222262 http.Error(w, http.StatusText(code), code)