fork of whitequark.org/git-pages with mods for tangled

Add "dry run" capability for all destructive endpoints.

Changed files
+31 -7
src
+1
README.md
··· 70 70 - 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. 71 71 - If the received contents is empty, performs the same action as `DELETE`. 72 72 * 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. 73 + * 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. 73 74 * 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. 74 75 * Files with a certain name, when placed in the root of a site, have special functions: 75 76 - [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.)
+30 -7
src/pages.go
··· 405 405 return nil 406 406 } 407 407 408 + func checkDryRun(w http.ResponseWriter, r *http.Request) bool { 409 + // "Dry run" requests are used to non-destructively check if the request would have 410 + // successfully been authorized. 411 + if r.Header.Get("Dry-Run") != "" { 412 + fmt.Fprintln(w, "dry-run ok") 413 + return true 414 + } 415 + return false 416 + } 417 + 408 418 func putPage(w http.ResponseWriter, r *http.Request) error { 409 419 var result UpdateResult 410 420 ··· 424 434 defer cancel() 425 435 426 436 contentType := getMediaType(r.Header.Get("Content-Type")) 427 - 428 - if contentType == "application/x-www-form-urlencoded" { 437 + switch contentType { 438 + case "application/x-www-form-urlencoded": 429 439 auth, err := AuthorizeUpdateFromRepository(r) 430 440 if err != nil { 431 441 return err ··· 450 460 return err 451 461 } 452 462 463 + if checkDryRun(w, r) { 464 + return nil 465 + } 466 + 453 467 result = UpdateFromRepository(updateCtx, webRoot, repoURL, branch) 454 - } else { 468 + 469 + default: 455 470 _, err := AuthorizeUpdateFromArchive(r) 456 471 if err != nil { 457 472 return err 473 + } 474 + 475 + if checkDryRun(w, r) { 476 + return nil 458 477 } 459 478 460 479 // request body contains archive ··· 518 537 return err 519 538 } 520 539 540 + if checkDryRun(w, r) { 541 + return nil 542 + } 543 + 521 544 err = backend.DeleteManifest(r.Context(), makeWebRoot(host, projectName)) 522 545 if err != nil { 523 546 w.WriteHeader(http.StatusInternalServerError) ··· 618 641 return err 619 642 } 620 643 644 + if checkDryRun(w, r) { 645 + return nil 646 + } 647 + 621 648 resultChan := make(chan UpdateResult) 622 649 go func(ctx context.Context) { 623 650 ctx, cancel := context.WithTimeout(ctx, time.Duration(config.Limits.UpdateTimeout)) ··· 645 672 w.WriteHeader(http.StatusGatewayTimeout) 646 673 fmt.Fprintln(w, "update timeout") 647 674 case UpdateNoChange: 648 - w.WriteHeader(http.StatusOK) 649 675 fmt.Fprintln(w, "unchanged") 650 676 case UpdateCreated: 651 - w.WriteHeader(http.StatusOK) 652 677 fmt.Fprintln(w, "created") 653 678 case UpdateReplaced: 654 - w.WriteHeader(http.StatusOK) 655 679 fmt.Fprintln(w, "replaced") 656 680 case UpdateDeleted: 657 - w.WriteHeader(http.StatusOK) 658 681 fmt.Fprintln(w, "deleted") 659 682 } 660 683 if result.manifest != nil {