Changing base URL on part of a page only

2019-07-27 01:08发布

问题:

I have a page on my site that fetches and displays news items from the database of another (legacy) site on the same server. Some of the items contain relative links that should be fixed so that they direct to the external site instead of causing 404 errors on the main site.

I first considered using the <base> tag on the fetched news items, but this changes the base URL of the whole page, breaking the relative links in the main navigation - and it feels pretty hackish too.

I'm currently thinking of creating a regex to find the relative URLs (they all start with /index.php?) and prepending them with the desired base URL. Are there any more elegant solutions to this? The site is built on Symfony 2 and uses jQuery.

回答1:

Here is how I would tackle the problem:

function prepend_url ($prefix, $path) {
    // Prepend $prefix to $path if $path is not a full URL
    $parts = parse_url($path);
    return empty($parts['scheme']) ? rtrim($prefix, '/').'/'.ltrim($path, '/') : $path;
}

// The URL scheme and domain name of the other site
$otherDomain = 'http://othersite.tld';

// Create a DOM object
$dom = new DOMDocument('1.0');
$dom->loadHTML($inHtml); // $inHtml is an HTML string obtained from the database

// Create an XPath object
$xpath = new DOMXPath($dom);

// Find candidate nodes
$nodesToInspect = $xpath->query('//*[@src or @href]');

// Loop candidate nodes and update attributes
foreach ($nodesToInspect as $node) {
    if ($node->hasAttribute('src')) {
        $node->setAttribute('src', prepend_url($otherDomain, $node->getAttribute('src')));
    }
    if ($node->hasAttribute('href')) {
        $node->setAttribute('href', prepend_url($otherDomain, $node->getAttribute('href')));
    }
}

// Find all nodes to export
$nodesToExport = $xpath->query('/html/body/*');

// Iterate and stringify them
$outHtml = '';
foreach ($nodesToExport as $node) {
    $outHtml .= $node->C14N();
}

// $outHtml now contains the "fixed" HTML as a string

See it working



回答2:

You can override the base tag by putting http:\\ in front of the link. That is, give a full url, not a relative URL.



回答3:

Well, not actually a solution, but mostly a tip...

You could start playing aroung with ExceptionController.

There, just for example, you could seek for 404 error and check query string appended to request:

$request = $this->container->get('request');
....

if (404 === $exception->getStatusCode()) {
    $query = $request->server->get('QUERY_STRING');
    //...handle your logic
}

The other solution would be to define special route with its controller for such purposes, which would catch requests to index.php and do redirects and so on. Just define index.php in requirements of route and move this route on the top of your routing.

Not a clearest answer ever, but at least I hope I gave you a direction...

Cheers ;)