New builds a new server.
(ctx context.Context, opts ...Option)
| 140 | |
| 141 | // New builds a new server. |
| 142 | func New(ctx context.Context, opts ...Option) (*Server, error) { |
| 143 | logger := log.FromContext(ctx).WithField("namespace", "web") |
| 144 | |
| 145 | options := new(options) |
| 146 | for _, opt := range opts { |
| 147 | opt(options) |
| 148 | } |
| 149 | |
| 150 | hashKey, blockKey := options.cookieHashKey, options.cookieBlockKey |
| 151 | |
| 152 | if len(hashKey) == 0 || isZeros(hashKey) { |
| 153 | hashKey = random.Bytes(64) |
| 154 | if !options.disableWarnings { |
| 155 | logger.Warn("No cookie hash key configured, generated a random one") |
| 156 | } |
| 157 | } |
| 158 | |
| 159 | if len(hashKey) != 32 && len(hashKey) != 64 { |
| 160 | return nil, errors.New("Expected cookie hash key to be 32 or 64 bytes long") |
| 161 | } |
| 162 | |
| 163 | if len(blockKey) == 0 || isZeros(blockKey) { |
| 164 | blockKey = random.Bytes(32) |
| 165 | if !options.disableWarnings { |
| 166 | logger.Warn("No cookie block key configured, generated a random one") |
| 167 | } |
| 168 | } |
| 169 | |
| 170 | if len(blockKey) != 32 { |
| 171 | return nil, errors.New("Expected cookie block key to be 32 bytes long") |
| 172 | } |
| 173 | |
| 174 | var proxyConfiguration webmiddleware.ProxyConfiguration |
| 175 | if err := proxyConfiguration.ParseAndAddTrusted(options.trustedProxies...); err != nil { |
| 176 | return nil, err |
| 177 | } |
| 178 | compressor, err := gzhttp.NewWrapper() |
| 179 | if err != nil { |
| 180 | return nil, err |
| 181 | } |
| 182 | root := mux.NewRouter() |
| 183 | root.NotFoundHandler = http.HandlerFunc(webhandlers.NotFound) |
| 184 | root.Use( |
| 185 | webhandlers.WithErrorHandlers(map[string]http.Handler{ |
| 186 | "text/html": webhandlers.Template, |
| 187 | }), |
| 188 | mux.MiddlewareFunc(webmiddleware.Recover()), |
| 189 | func(next http.Handler) http.Handler { return compressor(next) }, |
| 190 | otelmux.Middleware("ttn-lw-stack", otelmux.WithTracerProvider(tracing.FromContext(ctx))), |
| 191 | mux.MiddlewareFunc(webmiddleware.FillContext(options.contextFillers...)), |
| 192 | mux.MiddlewareFunc(webmiddleware.Peer()), |
| 193 | mux.MiddlewareFunc(webmiddleware.RequestURL()), |
| 194 | mux.MiddlewareFunc(webmiddleware.RequestID()), |
| 195 | mux.MiddlewareFunc(webmiddleware.ProxyHeaders(proxyConfiguration)), |
| 196 | mux.MiddlewareFunc(webmiddleware.Metadata("X-Forwarded-For", "User-Agent")), |
| 197 | mux.MiddlewareFunc(webmiddleware.MaxBody(1024*1024*16)), |
| 198 | mux.MiddlewareFunc(webmiddleware.SecurityHeaders()), |
| 199 | mux.MiddlewareFunc(webmiddleware.HSTSHeaders()), |