mirror of https://github.com/harness/drone.git
64 lines
2.2 KiB
Go
64 lines
2.2 KiB
Go
// Copyright 2022 Harness Inc. All rights reserved.
|
|
// Use of this source code is governed by the Polyform Free Trial License
|
|
// that can be found in the LICENSE.md file for this repository.
|
|
|
|
// Package request provides http handlers for serving the
|
|
// web applications and API endpoints.
|
|
package request
|
|
|
|
import (
|
|
"fmt"
|
|
"net/http"
|
|
"net/url"
|
|
)
|
|
|
|
// ReplacePrefix replaces the path of the request.
|
|
// IMPORTANT:
|
|
// - both prefix are unescaped for path, and used as is for RawPath!
|
|
// - only called by top level handler!!
|
|
func ReplacePrefix(r *http.Request, oldPrefix string, newPrefix string) error {
|
|
/*
|
|
* According to official documentation, we can change anything in the request but the body:
|
|
* https://pkg.go.dev/net/http#Handler
|
|
*
|
|
* ASSUMPTION:
|
|
* This is called by a top level handler (no router or middleware above it)
|
|
* Therefore, we don't have to worry about getting any routing metadata out of sync.
|
|
*
|
|
* This is different to returning a shallow clone with updated URL, which is what
|
|
* http.StripPrefix or earlier versions of request.WithContext are doing:
|
|
* https://cs.opensource.google/go/go/+/refs/tags/go1.19:src/net/http/server.go;l=2138
|
|
* https://cs.opensource.google/go/go/+/refs/tags/go1.18:src/net/http/request.go;l=355
|
|
*
|
|
* http.StripPrefix initially changed the path only, but that was updated because of official recommendations:
|
|
* https://github.com/golang/go/issues/18952
|
|
*/
|
|
unOldPrefix, err := url.PathUnescape(oldPrefix)
|
|
if err != nil {
|
|
return fmt.Errorf("failed to unescape old prefix '%s'", oldPrefix)
|
|
}
|
|
unNewPrefix, err := url.PathUnescape(newPrefix)
|
|
if err != nil {
|
|
return fmt.Errorf("failed to unescape new prefix '%s'", newPrefix)
|
|
}
|
|
|
|
unl := len(unOldPrefix)
|
|
if len(r.URL.Path) < unl || r.URL.Path[0:unl] != unOldPrefix {
|
|
return fmt.Errorf("path '%s' doesn't contain prefix '%s'", r.URL.Path, unOldPrefix)
|
|
}
|
|
|
|
// only change RawPath if it exists
|
|
if r.URL.RawPath != "" {
|
|
l := len(oldPrefix)
|
|
if len(r.URL.RawPath) < l || r.URL.RawPath[0:l] != oldPrefix {
|
|
return fmt.Errorf("raw path '%s' doesn't contain prefix '%s'", r.URL.RawPath, oldPrefix)
|
|
}
|
|
|
|
r.URL.RawPath = newPrefix + r.URL.RawPath[l:]
|
|
}
|
|
|
|
r.URL.Path = unNewPrefix + r.URL.Path[unl:]
|
|
|
|
return nil
|
|
}
|