ParsoidHandler: optionally use private URLs for redirects

The ParsoidHanlder base class is used by the Transform endpoint in core,
which should redirect to core's public /page and /revision endpoints,
using URLs based on the CanonicalServer setting.

It is also used by the Page and Transform endpoints in the parsoid
extension, which need to redirect to private endpoints, using URLs based
on the InternalServer setting.

This patch allows that distinction to be made while using the standard
mechanism for determining route URLs provided by the REST framework. So
far, we had a work-around in place that duplicated that logic.

Bug: T311867
Depends-On: I85ac2f2a8626989e111265869ff301fc72dfaa15
Change-Id: I8e154ded4b93b1e7201fc302a968bd88211666bc
This commit is contained in:
daniel 2022-07-04 15:20:59 +02:00 committed by Arlolra
parent 2f8736f1d3
commit ef9889433f
2 changed files with 38 additions and 20 deletions

View file

@ -388,6 +388,8 @@ abstract class ParsoidHandler extends Handler {
/**
* Redirect to another Parsoid URL (e.g. canonization)
*
* @stable to override
*
* @param string $path Target URL
* @param array $pathParams Path parameters to inject into path
* @param array $queryParams Query parameters
@ -397,34 +399,43 @@ abstract class ParsoidHandler extends Handler {
protected function createRedirectResponse(
string $path, array $pathParams = [], array $queryParams = []
): Response {
// FIXME: We should be using $this->getRouteUrl here. But that uses the CanonicalServer
// setting as the base URL, which is incorrect when redirecting to private
// endpoints. See T311867.
global $wgRestPath;
$path = wfExpandUrl( "$wgRestPath$path", PROTO_CURRENT );
foreach ( $pathParams as $param => $value ) {
// NOTE: we use rawurlencode here, since execute() uses rawurldecode().
// Spaces in path params must be encoded to %20 (not +).
$path = str_replace( '{' . $param . '}', rawurlencode( $value ), $path );
}
// XXX: this should not be necessary in the REST entry point
// FIXME this should not be necessary in the REST entry point
unset( $queryParams['title'] );
if ( $queryParams ) {
$path .= ( strpos( $path, '?' ) === false ? '?' : '&' )
. http_build_query( $queryParams, '', '&', PHP_QUERY_RFC3986 );
}
$url = $this->getRedirectRouteUrl( $path, $pathParams, $queryParams );
if ( $this->getRequest()->getMethod() === 'POST' ) {
$response = $this->getResponseFactory()->createTemporaryRedirect( $path );
// 307 response
$response = $this->getResponseFactory()->createTemporaryRedirect( $url );
} else {
$response = $this->getResponseFactory()->createLegacyTemporaryRedirect( $path );
// 302 response
$response = $this->getResponseFactory()->createLegacyTemporaryRedirect( $url );
}
$response->setHeader( 'Cache-Control', 'private,no-cache,s-maxage=0' );
return $response;
}
/**
* Returns the target URL for a redirect to the given path and parameters.
* This exists so subclasses can override it to control whether the redirect
* should go to a private or to a public URL.
*
* @see Router::getRouteUrl()
*
* @stable to override
*
* @param string $path
* @param array $pathParams
* @param array $queryParams
*
* @return string
*/
protected function getRedirectRouteUrl(
string $path, array $pathParams = [], array $queryParams = []
) {
return $this->getRouter()->getRouteUrl( $path, $pathParams, $queryParams );
}
/**
* Try to create a PageConfig object. If we get an exception (because content
* may be missing or inaccessible), throw an appropriate HTTP response object
@ -475,6 +486,8 @@ abstract class ParsoidHandler extends Handler {
* This is done in the parsoid extension, for backwards compatibility
* with the old endpoint URLs.
*
* @stable to override
*
* @param string $format The format the endpoint is expected to return.
*
* @return string
@ -489,6 +502,8 @@ abstract class ParsoidHandler extends Handler {
* This is done in the parsoid extension, for backwards compatibility
* with the old endpoint URLs.
*
* @stable to override
*
* @param string $format The format the endpoint is expected to return.
*
* @return string
@ -506,6 +521,8 @@ abstract class ParsoidHandler extends Handler {
* This is done in the parsoid extension, for backwards compatibility
* with the old endpoint URLs.
*
* @stable to override
*
* @param string $format The format the endpoint is expected to return.
*
* @return string

View file

@ -336,7 +336,8 @@ class Router {
foreach ( $pathParams as $param => $value ) {
// NOTE: we use rawurlencode here, since execute() uses rawurldecode().
// Spaces in path params must be encoded to %20 (not +).
$route = str_replace( '{' . $param . '}', rawurlencode( $value ), $route );
// Slashes must be encoded as %2F.
$route = str_replace( '{' . $param . '}', rawurlencode( (string)$value ), $route );
}
return $route;