• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

go-spatial / tegola / fa61eff93-PR-1040

19 Mar 2025 08:01AM UTC coverage: 40.442% (-0.3%) from 40.721%
fa61eff93-PR-1040

Pull #1040

github

iwpnd
chore: vendor
Pull Request #1040: refactor: drop zap and stdlogger in favour of slog

21 of 110 new or added lines in 6 files covered. (19.09%)

21 existing lines in 4 files now uncovered.

6588 of 16290 relevant lines covered (40.44%)

216.18 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

0.0
/cmd/tegola_lambda/main.go
1
package main
2

3
import (
4
        "fmt"
5
        "net/http"
6
        "net/url"
7
        "os"
8

9
        "github.com/akrylysov/algnhsa"
10
        "github.com/dimfeld/httptreemux"
11
        "github.com/go-spatial/geom/encoding/mvt"
12

13
        "github.com/go-spatial/tegola/atlas"
14
        "github.com/go-spatial/tegola/cmd/internal/register"
15
        "github.com/go-spatial/tegola/config"
16
        "github.com/go-spatial/tegola/dict"
17
        "github.com/go-spatial/tegola/internal/build"
18
        "github.com/go-spatial/tegola/internal/log"
19
        "github.com/go-spatial/tegola/server"
20
)
21

22
// mux is a reference to the http muxer. it's stored as a package
23
// var so we can take advantage of Lambda's "Global State".
24
var mux *httptreemux.TreeMux
25

26
const DefaultConfLocation = "config.toml"
27

28
// instantiate the server during the init() function and then store
29
// the muxer in a package variable. This allows us to take advantage
30
// of "Global State" to avoid needing to re-parse the config, connect
31
// to databases, tile caches, etc. on each function invocation.
32
//
33
// For more info, see Using Global State:
34
// https://docs.aws.amazon.com/lambda/latest/dg/go-programming-model-handler-types.html
35
func init() {
×
36
        var err error
×
37

×
38
        // override the URLRoot func with a lambda specific one
×
39
        server.URLRoot = URLRoot
×
40

×
41
        confLocation := DefaultConfLocation
×
42

×
43
        // check if the env TEGOLA_CONFIG is set
×
44
        if os.Getenv("TEGOLA_CONFIG") != "" {
×
45
                confLocation = os.Getenv("TEGOLA_CONFIG")
×
46
        }
×
47

48
        // read our config
49
        conf, err := config.Load(confLocation)
×
50
        if err != nil {
×
NEW
51
                log.Error(err)
×
NEW
52
                os.Exit(1)
×
UNCOV
53
        }
×
54

55
        // validate our config
56
        if err = conf.Validate(); err != nil {
×
NEW
57
                log.Error(err)
×
NEW
58
                os.Exit(1)
×
UNCOV
59
        }
×
60

61
        // init our providers
62
        // but first convert []env.Map -> []dict.Dicter
63
        provArr := make([]dict.Dicter, len(conf.Providers))
×
64
        for i := range provArr {
×
65
                provArr[i] = conf.Providers[i]
×
66
        }
×
67

68
        // register the providers
69
        providers, err := register.Providers(provArr, nil)
×
70
        if err != nil {
×
NEW
71
                log.Error(err)
×
NEW
72
                os.Exit(1)
×
UNCOV
73
        }
×
74

75
        // register the maps
76
        if err = register.Maps(nil, conf.Maps, providers); err != nil {
×
NEW
77
                log.Error(err)
×
NEW
78
                os.Exit(1)
×
UNCOV
79
        }
×
80

81
        // check if a cache backend is provided
82
        if len(conf.Cache) != 0 {
×
83
                // register the cache backend
×
84
                cache, err := register.Cache(conf.Cache)
×
85
                if err != nil {
×
NEW
86
                        log.Error(err)
×
NEW
87
                        os.Exit(1)
×
88
                }
×
89
                if cache != nil {
×
90
                        atlas.SetCache(cache)
×
91
                }
×
92
        }
93

94
        // set our server version
95
        server.Version = build.Version
×
96
        if conf.Webserver.HostName.Host != "" {
×
97
                u := url.URL(conf.Webserver.HostName)
×
98
                server.HostName = &u
×
99
        }
×
100

101
        // set user defined response headers
102
        for name, value := range conf.Webserver.Headers {
×
103
                // cast to string
×
104
                val := fmt.Sprintf("%v", value)
×
105
                // check that we have a value set
×
106
                if val == "" {
×
NEW
107
                        log.Errorf("webserver.header (%v) has no configured value", val)
×
NEW
108
                        os.Exit(1)
×
UNCOV
109
                }
×
110

111
                server.Headers[name] = val
×
112
        }
113

114
        if conf.Webserver.URIPrefix != "" {
×
115
                server.URIPrefix = string(conf.Webserver.URIPrefix)
×
116
        }
×
117

118
        // http route setup
119
        mux = server.NewRouter(nil)
×
120
}
121

122
func main() {
×
123
        build.Commands = []string{"lambda"}
×
124
        // the second argument here tells algnhsa to watch for the MVT MimeType Content-Type headers
×
125
        // if it detects this in the response the payload will be base64 encoded. Lambda needs to be configured
×
126
        // to handle binary responses so it can convert the base64 encoded payload back into binary prior
×
127
        // to sending to the client
×
128
        algnhsa.ListenAndServe(mux, &algnhsa.Options{
×
129
                BinaryContentTypes: []string{mvt.MimeType},
×
130
                UseProxyPath:       true,
×
131
        })
×
132
}
×
133

134
// URLRoot overrides the default server.URLRoot function in order to include the "stage" part of the root
135
// that is part of lambda's URL scheme
136
func URLRoot(r *http.Request) *url.URL {
×
137
        u := url.URL{
×
138
                Scheme: scheme(r),
×
139
                Host:   r.Header.Get("Host"),
×
140
        }
×
141

×
142
        // read the request context to pull out the lambda "stage" so it can be prepended to the URL Path
×
143
        if ctx, ok := algnhsa.APIGatewayV1RequestFromContext(r.Context()); ok {
×
144
                u.Path = ctx.RequestContext.Stage
×
145
        }
×
146

147
        return &u
×
148
}
149

150
// various checks to determine if the request is http or https. the scheme is needed for the TileJSON URLs
151
// r.URL.Scheme can be empty if a relative request is issued from the client. (i.e. GET /foo.html)
152
func scheme(r *http.Request) string {
×
153
        if r.Header.Get("X-Forwarded-Proto") != "" {
×
154
                return r.Header.Get("X-Forwarded-Proto")
×
155
        } else if r.TLS != nil {
×
156
                return "https"
×
157
        }
×
158

159
        return "http"
×
160
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc