DevProTalk

DevProTalk (http://www.devprotalk.com/index.php)
-   Regular expression i htaccess (http://www.devprotalk.com/forumdisplay.php?f=41)
-   -   Subdomain iz $_SERVER['HTTP_HOST'] (http://www.devprotalk.com/showthread.php?t=8573)

User 18. 03. 2010. 15:26

Subdomain iz $_SERVER['HTTP_HOST']
 
Aplikacija prikazuje sadržaj na osnovu domena na kome se servira (uključujući i poddomen). Jedni podaci se prikazuju za www.domain.com, drugi za dev.domain.com, treći za test.domain.com i tako dalje.

Pokušavam da rešim sledeći problem: automatski izvršiti redirekciju na www poddomen ukoliko korisnik dođe na domen bez ikakvog poddomena. Na praktičnom primeru:
1) korisnik je došao na example.com => izvrsiti redirekciju na www.example.com
2) korisnik je došao na test.еxample.com (ili www.example.com ili dev.example.com) => ne menjati ništa

Trenutno radim preg_match nad $_SERVER['HTTP_HOST']:
Kôd:

preg_match ("%^(?:([A-Za-z0-9\-_]+)\.)?([^/.]+)\.([^/:]+)(\:[0-9]+)?%i", $_SERVER['HTTP_HOST'], $data);
To radi dobro sa TLD koji nemaju second level, jer odmah saznam da mi je $data[1] prazan, prependujem www i izvrsim redirekciju bez upita u bazu.

Problem nastaje sa raznim ccTLD i second level TLD, kao sto su .co.uk ili .com.br - tada sam primoran da vršim upite u bazu što želim da izbegnem.

Uzmimo za primer da korisnik dolazi na example.co.uk, a da se aplikacija servira sa www.example.co.uk. Trenutni regex ce vratiti:
$data[1] = 'example';
$data[2] = 'co';
$data[3] = 'uk';

Tj dobiću da je pronađen subdomain 'example'. Potom vršim upit u bazu po domenu 'example.co.uk'. Ukoliko ne dobijem rezultat, pokušavam sa 'www.example.co.uk'. Tim upitom nalazim domen i vršim redirekciju.

U slučaju da ni 'www.example.co.uk' domen nije nađen u bazi, izvrsiću redirekciju na neki treći domen, ali to je trenutno manje bitno.

Ima li neko bolju ideju kako bolje razrešiti ovaj problem?

JovanT 18. 03. 2010. 16:03

Мислим да нема потреба да се компликује оволико. Твоје потребе би могао да задовољи и обичан explode('.', $_SERVER['HTTP_HOST']);. Тиме ћеш добити све појединачне делове домена. Затим можеш да провераваш предзадњи део. Уколико је он нешто из опсега (co, its, in...), знаш да се ради о .ccTLD па сходно томе вршиш даље провере.

Ако ово није довољно поуздано, онда можеш да идеш обрнутом логиком - провераваш да ли се ради о интернационалном домену (com, net, org, info, eu, asia...). Ако јесте, третираш га на један начин, ако није - на други. Верујем да се све ово можеш решити уз неколико if-ова.

noviKorisnik 18. 03. 2010. 16:14

To radi na nivou .htaccess, ne u PHP. Recimo ovako (brzi primer, hvala Google...
Kôd:

Options +FollowSymlinks
RewriteEngine on
rewritecond %{http_host} ^domain.com [nc]
rewriterule ^(.*)$ http://www.domain.com/$1 [r=301,nc]


User 18. 03. 2010. 16:41

To nije resenje. Evo vise primera:

www.domain.com ne menjati
primer.domain.com ne menjati
drugi.domain.com ne menjati
domain.com se menja u www.domain.com

www.domain232.com.br ne menjati
primer.domain32423.com.br ne menjati
example2323.com.br se menja u www.example2323.com.br

Nije mi bilo u planu da za svaki domen koji se kreira pravim novu liniju u .htaccess fajlu.

Ja ne znam na kom ce (pod)domenu korisnici pokretati applikaciju. Oni najcesce imaju *.domain.com => domain.com alias. Aplikacija se servira sa jednog (ili vise) njihovih poddomena (ne domena bez poddomena) - to je obicno www.domain123.com ali moze da bude bilosta.domain123.com (kao i bilo koji drugi TLD).

sinisabobic 18. 03. 2010. 16:48

Imao sam slican problem (sa jedinom razlikom da su mi trebali domainovi kod kojih se znalo da je SDL veci od 3). Problem je resen na sledeci nacin:

explode-ujes po "."

onda proveravam po broju clanova u dobijenom nizu

ukoliko je 2 to je domain formata example.com
ukoliko je 3 onda se proverava srednji clan, pa ako je on manji ili jednak 3 onda je to formata example.co.uk npr a ako nije onda je to formata nesto.example.com

a sve ostalo je formata nesto.example.co.uk

(ne znam koji su detalji, ali ovo je meni resavalo sve sto mi je trebalo za tu situaciju)

sinisabobic 18. 03. 2010. 16:54

Ako je .htaccess u igri probaj nesto ovako
Kôd:

RewriteCond %{HTTP_HOST} !^(.*)\.([^\.]+)\.com$ [NC]
RewriteCond %{HTTP_HOST} ([^\.]+).com$ [NC]
RewriteRule ^(.*)$ http://www.%1.com/$1 [L,R=301]

pa ako ti to radi za sve com domainove smislicemo nesto i za ostale :)

UPDATE: ja koristim ovo za neke sajtove gde imam po 300+ domainova koji teraju isti kod

bOkIcA 18. 03. 2010. 17:39

Ako sam dobro skapirao radi se o aplikaciji koja "tera" vise domena.
U tom slucaju bih generisao (array) listu domena pri svakoj promeni u bazi, dalje bi se prema tome radila provera i redirekcija.

bOkIcA 18. 03. 2010. 19:28

mikro vreme odvojih...
Mislim da bi ovako nesto radilo dovoljno brzo cak i na vecem broju domena.

PHP kôd:

$current_domain    "example.co.uk"//$_SERVER['HTTP_HOST']

$domains    = array('example.com',
                    
'example.co.uk',
                    
'nekidomen.com',
                    
'nekinas.iz.rs',
                    
'test.co.rs');

foreach(
$domains as $key=>$domain) {
    
$strpos strpos($current_domain$domain);
    if (
$strpos AND preg_match("/\.$domain$/"$current_domain)) {
        
$success TRUE;
        break;
    } elseif (
$strpos === AND preg_match("/$domain$/"$current_domain)) {
        
// redirection here...
        
exit("redirecting to www.{$domains[$key]}");
    }
}

if (!isset(
$success)) {
    exit(
'domain not exist');
}

echo 
"show content w/o redirection"


bluesman 18. 03. 2010. 19:49

Biće bar 2000+ domena i broj raste vremenom ... već sada ih ima oko 300 a još nismo ni počeli.

bOkIcA 18. 03. 2010. 19:52

Na 50.000 domena u array-u vreme prolaska kroz petlju je na mom racunaru 0.035 sec.
A verujem da sigurno moze jos da se optimizuje.

bOkIcA 18. 03. 2010. 19:59

Dodavanje jednog IF-a i vreme prolaska kroz petnju (na tih 50.000 stavki u array-u) je sada ~ 0.027 sec.

PHP kôd:

foreach($domains as $key=>$domain) {
    if (
$strpos strpos($current_domain$domain) !== FALSE) {
        if (
$strpos AND preg_match("/\.$domain$/"$current_domain)) {
            
$success TRUE;
            break;
        } elseif (
$strpos === AND preg_match("/$domain$/"$current_domain)) {
            
// redirection here...
            
exit("redirecting to www.{$domains[$key]}");
        }
    }



bOkIcA 18. 03. 2010. 20:02

na 2.000 domena...
~ 0.00103402137756 seconds

bOkIcA 18. 03. 2010. 20:22

Kod svih merenja traženi domen je bio na kraju array-a... ukoliko se domen nalazi na nekom drugom mestu iz petlje se, naravno, izlazi ranije.

bluesman 18. 03. 2010. 23:39

Hvala na trudu i svemu, ali meni je neprihvatljivo rešenje da držim niz od 2000+ domena i radim foreach na svakom page view. Onda ću rađe da napravim jedno opšte pravilo koje važi za većinu a samo izuzetke da tretiram drugačije.

bOkIcA 19. 03. 2010. 00:01

Ok, kapiram.
Ovo je bila samo jedna od "mehničkih" ideja.

I btw. zašto ima potrebe da se na svaki prikaz radi takva provera?
Nije li dovoljno samo jednom pa to zapisati u session i koristiti?

laku noć :)

bluesman 19. 03. 2010. 00:06

Zato što je to prvo što se izvršava, pre svega ... neću da učitavam stranu do pola da bih shvatio da moram da radim redirekciju... ako ću tako, onda mogu i da koristim ovo tvoje rešenje :)

Hoću da izbegnem htaccess da mi ne bi radio rulove za svaki request. Hoću da izbegnem čitanje iz baze po svaku cenu.

miks 19. 03. 2010. 03:12

Na datom linku se nalazi bibliteka/funkcije za dobijanje registrovanog domena

http://www.dkim-reputation.org/regdom-libs/

ako imate registrovani domen, onda poddomen nije tesko pronaci.

razno 19. 03. 2010. 03:38

Nije potreban nikakav niz niti DNS lookup.
ccTLD domen ima maksimalno dva karaktera. Ispred ta dva karaktera ide do cetri znaka tipa info, co, com, biz itd (izvor http://www.entorno.es/dominios_terri...php?idioma=eng)
Ja sam pronasao da je info jedini sa cetiri karaktera (U .info.tr), eventualno postoji jos neki koji bi bilo potrebno dodati.

Sledeci kod bi trebalo da prepoznaje sve vrste domena i poddomena, eventualno je potrebna mala modifikacija za jos neki ccTLD koji nisam pronasao.
PHP kôd:

<?

function transfer($host){
    echo 
"$host ";
    
$d=explode('.',$host);
$total=count($d);

if(
$total==3)
{
    if(
strlen($d[2])==&& $d[0]!="www")
        if(
strlen($d[1])==&& $d[1]=="info")
            echo
"<b>www.".$d[0].".".$d[1].".".$d[2]."</b>";
        elseif(
strlen($d[1])<4)
            echo
"<b>www.".$d[0].".".$d[1].".".$d[2]."</b>";

        
}
elseif(
$total==2)//host sa jednom tackom
    
echo"<b>www.".$d[0].".".$d[1]."</b>";
    
echo
"<br>";
}

transfer("www.domain.com");
transfer("primer.domain.com");
transfer("domain.com");
transfer("www.domain232.com.br");
transfer("primer.domain32423.com.br");
transfer("example2323.com.br");
transfer("www.nesto.rs");
transfer("www.nesto.co.rs");
transfer("nesto.rs");
transfer("nesto.co.rs");
transfer("domen.nesto.rs");
transfer("domen.nesto.co.rs");
transfer("domen.com.hr");
transfer("prvi.domen.com.hr");
transfer("nesto.info.tr");
transfer("www.nesto.info.tr");
transfer("prvi.nesto.info.tr");;

?>

Skripta stampa samo gde treba doci do promene, u mojim primerima izlaz je sledeci
Kôd:

www.domain.com
primer.domain.com
domain.com www.domain.com
www.domain232.com.br
primer.domain32423.com.br
example2323.com.br www.example2323.com.br
www.nesto.rs
www.nesto.co.rs
nesto.rs www.nesto.rs
nesto.co.rs www.nesto.co.rs
domen.nesto.rs
domen.nesto.co.rs
domen.com.hr www.domen.com.hr
prvi.domen.com.hr
nesto.info.tr www.nesto.info.tr
www.nesto.info.tr
prvi.nesto.info.tr

Nadam se da nisam nesto ispustio sobzirom da je kasno i da sam proveo 12 sati na fakultetu :1058:

User 19. 03. 2010. 11:07

https://wiki.mozilla.org/TLD_List

bOkIcA 19. 03. 2010. 17:09

^ onda tu TLD listu da drzite u multidimenzijalnom array-u, lol opet ja i array :D ;)

Aj kad dodjete do nekog resenja da ga objavite ovde, ako ne bude problem.

miks 19. 03. 2010. 19:11

1 Prilog(a)
Citat:

Originalno napisao bOkIcA (Napišite 81968)
^ onda tu TLD listu da drzite u multidimenzijalnom array-u, lol opet ja i array :D ;)

Aj kad dodjete do nekog resenja da ga objavite ovde, ako ne bude problem.

Resenje vec postoji. Na linku koji sam prethodno postovao mozete naci vise informacija. Poslednja verzija za PHP je prikacena.

dejanr 26. 03. 2010. 13:28

Ja sam uspeo da odradim ovo na nivou web server-a jedan virtual host sa rewrite-om na osnovu toga da li postoji fajl u document_root/domains/imedomena

Posto je vec receno da u bazi drzite imena domena za koje ce raditi aplikacija, prilikom dodavanja, brisanja domena potrebno je i dodati i obrisati fajl u domains/ime_domena.

Tipa ako zelimo da nam aplikacija radi za example.com, samo cu touch-ovati taj fajl:

Kôd:

touch domains/example.com
touch domains/www.example.com
touch domains/test.example.com

Tako da ako posetimo http://example.com, mozemo uraditi sledeci rewrite:

Kôd:

set $postoji 0;
       
