carlos / platform Public

Clone
git clone https://amadan.net/carlos/platform

Plain git — no account needed to clone.

Download

Download this file

1package edge
2
3import (
4 "context"
5 "net"
6 "net/http"
7 "net/http/httputil"
8
9 "github.com/carlosframework/platform/internal/geoip"
10 "github.com/carlosframework/platform/internal/tunnelclient"
11)
12
13// geoResultKey carries the request's one geo answer (spec §8.2): computed
14// at ingress or adopted from a trusted transport, read by setGeo, the cache
15// path (through r.Header) and analytics.
16type geoResultKey struct{}
17
18func geoAnswerFrom(ctx context.Context) (geoip.Answer, bool) {
19 a, ok := ctx.Value(geoResultKey{}).(geoip.Answer)
20 return a, ok
21}
22
23// fromTunnel is the tunnel client's mark (geoip spec §8.4, D2): set on
24// every request tunnelclient serves, never by anything a client sends.
25var fromTunnel = tunnelclient.FromTunnel
26
27// decideGeo is step 3 of spec §8.1. hopPresent says the request ARRIVED
28// carrying X-Carlos-Hop (captured before acceptHop strips it); hopped says
29// acceptHop verified it.
30func (e *Edge) decideGeo(r *http.Request, c geoip.Captured, hopPresent, hopped, isDoor bool) geoip.Answer {
31 switch {
32 case isDoor:
33 return geoip.Off() // RemoteAddr is this box (door.go)
34 case hopped:
35 return c.Adopt() // the sending edge looked up; never trust our own peer
36 case hopPresent:
37 return geoip.Off() // rejected hop: RemoteAddr is the sending edge (codex R2-1)
38 case fromTunnel(r.Context()):
39 return c.Adopt() // the hub looked up (spec §8.4)
40 }
41 ip := net.ParseIP(clientIP(r))
42 return geoip.FromSnapshot(e.geoLookup(ip))
43}
44
45// setGeo is every Rewrite's geo step (spec §8.3): after hop-by-hop removal,
46// delete every geo header from the outbound request and write the answer
47// back from the context. forwardsToEdge adds X-Carlos-Hop-Geo for the next
48// edge; an app never receives it.
49func setGeo(pr *httputil.ProxyRequest, forwardsToEdge bool) {
50 geoip.StripAll(pr.Out.Header)
51 a, ok := geoAnswerFrom(pr.In.Context())
52 if !ok {
53 a = geoip.Off() // scheduler calls through UnixProxy and anything else that never passed ServeHTTP
54 }
55 a.WriteApp(pr.Out.Header)
56 if forwardsToEdge {
57 pr.Out.Header.Set(geoip.HeaderHop, a.HopValue())
58 }
59}
60