mirror of https://github.com/harness/drone.git
64 lines
2.2 KiB
Go
64 lines
2.2 KiB
Go
// Copyright 2023 Harness, Inc.
|
|
//
|
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
|
// you may not use this file except in compliance with the License.
|
|
// You may obtain a copy of the License at
|
|
//
|
|
// http://www.apache.org/licenses/LICENSE-2.0
|
|
//
|
|
// Unless required by applicable law or agreed to in writing, software
|
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
// See the License for the specific language governing permissions and
|
|
// limitations under the License.
|
|
|
|
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
|
|
*/
|
|
|
|
l := len(oldPrefix)
|
|
|
|
if r.URL.RawPath != "" {
|
|
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 = url.PathEscape(r.URL.RawPath)
|
|
} else {
|
|
if len(r.URL.Path) < l || r.URL.Path[0:l] != oldPrefix {
|
|
return fmt.Errorf("path '%s' doesn't contain prefix '%s'", r.URL.Path, oldPrefix)
|
|
}
|
|
|
|
r.URL.Path = newPrefix + r.URL.Path[l:]
|
|
}
|
|
|
|
return nil
|
|
}
|