# ako fajl postoji vrati ga odmah i prekini konekciju
if (-f $request_filename) {
  break;
}
       
# ukoliko postoji trazeni domen
if (-f $document_root/domains/$host) {
  set $postoji 1;
}
       
# ukoliko postoji trazeni domen sa www pod domenom
if (-f $document_root/domains/www.$host) {
  set $postoji "${postoji}2";
}
       
# ukoliko ne postoji domen redirektuj na default host
if ($postoji = 0){
  rewrite ^(.+)$ http://www.example.com$1 last;
break;
}
       
# rewrite-uj trazeni domen sa www pod domenom
if ($postoji = 12){
  rewrite ^(.+)$ http://www.$host$1 last;
  break;
}

Koristim nginx i php fast cgi i evo kako bi to moglo da se resi:

A sve to zajedno za catchall virtual host bi izgledalo ovako:

Kôd:

server {
  listen 80 default;
  server_name    _;
  root  /Users/dejanr/Sites/dpt;
  server_name_in_redirect  off;     
  set $postoji 0;
       
  # ako fajl postoji vrati ga odmah i prekini konekciju
  if (-f $request_filename) {
    break;
  }
       
  # ukoliko postoji trazeni domen
  if (-f $document_root/domains/$host) {
    set $postoji 1;
  }
       
  # ukoliko postoji trazeni domen sa www pod domenom
  if (-f $document_root/domains/www.$host) {
    set $postoji "${postoji}2";
  }
       
  # ukoliko ne postoji domen setuj default host
  if ($postoji = 0){
    rewrite ^(.+)$ http://www.example.com$1 last;
    break;
  }
       
  # rewrite-uj trazeni domen sa www pod domenom
  if ($postoji = 12){
    rewrite ^(.+)$ http://www.$host$1 last;
    break;
  }
       
  location ~ .php$ {
    fastcgi_pass  127.0.0.1:9000;
    fastcgi_index  index.php;
    fastcgi_param  SCRIPT_FILENAME  $document_root/public$fastcgi_script_name;
    include /usr/local/nginx/conf/fastcgi_params;
  }
}


