View Full Version : [WEB] Redirect verso nuovo sito mantendo url
alvinian
25-08-2010, 14:05
Salve, vi posto il mio problema:
ho due domini, nuovosito.com (ho solo il nome, niente hosting) e vecchiosito.com (con anche hosting)
e vorrei che le richieste su nuovosito.com venissero rimbalzate a vecchiosito.com
Fino qui tutto ok, ci sono mille modi per farlo e 10mila topic a riguardo ovunque, però:
- Mi serve che l'url finale resti quello di nuovo sito, ovvero ad esempio richieste:
nuovosito.com/pagina1.html ---> vecchiosito.com/pagina1.html
nuovosito.com/blabla ---> vecchiosito.com/blabla
Il contenuto deve essere quello della pagina corrispondente di vecchosito, ma l'url nel browser deve restare quello di nuovosito, completo!
- NON posso fare un redirect dns, altrimenti avrei già risolto
- Gli altri redirect al massimo mi marcherano l'url sottostante, ovvero farebbero diventaure tutto
nuovosito.com/pagina1.html ---> vecchiosito.com/pagina1.html
nuovosito.com/blabla ---> vecchiosito.com/blabla
ma nella barra degli indirizzi si continuerebbe a vedere unicamente nuovosito.com, senza percorsi!
Esiste un modo per farlo? io nel nuovosito.com posso uppare qualche file.
Pensavo ad esempio ad usare i socket in php e rimbarlzare la risposta, creando con l'htaccess la "struttura di directory e file" al volo per mantenere anche i percorsi.
Qualcuno lo ha mai fatto o sa se esiste un modo per farlo più facilmente?
Se puoi accedere via php ai socket allora puoi accedere anche ad internet direttamente tramite il comando file (ti legge per intero una pagina web, sempre che tu abbia accesso ai socket).
Crei una pagina php che non fa altro che andare a prendere il contenuto dell'url dell'altro sito che gli viene passato.
Ad esempio:
http://www.nuovosito.com/ o http://www.nuovosito.com/index.php
deve andare a prendere la home page.
http://www.nuovosito.com/index.php?path=/pagina1.html
dovrà andare a prendere e visualizzare
http://www.vecchiosito.com/pagina1.html
Non è chiaramente quello che vuoi fare...ma con l'uso di mod_rewrite di apache fai corrispondere
http://www.nuovosito.com/path/xyz.html a http://www.nuovosito.com/index.php?path=/path/xyz.html
In questo modo aggiri il problema è ottieni il risultato voluto. Visualizzerai http://www.nuovosito.com/path/xyz.html nella barra del browser, ma eseguirai http://www.nuovosito.com/index.php?path=/path/xyz.html
alvinian
25-08-2010, 18:25
Ti quoto quello che hai scritto modificandolo correttamente:
col mod_rewrite:
da http://www.nuovosito.com/path/xyz.html a http://www.nuovosito.com/index.php?path=/path/xyz.html
poi con curl dentro la index.php prendo il path e scarico il contenuto di http://www.vecchiosito.com/path/xyz.html e barra del browser visualizzo in realtàhttp://www.nuovosito.com/path/xyz.html
Esattamente quello che volevo, già testato e funziona a meraviglia.
Il problema sono i contenuti secondari, ad esempio se nella pagina vecchiosito.com/path/xzy.html c'è un <img src="/img/im.jpg"> questo viene "cercato" nel nuovosito e ovviamente non viene trovato.
Lo stesso problema lo ho coi css e con gli script js.
Dovrei praticamente far con curl uno scaricamento "globale" e creare le risorse "virtuali" sul nuovosito.com
Tu sai come è possibile farlo?
Nel senso che scandire una pagina html e vedere se ci sono risorse da scaricare a parte lo so fare, ma poi come le "propongo" all'utente?
Nel senso che io ad esempio "/img/im.jpg" non la ho, ma posso procurarmela, il punto è come faccio a metterne il contenuto scaricato esattamente li?
Salve, vi posto il mio problema:
ho due domini, nuovosito.com (ho solo il nome, niente hosting) e vecchiosito.com (con anche hosting)
Ciao, cosa intendi dire che di nuovosito.com hai solo il nome ? E' un altro dominio di cui in pratica vuoi fare una sorta di mirroring ?
Domanda collaterale idiota: nuovosito e' tuo o di qualcun altro ?
In ogni caso, su vecchiosito che tipo di hosting hai ? Su cosa puoi mettere mano ?
Sembrerebbe il lavoro ideale per mod_proxy.
No, avevo scritto correttamente.
Ogni url viene trasformato da http://www.nuovosito.com/path/xyz.html a http://www.nuovosito.com/index.php?path=/path/xyz.html, quindi quando visualizzerai la pagina anche l'url http://www.nuovosito.com/img/im.jpg verrà riscritto in http://www.nuovosito.com/index.php?path=/img/im.jpg
Quindi anche l'immagine verrà recuperata e visualizzata. Al massimo ci sarà da adattare il mime type...
readfile è una funzione più adatta di file. Trovi esempi su come settare il corretto mime type nella pagina di readfile nella documentazione di php.
Ecco qua un esempio su come usare mod_rewrite: http://www.logon2.com.au/blog/archive/web-design/php-apache-mod-rewrite-tutorial/
Per determinare la pagina di vecchio sito da caricare, stampa $_SERVER['REQUEST_URI'] e capirai come viene composta la richiesta.
A questo punto determini il mime type, stampi i vari header (come nell'help di readfile) e leggi il file remoto tramite readfile.
In alcuni casi ci potrebbero essere problemi per la determinazione dei mime type, ma per un sito "tranquillo" non ci dovrebbero essere grossi prolemi.
alvinian
25-08-2010, 23:51
Ti ringrazio veramente cionci, usando quel link ho fatto molto più velocemente di quello che stavo realizzando e funziona a meraviglia!
Posto il codice nel caso servisse a qualcun altro.
File da mettere su nuovosito.com (niente hosting, solo nome dominio):
-- file .htaccess --
<IfModule mod_rewrite.c>
RewriteEngine On
RewriteBase /
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule . /index.php [L]
</IfModule>
-- file .index.php --
<?
$url = "http://vecchiosito.com".$_SERVER['REQUEST_URI'];
$output = getContent($url);
if (strstr($_SERVER['REQUEST_URI'],".css"))
$output = eval(header("Content-type: text/css")).$output;
echo $output;
function getContent ($url)
{
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_HEADER, 0);
curl_setopt($ch, CURLOPT_USERAGENT, $_SERVER['HTTP_USER_AGENT']);
curl_setopt($ch, CURLOPT_RETURNTRANSFER,true);
$output = curl_exec($ch);
curl_close($ch);
return $output;
}
?>
Funziona alla perfezione, l'unico mime che dava problemi era quello dei css, le immagini e il resto per ora sono ok (devo testare su altri browser).
In questo modo si ottiene - in modo completamente trasparente all'utente - tutto il contenuto di vecchiosito.com stampato su nuovosito.com, mantenendo i path e la struttura originale!
Grazie ancora
Ti ringrazio veramente cionci, usando quel link ho fatto molto più velocemente di quello che stavo realizzando e funziona a meraviglia!
Bene :)
Ho verificato anche io in locale e funziona anche in questo modo:
<?php
$url = "http://www.sito.it".$_SERVER['REQUEST_URI'];
if (strstr($_SERVER['REQUEST_URI'],".css"))
header("Content-type: text/css");
readfile($url);
?>
Visto che per molti l'uso di curl in php è problematico (non sempre è compilato con l'interprete)...
Il problema con i css c'è anche qui. Sinceramente trovo difficile capirne il perché.
PS: la funzione header rende già in output il nuovo header
Mi vengono in mente ora molte limitazioni. Principalmente alle richieste post ed ai coockies. In pratica con curl sarebbe possibile risolvere il problema, basterebbe duplicare tutti gli header (con getallheaders si ottengono tutti gli header) ed inviarli nella request tramite curl.
Poi ci sarebbero da gestire i cookies con dominio esplicito: bisogna cambiare il dominio sostituendo dove appare "vecchiosito", con "nuovosito" nel response header.
In sostanza, per un sito statico va bene anche così, per un sito dinamico è difficile che basti.
alvinian
26-08-2010, 14:04
Si mi sono già accorto anche io di questi due problemi e li stavo sistemando.
Il problema del post lo ho sistemato aggiungendo:
function getPostVars()
{
$post = "";
$amp = "";
foreach($_POST as $key => $value) {
$post .= $amp . $key . "=" . urlencode($value);
$amp = "&";
}
return $post;
}
if (count($_POST) > 0)
{
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_POSTFIELDS, getPostVars());
}
Per i cookie ci sto an cora lavorando, ho problemi con la CURLOPT_COOKIE di curl.
Se vuoi darmi una mano... :D
Non conosco curl e la mia versione di php è compilata senza il supporto a curl. Non c'è il modo di trapiantare tutti gli header dalla richiesta che arriva a php a curl ?
Con getallheaders si dovrebbero ottenere tutti... In tal caso si risolverebbe automaticamente il problema del post.
Per i cookies basterebbe fare una sostituzione nell'header ricevuto dal sito, se setta un cookie sostituisci "vecchiosito" a "nuovosito".
alvinian
26-08-2010, 15:43
Scusa ma la getallheaders() prende gli header tra il mio client e il sito specchio che fa girare curl.
A me servono gli header che girano tra la richiesta curl e il sito vero con i contenuti.
Se tu giri tutti gli header che ricevi alla richiesta HTTP verso la richiesta curl, salti a piè pari sia il problema del post che dei cookies nella direzione dal browser al vecchio sito.
Poi nei dati ricevuti da curl ti basta cercare negli header se vengono settati dei cookies. Se vengono settati cambi qualsiasi riferimento testuale a vecchiosito.it in nuovosito.it.
Guarda qui come passa tutti gli header: http://www.php.net/manual/en/function.curl-setopt.php#80271
alvinian
26-08-2010, 16:49
Si questo lo ho capito e sono in grando di rimbalzare gli header che girano tra client->curl verso la comunicazione curl->vecchiosito (usando la CURLOPT_HTTPHEADER, come mi hai appena linkato anche tu :D)
Il problema è capire gli header che ci sono tra vecchiosito->curl. Se vecchiosito mi imposta dei cookie su curl come faccio a intercettarli e poi infilarli dentro una setcookie verso il mio client?
Cerchi in quello che ti ritorna curl_exec...
Prima di tutto dovresti determinare la fine degli header, per evitare di cercare in tutto l'output (potrebbe essere anche un file ed avere dati binari). La fine degli header è determinata da una sequenza "\r\n\r\n".
A questo punto estrapoli gli header e devi cercare un testo come questo: "\r\nSet-Cookie: "
Cerchi fra la fine della stringa sopra ed il prossimo "\r\n", tutte le occorrenze di "vecchiosito.it" e le cambi in "nuovosito.it". Riaggiungi l'header alla risposta e prosegui.
alvinian
26-08-2010, 20:01
Benissimo, ho quasi finito.
I cookie che il client mi manda li setto da curl verso vecchio sito cosi:
// Header richiesta
$headerArr = getallheaders();
// Prendo eventuali cookie dalla richiesta corrente
$cookiestr = $headerArr["Cookie"];
if ($cookiestr)
{
// Sostituisco occorrenze host (newUrl -> originalUrl)
$cookiestr = str_replace($newUrl, $originalUrl, $cookiestr); // non testata
$addHeader = "Cookie: ".$cookiestr;
curl_setopt($ch, CURLOPT_HTTPHEADER, $addHeader);
}
E quelli che vecchiosito setta al curl li rimbalzo al client cosi:
// Funzione callback per intercettare i cookie
curl_setopt($ch, CURLOPT_HEADERFUNCTION, 'read_header');
// Callback eseguita per ogni riga dell'header
function read_header($ch, $header)
{
global $originalUrl;
global $newUrl;
$length = strlen($header);
// La CURLOPT_FOLLOWLOCATION non funziona col safe mode, forzo in locale l'esecuzione
if(!strncmp($header, "Location:", 9))
{
$location = trim(substr($header, 9, -1));
header("Location: $location");
}
if(!strncmp($header, "Set-Cookie:", 11))
{
$cookiestr = trim(substr($header, 11, -1));
// Sostituisco occorrenze host (originalUrl -> newUrl)
$cookiestr = str_replace($originalUrl, $newUrl, $cookiestr); // non testata
header("Set-Cookie: ".$cookiestr, false); // Senza false eventuali altre Set-Cookie verrebbero sovrascritte
}
return $length;
}
Ma ho ancora qualche problema con le sessioni, anche se non capisco perchè.
Il Cookie: PHPSESSID=xxxxxx lo vedo girare correttamnete
Quelli che arrivano dal client non li devi toccare, vengono già selezionati dal client, non ci dovrebbe essere un campo domain da modificare.
Quindi passa direttamente tutti gli header a curl, pari pari.
alvinian
27-08-2010, 01:36
Direi che ho finito.
Posto ancora il codice nel caso servisse a qualcun altro.
Se gentilmente ci dai un'occhiata mi faresti anche un grande favore :D
<?
$originalUrl = "vecchiosito.com";
$newUrl = "sitospecchio.com";
$url = "http://".$originalUrl.$_SERVER['REQUEST_URI'];
$ch = curl_init();
// Header richiesta
$headerArr = getallheaders();
$headers = array();
// Prendo eventuali cookie dalla richiesta corrente
if (isset($headerArr["Cookie"]))
array_push($headers,"Cookie: ".$headerArr["Cookie"]);
if (isset($headerArr["Accept"]))
array_push($headers,"Accept: ".$headerArr["Accept"]);
if (isset($headerArr["Accept-Language"]))
array_push($headers,"Accept-Language: ".$headerArr["Accept-Language"]);
if (isset($headerArr["Accept-Encoding"]))
array_push($headers,"Accept-Encoding: ".$headerArr["Accept-Encoding"]);
if (isset($headerArr["Accept-Charset"]))
array_push($headers,"Accept-Charset: ".$headerArr["Accept-Charset"]);
if (isset($headerArr["Keep-Alive"]))
array_push($headers,"Keep-Alive: ".$headerArr["Keep-Alive"]);
if (isset($headerArr["Connection"]))
array_push($headers,"Connection: ".$headerArr["Connection"]);
if (isset($headerArr["X-Requested-With"]))
array_push($headers,"X-Requested-With: ".$headerArr["X-Requested-With"]);
if (isset($headerArr["Cache-Control"]))
array_push($headers,"Cache-Control: ".$headerArr["Cache-Control"]);
// Aggiungo tutto all'header curl
if (count($headers) > 0)
// L'array deve essere appiattito, know-bug curl
curl_setopt($ch, CURLOPT_HTTPHEADER, flat_array($headers));
// Prendo eventuali variabili post dalla richiesta corrente
// TODO: Si poteva fare direttamente esaminando l'header
if (count($_POST) > 0)
{
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_POSTFIELDS, getPostVars());
}
// Funzione callback per intercettare i cookie arrivati a curl
curl_setopt($ch, CURLOPT_HEADERFUNCTION, 'read_header');
// Altre impostazioni
if (isset($_SERVER['HTTP_REFERER']))
curl_setopt($ch, CURLOPT_REFERER, str_replace($newUrl, $originalUrl, $_SERVER['HTTP_REFERER']));
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_USERAGENT, $_SERVER['HTTP_USER_AGENT']);
curl_setopt($ch, CURLOPT_HEADER, 0);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_TIMEOUT, 10);
$output = curl_exec($ch);
curl_close($ch);
// Sistemo mime
// TODO: Si potrebbe prendere il mime corretto direttamente dall'header nel callback
if (strstr($_SERVER['REQUEST_URI'],".css"))
header("Content-type: text/css");
elseif (strstr($_SERVER['REQUEST_URI'],".png"))
header("Content-type: image/png");
elseif (strstr($_SERVER['REQUEST_URI'],".gif"))
header("Content-type: image/gif");
elseif (strstr($_SERVER['REQUEST_URI'],".jpg"))
header("Content-type: image/jpeg");
elseif (strstr($_SERVER['REQUEST_URI'],".htc"))
header('Content-type: text/x-component');
elseif (strstr($_SERVER['REQUEST_URI'],".ico"))
header('Content-type: image/x-icon');
elseif (strstr($_SERVER['REQUEST_URI'],".xml"))
header('Content-type: text/xml');
// Stampo
echo $output;
// Callback eseguita per ogni riga dell'header
function read_header($ch, $header)
{
global $originalUrl;
global $newUrl;
$length = strlen($header);
// curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true) non funziona col safe mode, forzo con l'header
if(!strncmp($header, "Location:", 9))
{
$location = trim(substr($header, 9, -1));
header("Location: $location");
}
if(!strncmp($header, "Set-Cookie:", 11))
{
$cookiestr = trim(substr($header, 11, -1));
// Sostituisco occorrenze host (originalUrl -> newUrl)
$cookiestr = str_replace($originalUrl, $newUrl, $cookiestr); // non testata
header("Set-Cookie: ".$cookiestr, false); // Senza false eventuali altre Set-Cookie verrebbero sovrascritte
}
return $length;
}
function getPostVars()
{
$post = "";
$amp = "";
foreach($_POST as $key => $value) {
$post .= $amp . $key . "=" . urlencode($value);
$amp = "&";
}
return $post;
}
function flat_array($arr)
{
$res = "";
foreach($arr as $value)
$res .= $value."\n";
return array(substr($res,0,-1));
}
?>
Il file .htaccess è lo stesso del post #8 (http://www.hwupgrade.it/forum/showpost.php?p=32917514&postcount=8)
L'unico problema che fino ad ora ho riscontrato è che dal sito specchio non riesco a fare il login allo script piwik (http://piwik.org/), mi torna:
Errore: Form security key is invalid or has expired. Please reload the form and check that your cookies are enabled.
Ma è un problema che interessa solo me e io mi loggo dall'url reale; il resto del sito funziona a meraviglia
C'è l'header Referer nella request che potrebbe creare problemi. Dovrebbe bastare cambiare ogni occorrenza di "nuovosito" con "vecchiosito" e passarlo a curl.
Al posto di questo:
// Prendo eventuali cookie dalla richiesta corrente
if (isset($headerArr["Cookie"]))
array_push($headers,"Cookie: ".$headerArr["Cookie"]);
if (isset($headerArr["Accept"]))
array_push($headers,"Accept: ".$headerArr["Accept"]);
if (isset($headerArr["Accept-Language"]))
array_push($headers,"Accept-Language: ".$headerArr["Accept-Language"]);
if (isset($headerArr["Accept-Encoding"]))
array_push($headers,"Accept-Encoding: ".$headerArr["Accept-Encoding"]);
if (isset($headerArr["Accept-Charset"]))
array_push($headers,"Accept-Charset: ".$headerArr["Accept-Charset"]);
if (isset($headerArr["Keep-Alive"]))
array_push($headers,"Keep-Alive: ".$headerArr["Keep-Alive"]);
if (isset($headerArr["Connection"]))
array_push($headers,"Connection: ".$headerArr["Connection"]);
if (isset($headerArr["X-Requested-With"]))
array_push($headers,"X-Requested-With: ".$headerArr["X-Requested-With"]);
if (isset($headerArr["Cache-Control"]))
array_push($headers,"Cache-Control: ".$headerArr["Cache-Control"]);
Non potresti mettere un bel for each ? Magari cambiando l'header relativo al Referer con un if.
alvinian
27-08-2010, 16:30
C'è l'header Referer nella request che potrebbe creare problemi. Dovrebbe bastare cambiare ogni occorrenza di "nuovosito" con "vecchiosito" e passarlo a curl.
Non è quello che faccio già qui?
// Altre impostazioni
if (isset($_SERVER['HTTP_REFERER']))
curl_setopt($ch, CURLOPT_REFERER, str_replace($newUrl, $originalUrl, $_SERVER['HTTP_REFERER']));
Avrei potuto fare anche questo direttamente con l'header oppure usare un foreach come dici tu..lo ho scritto di getto senza ottimizzazioni, ho fretta che il mio sito torni online!
Certamente hai ragione :D
Il fatto è che ci potrebbero essere altri header interessanti, mentre tu ne fai una selezione. Ad esempio Referer l'hai ignorato ;)
alvinian
27-08-2010, 19:04
Il referrer lo prendo dalla variabile php $_SERVER['HTTP_REFERER'] nelle due righe di codice che ti riquotato
vBulletin® v3.6.4, Copyright ©2000-2025, Jelsoft Enterprises Ltd.