blob: 452a321793cb5455748de481ae34e793a54efd36 [file] [log] [blame]
// Copyright 2019 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package frontend
import (
"fmt"
"net/http"
"github.com/google/safehtml/template"
"golang.org/x/pkgsite/internal"
"golang.org/x/pkgsite/internal/derrors"
"golang.org/x/pkgsite/internal/log"
"golang.org/x/pkgsite/internal/stdlib"
)
// errUnitNotFoundWithoutFetch returns a 404 with instructions to the user on
// how to manually fetch the package. No fetch button is provided. This is used
// for very large modules or modules that previously 500ed.
var errUnitNotFoundWithoutFetch = &serverError{
status: http.StatusNotFound,
epage: &errorPage{
messageTemplate: template.MakeTrustedTemplate(`
<h3 class="Error-message">{{.StatusText}}</h3>
<p class="Error-message">Check that you entered the URL correctly or try fetching it following the
<a href="/about#adding-a-package">instructions here</a>.</p>`),
MessageData: struct{ StatusText string }{http.StatusText(http.StatusNotFound)},
},
}
func (s *Server) servePathNotFoundPage(w http.ResponseWriter, r *http.Request, ds internal.DataSource, fullPath, requestedVersion string) (err error) {
defer derrors.Wrap(&err, "servePathNotFoundPage(w, r, %q, %q)", fullPath, requestedVersion)
ctx := r.Context()
path, err := stdlibPathForShortcut(ctx, ds, fullPath)
if err != nil {
// Log the error, but prefer a "path not found" error for a
// better user experience.
log.Error(ctx, err)
}
if path != "" {
http.Redirect(w, r, fmt.Sprintf("/%s", path), http.StatusFound)
return
}
if stdlib.Contains(fullPath) {
return &serverError{status: http.StatusNotFound}
}
return pathNotFoundError(fullPath, requestedVersion)
}
// pathNotFoundError returns a page with an option on how to
// add a package or module to the site.
func pathNotFoundError(fullPath, requestedVersion string) error {
if !isSupportedVersion(fullPath, requestedVersion) {
return invalidVersionError(fullPath, requestedVersion)
}
if stdlib.Contains(fullPath) {
return &serverError{status: http.StatusNotFound}
}
path := fullPath
if requestedVersion != internal.LatestVersion {
path = fmt.Sprintf("%s@%s", fullPath, requestedVersion)
}
return &serverError{
status: http.StatusNotFound,
epage: &errorPage{
templateName: "fetch.tmpl",
MessageData: path,
},
}
}