mirror of
https://codeberg.org/git-pages/git-pages.git
synced 2026-05-14 03:01:48 +00:00
Add "dry run" capability for all destructive endpoints.
This commit is contained in:
@@ -70,6 +70,7 @@ Features
|
||||
- The `POST` method requires an `application/json` body containing a Forgejo/Gitea/Gogs/GitHub webhook event payload. Requests where the `ref` key contains anything other than `refs/heads/pages` are ignored, and only the `pages` branch is used. The `repository.clone_url` key contains a repository URL to be shallowly cloned.
|
||||
- If the received contents is empty, performs the same action as `DELETE`.
|
||||
* In response to a `DELETE` request, the server unpublishes a site. The URL of the request must be the root URL of the site that is being unpublished. Site data remains stored for an indeterminate period of time, but becomes completely inaccessible.
|
||||
* If a `Dry-Run: yes` header is provided with a `PUT`, `DELETE`, or `POST` request, only the authorization checks are run; no destructive updates are made. Note that this functionality was added in _git-pages_ v0.2.0.
|
||||
* All updates to site content are atomic (subject to consistency guarantees of the storage backend). That is, there is an instantaneous moment during an update before which the server will return the old content and after which it will return the new content.
|
||||
* Files with a certain name, when placed in the root of a site, have special functions:
|
||||
- [Netlify `_redirects`][_redirects] file can be used to specify HTTP redirect and rewrite rules. The _git-pages_ implementation currently does not support placeholders, query parameters, or conditions, and may differ from Netlify in other minor ways. If you find that a supported `_redirects` file feature does not work the same as on Netlify, please file an issue. (Note that _git-pages_ does not perform URL normalization; `/foo` and `/foo/` are *not* the same, unlike with Netlify.)
|
||||
|
||||
37
src/pages.go
37
src/pages.go
@@ -405,6 +405,16 @@ func getPage(w http.ResponseWriter, r *http.Request) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func checkDryRun(w http.ResponseWriter, r *http.Request) bool {
|
||||
// "Dry run" requests are used to non-destructively check if the request would have
|
||||
// successfully been authorized.
|
||||
if r.Header.Get("Dry-Run") != "" {
|
||||
fmt.Fprintln(w, "dry-run ok")
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
func putPage(w http.ResponseWriter, r *http.Request) error {
|
||||
var result UpdateResult
|
||||
|
||||
@@ -424,8 +434,8 @@ func putPage(w http.ResponseWriter, r *http.Request) error {
|
||||
defer cancel()
|
||||
|
||||
contentType := getMediaType(r.Header.Get("Content-Type"))
|
||||
|
||||
if contentType == "application/x-www-form-urlencoded" {
|
||||
switch contentType {
|
||||
case "application/x-www-form-urlencoded":
|
||||
auth, err := AuthorizeUpdateFromRepository(r)
|
||||
if err != nil {
|
||||
return err
|
||||
@@ -450,13 +460,22 @@ func putPage(w http.ResponseWriter, r *http.Request) error {
|
||||
return err
|
||||
}
|
||||
|
||||
if checkDryRun(w, r) {
|
||||
return nil
|
||||
}
|
||||
|
||||
result = UpdateFromRepository(updateCtx, webRoot, repoURL, branch)
|
||||
} else {
|
||||
|
||||
default:
|
||||
_, err := AuthorizeUpdateFromArchive(r)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if checkDryRun(w, r) {
|
||||
return nil
|
||||
}
|
||||
|
||||
// request body contains archive
|
||||
reader := http.MaxBytesReader(w, r.Body, int64(config.Limits.MaxSiteSize.Bytes()))
|
||||
result = UpdateFromArchive(updateCtx, webRoot, contentType, reader)
|
||||
@@ -518,6 +537,10 @@ func deletePage(w http.ResponseWriter, r *http.Request) error {
|
||||
return err
|
||||
}
|
||||
|
||||
if checkDryRun(w, r) {
|
||||
return nil
|
||||
}
|
||||
|
||||
err = backend.DeleteManifest(r.Context(), makeWebRoot(host, projectName))
|
||||
if err != nil {
|
||||
w.WriteHeader(http.StatusInternalServerError)
|
||||
@@ -618,6 +641,10 @@ func postPage(w http.ResponseWriter, r *http.Request) error {
|
||||
return err
|
||||
}
|
||||
|
||||
if checkDryRun(w, r) {
|
||||
return nil
|
||||
}
|
||||
|
||||
resultChan := make(chan UpdateResult)
|
||||
go func(ctx context.Context) {
|
||||
ctx, cancel := context.WithTimeout(ctx, time.Duration(config.Limits.UpdateTimeout))
|
||||
@@ -645,16 +672,12 @@ func postPage(w http.ResponseWriter, r *http.Request) error {
|
||||
w.WriteHeader(http.StatusGatewayTimeout)
|
||||
fmt.Fprintln(w, "update timeout")
|
||||
case UpdateNoChange:
|
||||
w.WriteHeader(http.StatusOK)
|
||||
fmt.Fprintln(w, "unchanged")
|
||||
case UpdateCreated:
|
||||
w.WriteHeader(http.StatusOK)
|
||||
fmt.Fprintln(w, "created")
|
||||
case UpdateReplaced:
|
||||
w.WriteHeader(http.StatusOK)
|
||||
fmt.Fprintln(w, "replaced")
|
||||
case UpdateDeleted:
|
||||
w.WriteHeader(http.StatusOK)
|
||||
fmt.Fprintln(w, "deleted")
|
||||
}
|
||||
if result.manifest != nil {
|
||||
|
||||
Reference in New Issue
Block a user