bluesman 26. 03. 2010. 13:35

Tnx, ali kod nas svi domeni pucaju na isti docroot. Mada nekako mi je nesigurno da se jedna stvar oslanja na drugu nezavisnu stvar računajući da će sve da bude kako je "logično".

dejanr 26. 03. 2010. 13:39

pa da radi sve za isti document root

dejanr 26. 03. 2010. 14:27

Document Root je u:

Kôd:

root  /Users/dejanr/Sites/dpt;
btw ovo moze i da radi kao reverse proxy ka apache-u koji je na drugom ip-u ili port-u. Pri cemu ce sve staticke stvari servirati nginx iz ovog uslova:

Kôd:

# ako fajl postoji vrati ga odmah i prekini konekciju
  if (-f $request_filename) {
    break;
  }

A ostalo biti prosledjeno apache-u koji je zver :)


Vreme je GMT +2. Trenutno vreme je 19:08.

Powered by vBulletin® Verzija 3.6.8
Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
Copyright © DevProTalk. All Rights Reserved.

Mišljenja, saveti, izjave, ponude ili druge informacije ili sadržaji nastali na Sajtu su vlasništvo onoga ko ih je kreirao, a ne DevProTalk.com, tako da ne morate da se oslanjate na njih.
Autori poruka su jedini odgovorni za ovakve sadržaje. DevProTalk.com ne garantuje tačnost, kompletnost ili upotrebnu vrednost informacija, stavova, saveta ili datih izjava. Ne postoje uslovi pod kojima bi mi bili odgovorni za štetu ili gubitak koji je posledica bilo čijeg oslanjanja na nepouzdane informacije, ili bilo kakve informacije nastale kroz komunikaciju između registrovanih članova.
Web sajt može sadržavati linkove na druge web sajtove na Internetu ili neke druge sadržaje. Ne kontrolišemo niti podržavamo te druge web sajtove, niti smo pregledali bilo kakve sadržaje na takvim sajtovima. Mi nećemo biti odgovorni za legalnost, tačnost ili prikladnost bilo kog sadržaja, oglasa, proizvoda, usluga ili informacije lociranim na ili distribuiranih kroz druge web sajtove, niti za bilo kakvu štetu nastalu kao posledica takvih informacija. DevProTalk.com drži i čuva druga prava vlasništva na web sajtu. Web sajt sadrže materijale zaštićene copyright-om, zaštitne znakove i druge informacije o pravu vlasništva ili softver. Članovi mogu poslatu informacije zaštićene pravima vlasništva njihovih nosilaca i ona ostaju zaštićena bez obzira da li su oni koji prenose te informacije to naveli ili ne. Osim informacija koje su u javnom vlasništvu ili za koje dobijete dozvolu, nemate pravo da kopirate, modifikujete ili na bilo koji način menjate, objavljujete, prenosite, distribuirate, izvršavate, prikazujete ili prodajte bilo koju informaciju zaštićenu pravima vlasništva. Slanjem informacija ili sadržaja na bilo koji deo DevProTalk.com, Vi automatski dozvoljavate i predstavljate garanciju da imate pravo da dozvolite DevProTalk.com ili članovima DevProTalk.com bespovratnu, kontinualnu, neograničenu, globalnu dozvolu da koriste, kopiraju, izvršavaju, prikazuju i distribuiraju takve informacije i sadržaje i da iz takvih sadžaja koriste bilo koji deo u bilo koje svrhe, kao i pravo i dozvolu da koriste gore navedene sadržaje. Svi zaštitni znakovi (trademarks), logotipi, oznake usluga, firme ili imena proizvoda koji se pominju na ovom web sajtu su vlasništvo kojim raspolažu njihovi vlasnici.