| 149 | } |
| 150 | |
| 151 | func customLandingPage(options *LandingPageOptions) rex.Handle { |
| 152 | assets := set.New[string]() |
| 153 | for _, p := range options.Assets { |
| 154 | assets.Add("/" + strings.TrimPrefix(p, "/")) |
| 155 | } |
| 156 | return func(ctx *rex.Context) any { |
| 157 | if ctx.R.URL.Path == "/" || assets.Has(ctx.R.URL.Path) { |
| 158 | query := ctx.R.URL.RawQuery |
| 159 | if query != "" { |
| 160 | query = "?" + query |
| 161 | } |
| 162 | url, err := ctx.R.URL.Parse(options.Origin + ctx.R.URL.Path + query) |
| 163 | if err != nil { |
| 164 | return rex.Err(http.StatusBadRequest, "Invalid url") |
| 165 | } |
| 166 | fetchClient := fetch.NewClient(ctx.UserAgent(), 15, false) |
| 167 | res, err := fetchClient.Fetch(url, nil) |
| 168 | if err != nil { |
| 169 | return rex.Err(http.StatusBadGateway, "Failed to fetch custom landing page") |
| 170 | } |
| 171 | etag := res.Header.Get("Etag") |
| 172 | if etag != "" { |
| 173 | if ctx.R.Header.Get("If-None-Match") == etag { |
| 174 | return rex.Status(http.StatusNotModified, nil) |
| 175 | } |
| 176 | ctx.SetHeader("Etag", etag) |
| 177 | } else { |
| 178 | lastModified := res.Header.Get("Last-Modified") |
| 179 | if lastModified != "" { |
| 180 | v := ctx.R.Header.Get("If-Modified-Since") |
| 181 | if v != "" { |
| 182 | timeIfModifiedSince, e1 := time.Parse(http.TimeFormat, v) |
| 183 | timeLastModified, e2 := time.Parse(http.TimeFormat, lastModified) |
| 184 | if e1 == nil && e2 == nil && !timeIfModifiedSince.After(timeLastModified) { |
| 185 | return rex.Status(http.StatusNotModified, nil) |
| 186 | } |
| 187 | } |
| 188 | ctx.SetHeader("Last-Modified", lastModified) |
| 189 | } |
| 190 | } |
| 191 | cacheControl := res.Header.Get("Cache-Control") |
| 192 | if cacheControl != "" { |
| 193 | ctx.SetHeader("Cache-Control", cacheControl) |
| 194 | } else { |
| 195 | ctx.SetHeader("Cache-Control", ccMustRevalidate) |
| 196 | } |
| 197 | ctx.SetHeader("Content-Type", res.Header.Get("Content-Type")) |
| 198 | return res.Body // auto closed |
| 199 | } |
| 200 | return ctx.Next() |
| 201 | } |
| 202 | } |