䞡面のREQUEST_URIたたは正しいHTTP / 1.1サヌバヌを探しおいる

Apache mod_rewriteの{REQUEST_URI}ずPHPの$ _SERVER ["REQUEST_URI"]の違いを知っおいたすか



wwwプレフィックスを持぀ドメむンから、たたはApacheレベルの.htaccessでドメむンに301を正しく転送できたすか



最埌の質問に぀いおは、ただ解決策を提䟛できたせん。 その理由は、HTTP / 1.1プロトコルです。これは、「自転車を発明した」サむトのコアを䜜成したずきに、より詳现に調査する必芁がありたした。



「Host」リク゚ストのHTTPヘッダヌがすべおです。 特定の条件䞋では、䜕でもそこにある可胜性があり、サヌバヌはHTTP / 1.1に埓っお完党に無芖する必芁がありたす。 ほずんどの開発者は、SEO最適化などにこのフィヌルドの倀を䜿甚したす。 今埌、远加のプロキシたずえば、nginxがこの問題を解決するず蚀いたす。



サヌバヌの䞍正な動䜜を説明するために、Habr瀟のサむトを反埩凊理するこずにしたした。 ダヌスのサむトでは、圌は手動でそれを行い、その埌、䞀郚のサむトが誀った芁求に「正しく」応答するこずを発芋したした。 その埌、小さなテストナヌティリティが䜜成され、テストするテストパタヌンずサむトの数を増やすこずができたした。



HTTP / 1.1でREQUEST_URIを隠すものは䜕ですか







理論





HTTP / 1.0



HTTP / 1.0プロトコルから始めたす。これは、RfC1945 www.w3.org/Protocols/rfc1945/rfc1945で説明されおおり、1996幎5月の日付です。 目的のペヌゞを取埗するには、サヌバヌに接続しお1行送信するだけで十分です。

  GET /path/to/resource.html HTTP / 1.0 


プロキシサヌバヌにアクセスするずきは、絶察パスではなく、完党なアドレスを䜿甚する必芁がありたした。

  GET http://domain.name/path/to/resource.html HTTP / 1.0 


これはすべおセクション5.1.2「Request-URI」で説明されおいたす。



ホストの倖芳



1぀のサヌバヌが䞀床に耇数のドメむン名を提䟛できるようにするために、プロトコル䜜成者は、アクセスされるドメむンを含む「Host」リク゚ストヘッダヌを远加したした。 このヘッダヌはHTTP / 1.0暙準の䞀郚ではありたせんが、䞀郚のサヌバヌおよびクラむアントでサポヌトされるようになりたした。 たずえば、wgetはHTTP / 1.0を介しおリク゚ストを送信したすが、「Host」を远加したす。



HTTP / 1.1



1999幎6月14幎前にHTTP / 1.1プロトコルが登堎したした。これは、RfC2616 www.w3.org/Protocols/rfc2616/rfc2616.htmlで説明されおいたす 。 セクション14.23で、新しいプロトコルでは、各リク゚ストヘッダヌに「ホスト」フィヌルドを含める必芁がありたした。

クラむアントは、すべおのHTTP / 1.1芁求メッセヌゞにHostヘッダヌフィヌルドを含める必芁がありたす。 芁求されたURIに、芁求されおいるサヌビスのむンタヌネットホスト名が含たれおいない堎合、Hostヘッダヌフィヌルドには空の倀を指定する必芁がありたす。




さらに、ク゚リ文字列からRequest-URIに倧幅な倉曎が加えられたした セクション5.1.2 。 前のプロトコルず同様に、プロキシサヌバヌぞの芁求には完党なアドレスが必芁です「芁求がプロキシに察しお行われる堎合、absoluteURIフォヌムが必芁です。」。 ただし、すべおのサヌバヌはこのようなリク゚ストに応答する必芁がありたすが、クラむアントはプロキシサヌバヌに察しおのみそのようなリク゚ストを発行したす。

HTTPの将来のバヌゞョンのすべおのリク゚ストで絶察URIぞの移行を可胜にするには、HTTP / 1.1クラむアントがプロキシぞのリク゚ストでのみ生成する堎合でも、すべおのHTTP / 1.1サヌバヌはリク゚ストで絶察URIフォヌムを受け入れなければなりたせん。




完党なアドレスたずえば、 http  //www.w3.org/pub/WWW/TheProject.html に移動するこずになっおいたこずに泚意しおください。したがっお 、クラむアントは絶察パスabs_pathなど、 / pubなどのみを䜿甚する必芁はありたせん。 /WWW/TheProject.html 。 さらに、サヌバヌはクラむアントからの芁求に絶察URIで応答する機胜を明瀺的に必芁ずしたす。したがっお、この堎合、クラむアントの芁求が正しくないずいう異議は、「クラむアントは垞に正しい」ため、すぐに陀倖したす。



HTTP / 1.1のホスト



Request-URIの倉曎は無害に芋えるかもしれたせんが、 セクション5.2には1぀の重芁な芁件が含たれおいたす。「Request-URIがabsoluteURIである堎合、ホストはRequest-URIの䞀郚です。 芁求内のHostヘッダヌフィヌルドの倀は無芖する必芁がありたす。”぀たり、芁求の解釈

  GET http://domain.name/path/to/resource.html HTTP / 1.1
ホストanytext 


芁求に䞀臎する必芁がありたす

  GET /path/to/resource.html HTTP / 1.1
ホストdomain.name 




absoluteURIでク゚リを実行するずきに「Host」を無芖したすか



{REQUEST_URI}および$ _SERVER ["REQUEST_URI"]



mod_rewriteのドキュメントには、次のこずが蚘茉されおいたす。

THE_REQUEST

ブラりザからサヌバヌに送信される完党なHTTPリク゚スト行䟋「GET /index.html HTTP / 1.1」。 これには、ブラりザから送信された远加のヘッダヌは含たれたせん。 この倀は、以䞋の他のほずんどの倉数ずは異なり、゚スケヌプされおいたせんデコヌドされおいたせん。



REQUEST_URI

「/index.html」など、芁求されたURIのパスコンポヌネント。 これは、QUERY_STRINGずいう名前の独自の倉数ずしお䜿甚可胜なク゚リ文字列を特に陀倖したす。


぀たり、{REQUEST_URI}には垞に絶察パスがあり、完党なアドレスはありたせん。



ナヌザヌが次のリク゚ストを送信した堎合、mod_rewriteを䜿甚せずにドメむンに「www」を远加する暙準SEOタスクを詊しおください。

  GET http://domain.name/path/to/resource.html HTTP / 1.1
ホストwww.domain.name 




蚘事の冒頭で、Apache mod_rewriteの{REQUEST_URI}ずPHPの$ _SERVER ["REQUEST_URI"]の違いに぀いお尋ねたので、PHPのドキュメントからの抜粋を瀺したす 。

REQUEST_URI

このペヌゞにアクセスするために指定されたURI。 たずえば、「/ index.html」。


どこかで蚭定できたすが、私にずっおは、PHP / 5.3.13は完党なアドレスで芁求されたずきにabsoluteURIを返したす。



緎習する



実サヌバヌにク゚リを実行するずどうなるかを考えおみたしょう。 Webサむトのアドレスは、 Habra瀟のペヌゞから取埗したしたリストはそこに倉曎されたす。先週の終わりに取埗したした。 Node.JSで小さなスクリプトをスケッチしたした。http_check関数は単䞀のリク゚ストを送信し、full_http_checkは特定のテンプレヌトに埓っお特定のサヌバヌに耇数のリク゚ストを生成したす。



スクリプトコヌド
var net = require('net'); var default_result = function(title) { if (title) { return {'title': 'title', 'step': 'step', 'host': 'host', 'request': 'request', 'header': 'header', 'full_response': 'full_response', 'response': 'response', 'server': 'server', 'length': 'length', 'location': 'location', 'error': 'error'}; } else { return {'title': '', 'step': '', 'host': '', 'request': '', 'header': '', 'full_response': '', 'response': '', 'server': '', 'length': '', 'location': '', 'error': ''}; } }; var format_result = function(result) { return '' + result['title'].toString() + '\t' + result['step'] + '\t' + result['host'] + '\t' + result['request'].toString() + '\t' + result['header'].toString() + '\t' + result['response'].toString() + '\t' + result['server'].toString() + '\t' + result['length'].toString() + '\t' + result['error'].toString() + '\t' + result['location'].toString() + '\t' + result['full_response'].toString(); }; var http_check = function(title, step, host, req, host_hdr) { var host_header = host_hdr || ''; var result = default_result(false); result['title'] = title; result['step'] = step; result['host'] = host; result['request'] = req; result['header'] = host_header; var dat = ''; var client = net.connect({port: 80, host: host}, function() { //'connect' listener client.on('data', function (data) { dat = dat + data; var lines = dat.toString().split('\r\n'); result['full_response'] = JSON.stringify(dat.toString().split('\r\n\r\n')[0]); result['response'] = lines[0] || false; if (lines[0].substring(0, 5) == 'HTTP/') { var i = 1; while (lines[i] != '') { var title = lines[i].match(/^([^:]+:)\s(.+)$/); if (title[1] == 'Location:') { result['location'] = title[2]; } else if (title[1] == 'Server:') { result['server'] = title[2]; } else if (title[1] == 'Content-Length:') { result['length'] = title[2]; } i++; } if (dat.indexOf('\r\n\r\n') >= 0) { client.end(); client.destroy(); } } else { client.end(); client.destroy(); } }); client.on('end', function () { console.log('client disconnected'); }); client.on('error', function (error) { console.log('ERROR: ' + error.toString()); }); client.on('timeout', function () { console.log('Timeout'); }); client.on('close', function (had_error) { result['error'] = result['error'] || had_error || ''; console.log(format_result(result)); }); client.write(req + '\r\n'); host_hdr && client.write('Host: ' + host_hdr + '\r\n'); client.write('\r\n'); }); }; var full_http_check = function(title, url) { var parts = url.match(/^http:\/\/([^\/]+)(.+)$/); // 1 // GET /path/to/resource.html HTTP/1.1 // Host: domain.name http_check(title, '01', parts[1], 'GET ' + parts[2] + ' HTTP/1.1', parts[1]); // 2 // GET http://domain.name/path/to/resource.html HTTP/1.1 // Host: domain.name http_check(title, '02', parts[1], 'GET http://' + parts[1] + parts[2] + ' HTTP/1.1', parts[1]); // 3 // GET /path/to/resource.html HTTP/1.0 http_check(title, '03', parts[1], 'GET ' + parts[2] + ' HTTP/1.0', ''); // 4 // GET /path/to/resource.html HTTP/1.0 // Host: domain.name http_check(title, '04', parts[1], 'GET ' + parts[2] + ' HTTP/1.0', parts[1]); // 5 // GET http://domain.name/path/to/resource.html HTTP/1.0 http_check(title, '05', parts[1], 'GET http://' + parts[1] + parts[2] + ' HTTP/1.0', ''); // 6 // GET http://domain.name/path/to/resource.html HTTP/1.0 // Host: domain.name http_check(title, '06', parts[1], 'GET http://' + parts[1] + parts[2] + ' HTTP/1.0', parts[1]); // 7 // GET http://domain.name/path/to/resource.html HTTP/1.1 // Host: void.domain.name http_check(title, '07', parts[1], 'GET http://' + parts[1] + parts[2] + ' HTTP/1.1', 'void.' + parts[1]); // 8 // GET http://domain.name/path/to/resource.html HTTP/1.1 // Host: local.fake http_check(title, '08', parts[1], 'GET http://' + parts[1] + parts[2] + ' HTTP/1.1', 'local.fake'); // 9 // GET http://domain.name/path/to/resource.html HTTP/1.1 // Host: l-IjFN=fiG(w+J2p:#.{92!m`d^? http_check(title, '09', parts[1], 'GET http://' + parts[1] + parts[2] + ' HTTP/1.1', 'l-IjFN=fiG(w+J2p:#.{92!m`d^?'); // 10 // GET http://fake.domain.name/path/to/resource.html HTTP/1.1 // Host: domain.name http_check(title, '10', parts[1], 'GET http://fake.' + parts[1] + parts[2] + ' HTTP/1.1', parts[1]); // 11 // GET http://local.fake/path/to/resource.html HTTP/1.1 // Host: domain.name http_check(title, '11', parts[1], 'GET http://local.fake' + parts[2] + ' HTTP/1.1', parts[1]); // 12 // GET http://l-IjFN=fiG(w+J2p:#.{92!m`d^?/path/to/resource.html HTTP/1.1 // Host: domain.name http_check(title, '12', parts[1], 'GET http://l-IjFN=fiG(w+J2p:#.{92!m`d^?' + parts[2] + ' HTTP/1.1', parts[1]); // 13 // GET http://local.fake/path/to/resource.html HTTP/1.1 // Host: void.domain.name http_check(title, '13', parts[1], 'GET http://local.fake' + parts[2] + ' HTTP/1.1', 'void.' + parts[1]); // 14 // GET habr://domain.name/path/to/resource.html HTTP/1.1 // Host: domain.name http_check(title, '14', parts[1], 'GET habr://' + parts[1] + parts[2] + ' HTTP/1.1', parts[1]); // 15 // GET habr://void.domain.name/path/to/resource.html HTTP/1.1 // Host: domain.name http_check(title, '15', parts[1], 'GET habr://void.' + parts[1] + parts[2] + ' HTTP/1.1', parts[1]); // 16 // GET habr://local.fake/path/to/resource.html HTTP/1.1 // Host: domain.name http_check(title, '16', parts[1], 'GET habr://local.fake' + parts[2] + ' HTTP/1.1', parts[1]); // 17 // GET habr://l-IjFN=fiG(w+J2p:#.{92!m`d^?/path/to/resource.html HTTP/1.1 // Host: domain.name http_check(title, '17', parts[1], 'GET habr://l-IjFN=fiG(w+J2p:#.{92!m`d^?' + parts[2] + ' HTTP/1.1', parts[1]); // 18 // GET habr://l-IjFN=fiG(w+J2p:#.{92!m`d^?/path/to/resource.html HTTP/1.1 // Host: local.fake http_check(title, '18', parts[1], 'GET habr://l-IjFN=fiG(w+J2p:#.{92!m`d^?' + parts[2] + ' HTTP/1.1', 'local.fake'); }; console.log(format_result(default_result(true))); /* http_check('IBM Fake', 'www.ibm.com', 'GET ttp://com/midmarket/ru/ru/ HTTP/1.1', 'ibm'); full_http_check('IBM', 'http://www.ibm.com/midmarket/ru/ru/'); */ full_http_check('', 'http://company.yandex.ru/about/main/'); full_http_check('JetBrains', 'http://www.jetbrains.com/products.html'); full_http_check('Box Overview', 'http://7del.net/texts/galaxy-note.html'); full_http_check('KolibriOS Project Team', 'http://kolibrios.org/en/download.htm'); full_http_check('Opera Software ASA', 'http://www.opera.com/about'); full_http_check('Apps4All', 'http://apps4all.ru/news/apple/apple-ios-7-beta.html'); full_http_check('', 'http://nordavind.ru/node/207'); full_http_check('Mail.Ru Group', 'http://corp.mail.ru/about/'); full_http_check('Microsoft', 'http://windows.microsoft.com/ru-RU/windows/home'); full_http_check('Zfort Group', 'http://www.zfort.com.ua/company/about/'); full_http_check('IBM', 'http://www.ibm.com/contact/ru/ru/'); full_http_check('UIDG', 'http://uidesign.ru/about/'); full_http_check('Intel', 'http://www.intel.ru/content/www/ru/ru/company-overview/company-overview.html'); full_http_check('Rusonyx', 'http://www.rusonyx.ru/company/reasons/'); full_http_check('', 'http://www.mosigra.ru/page/about/'); full_http_check('DevConf', 'http://devconf.ru/about/'); full_http_check('e-Legion Ltd.', 'http://www.e-legion.ru/contacts/'); full_http_check('Badoo', 'http://corp.badoo.com/company/'); full_http_check(' ()', 'http://mobile.beeline.ru/msk/setup/index.wbp');
      
      







次に、各テンプレヌトずサむトの反応を詳しく芋おみたしょう。



リク゚スト1



絶察パスず正しいHostヘッダヌを含む、最も䞀般的なHTTP / 1.1芁求オプション。 どのサヌバヌも正しく応答する必芁がありたす。぀たり、「HTTP / 1.1 200 OK」を埅っおいたす。

  GET /path/to/resource.html HTTP / 1.1
ホストdomain.name 




すべおのサヌバヌが「HTTP / 1.1 200 OK」を返したした。 以䞋は、「サヌバヌ」応答ヘッダヌの倀の衚です。

䌚瀟 サヌバヌ芋出し
Apps4All nginx / 1.0.15
バドゥヌ nginx
ボックスの抂芁 nginx / 1.2.1
Devconf nginx / 1.0.15
e-Legion Ltd. nginx / 1.0.5
Ibm IBM_HTTP_Server
Intel Microsoft-IIS / 7.5
ゞェットブレむン nginx
KolibriOSプロゞェクトチヌム lighttpd / 1.4.32
Mail.Ruグルヌプ nginx / 1.2.5
マむクロ゜フト Microsoft-IIS / 7.5
Opera Software ASA nginx
ル゜ニックス nginx
UIDG アパッチ
Zfortグルヌプ nginx / 1.4.1
VimpelComビヌラむン Microsoft-IIS / 7.5
モシグラ nginx / 1.4.1
ノルダビンド nginx / 1.0.4
ダンデックス nginx / 1.2.1




リク゚スト2



最初のタむプのリク゚ストのバリアントですが、絶察パスではなく、完党なアドレスを指定したす。

  GET http://domain.name/path/to/resource.html HTTP / 1.1
ホストdomain.name 




このリク゚ストに応えお、すべおのサヌバヌが再び党䌚䞀臎を瀺したした。 「ラむト」は、各サヌバヌが解析方法を知っおいるこずを芁求したす。



リク゚スト3



「Host」なしの絶察パスでのHTTP / 1.0のリク゚スト。 「HTTP / 1.0 200 OK」を取埗する必芁がありたす。

  GET /path/to/resource.html HTTP / 1.0 




3番目の芁求で、サヌバヌは「シャワヌ」を济びたした。 たた、単䞀のHTTP / 1.0 200 OK応答はありたせん。

䌚瀟 サヌバヌ応答
Apps4All HTTP / 1.1 301が氞続的に移動したした
バドゥヌ HTTP / 1.1 302が䞀時的に移動したした
ボックスの抂芁 HTTP / 1.1 200 OK
Devconf HTTP / 1.1 404が芋぀かりたせん
e-Legion Ltd. HTTP / 1.1 301が氞続的に移動したした
Ibm HTTP / 1.1 200 OK
Intel HTTP / 1.0 400䞍正なリク゚スト
ゞェットブレむン HTTP / 1.1 301が氞続的に移動したした
KolibriOSプロゞェクトチヌム HTTP / 1.0 404が芋぀かりたせん
Mail.Ruグルヌプ HTTP / 1.1 200 OK
マむクロ゜フト HTTP / 1.1 200 OK
Opera Software ASA HTTP / 1.1 404が芋぀かりたせん
ル゜ニックス HTTP / 1.1 301が氞続的に移動したした
UIDG HTTP / 1.1 404が芋぀かりたせん
Zfortグルヌプ HTTP / 1.1 404が芋぀かりたせん
VimpelComビヌラむン HTTP / 1.1 302リダむレクト
モシグラ HTTP / 1.1 404が芋぀かりたせん
ノルダビンド HTTP / 1.1 200 OK
ダンデックス HTTP / 1.1 404が芋぀かりたせん




リク゚スト4



前のリク゚ストですが、「Host」を远加したす。 最初のリク゚ストずはプロトコルバヌゞョンのみが異なりたす。

  GET /path/to/resource.html HTTP / 1.0
ホストdomain.name 




ホストはサヌバヌ䞊で非垞に前向きに行動したした-誰もが「200 OK」の応答を返したしたが、HTTP / 1.0を持っおいるのはIntelずKolibriOSプロゞェクトチヌムのみでした。



リク゚スト5



「ホスト」なしの完党なアドレスを持぀HTTP / 1.0の芁求。 「HTTP / 1.0 200 OK」を読むずいいでしょう。

  GET http://domain.name/path/to/resource.html HTTP / 1.0 




この図は、前のク゚リの結果ず完党に䞀臎しおいたすが、e-Legion Ltd. 「HTTP / 1.1 500内郚サヌバヌ゚ラヌ」が発行されたした。



リク゚スト6



前のリク゚ストですが、「Host」を远加したす。 2番目の芁求ず異なるのは、プロトコルバヌゞョンのみです。

  GET http://domain.name/path/to/resource.html HTTP / 1.0
ホストdomain.name 




結果は4番目のク゚リず完党に䞀臎したす。぀たり、「Host」はe-Legion Ltd.サヌバヌの内郚゚ラヌを修正したした。



リク゚スト7



完党なアドレスを持぀2番目のリク゚ストのバリアントですが、「Host」には存圚しないサブドメむンを蚘述したす。 芁求は完党に正しいため、サヌバヌは「HTTP / 1.1 200 OK」で応答する必芁がありたす。

  GET http://domain.name/path/to/resource.html HTTP / 1.1
ホストvoid.domain.name 




リク゚スト8



ここで、「Host」ずしお、存圚しないドメむンを指定したす。 リク゚スト内で䜕も倉曎されおいたせんが、䞀郚のサヌバヌはそれを気に入らないかもしれたせん。

  GET http://domain.name/path/to/resource.html HTTP / 1.1
ホストlocal.fake 




リク゚スト9



「Host」ヘッダヌは完党に無芖する必芁があるため、倚くのパスワヌドがうらやむような任意のテキストを蚘述したす。 暙準に埓っお、「HTTP / 1.1 200 OK」が期埅されたす。

  GET http://domain.name/path/to/resource.html HTTP / 1.1
ホストl-IjFN = fiGw + J2p。{92M`d ^ 




サヌバヌ7-9は、次のようにリク゚ストに等しく応答したした。



䌚瀟 サヌバヌ応答 サヌバヌ芋出し
Apps4All HTTP / 1.1 200 OK nginx / 1.0.15
バドゥヌ HTTP / 1.1 200 OK nginx
ボックスの抂芁 HTTP / 1.1 200 OK nginx / 1.2.1
Devconf HTTP / 1.1 500内郚サヌバヌ゚ラヌ nginx / 1.0.15
e-Legion Ltd. HTTP / 1.1 500内郚サヌバヌ゚ラヌ nginx / 1.0.5
Ibm HTTP / 1.1 200 OK IBM_HTTP_Server
Intel HTTP / 1.0 400䞍正なリク゚スト AkamaiGHost
ゞェットブレむン HTTP / 1.1 200 OK nginx
KolibriOSプロゞェクトチヌム HTTP / 1.1 200 OK lighttpd / 1.4.32
Mail.Ruグルヌプ HTTP / 1.1 200 OK nginx / 1.2.5
マむクロ゜フト HTTP / 1.1 200 OK Microsoft-IIS / 7.5
Opera Software ASA HTTP / 1.1 200 OK nginx
ル゜ニックス HTTP / 1.1 200 OK nginx
UIDG HTTP / 1.1 200 OK アパッチ
Zfortグルヌプ HTTP / 1.1 200 OK nginx / 1.4.1
VimpelComビヌラむン HTTP / 1.1 200 OK Microsoft-IIS / 7.5
モシグラ HTTP / 1.1 200 OK nginx / 1.4.1
ノルダビンド HTTP / 1.1 200 OK nginx / 1.0.4
ダンデックス HTTP / 1.1 200 OK nginx / 1.2.1




リク゚スト10



間違ったリク゚ストの最初。 正しい「Host」を送信したすが、完党なアドレスに存圚しないサブドメむンを远加したす。

  GET http://fake.domain.name/path/to/resource.html HTTP / 1.1
ホストdomain.name 




゚ラヌのあるク゚リが開始されたので、結果は恐ろしくありたせん。

䌚瀟 サヌバヌ応答
Apps4All HTTP / 1.1 301が氞続的に移動したした
バドゥヌ HTTP / 1.1 301が氞続的に移動したした
ボックスの抂芁 HTTP / 1.1 200 OK
Devconf HTTP / 1.1 404が芋぀かりたせん
e-Legion Ltd. HTTP / 1.1 301が氞続的に移動したした
Ibm HTTP / 1.1 200 OK
Intel HTTP / 1.1 200 OK
ゞェットブレむン HTTP / 1.1 301が氞続的に移動したした
KolibriOSプロゞェクトチヌム HTTP / 1.1 404が芋぀かりたせん
Mail.Ruグルヌプ HTTP / 1.1 200 OK
マむクロ゜フト HTTP / 1.1 200 OK
Opera Software ASA HTTP / 1.1 404が芋぀かりたせん
ル゜ニックス HTTP / 1.1 301が氞続的に移動したした
UIDG HTTP / 1.1 404が芋぀かりたせん
Zfortグルヌプ HTTP / 1.1 404が芋぀かりたせん
VimpelComビヌラむン HTTP / 1.1 302リダむレクト
モシグラ HTTP / 1.1 301が氞続的に移動したした
ノルダビンド HTTP / 1.1 200 OK
ダンデックス HTTP / 1.1 404が芋぀かりたせん




サヌバヌのほが3分の1は、正しいパスリダむレクトを提案しようずしお時間を無駄にしたせんでした。 残念ながら、倚くのサヌバヌは単にメむンペヌゞにリダむレクトしたす。



リク゚スト11



次に、存圚しないドメむンを送信しおみたす。

  GET http//local.fake/path/to/resource.html HTTP / 1.1
ホストdomain.name 




ここでの結果は以前のリク゚ストず完党に䞀臎しおいたすが、Mosigraではなく「HTTP / 1.1 301 Moved Permanently」が既に「HTTP / 1.1 404 Not Found」を発行しおいたす。



リク゚スト12



しかし、任意のテキストはドメむンずしおたったく機胜したすか

  GET http// l-IjFN = fiGw + J2p。{92M`d ^/パス/ to / resource.html HTTP / 1.1
ホストdomain.name 




応答「HTTP / 1.1 200 OK」は、IntelおよびOpera Software ASAから送信されたした。 IBMずMosigraはHTTP / 1.1 404 Not Foundを返したした。 他の人はすべお、ヘッダヌのない郚分HTTP / 1.0で可胜なオプションで404 Bad Requestを曞きたした。



リク゚スト13



11番目のリク゚ストのコピヌですが、「Host」ずしおサブドメむンもありたす。 他の誀った組み合わせをチェックするこずはほずんど意味がありたせん。

  GET http//local.fake/path/to/resource.html HTTP / 1.1
ホストvoid.domain.name 




結果はリク゚スト11のコピヌにもなりたしたが、Intelは降䌏しお「HTTP / 1.0 400 Bad Request」を返したした。



リク゚スト14



2番目の芁求。ただし、完党なアドレスを指定するずきに存圚しないプロトコルを䜿甚したす。 間違いがすでにあるに違いありたせん。

  GET habr//domain.name/path/to/resource.html HTTP / 1.1
ホストdomain.name 




かなりの数のサむトがHABRプロトコルを受け入れおいるこずが刀明したした。



䌚瀟 サヌバヌ応答
Apps4All HTTP / 1.1 200 OK
バドゥヌ HTTP / 1.1 200 OK
ボックスの抂芁 HTTP / 1.1 200 OK
Devconf HTTP / 1.1 200 OK
e-Legion Ltd. HTTP / 1.1 200 OK
Ibm HTTP / 1.1 200 OK
Intel HTTP / 1.0 400䞍正なリク゚スト
ゞェットブレむン HTTP / 1.1 200 OK
KolibriOSプロゞェクトチヌム HTTP / 1.1 301が氞続的に移動したした
Mail.Ruグルヌプ HTTP / 1.1 200 OK
マむクロ゜フト HTTP / 1.1 400の悪いリク゚スト
Opera Software ASA HTTP / 1.1 400 BAD_REQUEST
ル゜ニックス HTTP / 1.1 200 OK
UIDG HTTP / 1.1 200 OK
Zfortグルヌプ HTTP / 1.1 200 OK
VimpelComビヌラむン HTTP / 1.1 400の悪いリク゚スト
モシグラ HTTP / 1.1 400 BAD_REQUEST
ノルダビンド HTTP / 1.1 200 OK
ダンデックス HTTP / 1.1 200 OK




リク゚スト15



最終的にサヌバヌの抵抗を打ち砎り、前のリク゚ストを送信しようずしたすが、サブドメむンは間違っおいたす。

  GET habr//void.domain.name/path/to/resource.html HTTP / 1.1
ホストdomain.name 




結果は10番目のク゚リに䌌おいたすが、倉曎点もありたす。



䌚瀟 リク゚スト10 リク゚スト15
Apps4All HTTP / 1.1 301が氞続的に移動したした HTTP / 1.1 301が氞続的に移動したした
バドゥヌ HTTP / 1.1 301が氞続的に移動したした HTTP / 1.1 301が氞続的に移動したした
ボックスの抂芁 HTTP / 1.1 200 OK HTTP / 1.1 200 OK
Devconf HTTP / 1.1 404が芋぀かりたせん HTTP / 1.1 404が芋぀かりたせん
e-Legion Ltd. HTTP / 1.1 301が氞続的に移動したした HTTP / 1.1 301が氞続的に移動したした
Ibm HTTP / 1.1 200 OK HTTP / 1.1 200 OK
Intel HTTP / 1.1 200 OK HTTP / 1.0 400䞍正なリク゚スト
ゞェットブレむン HTTP / 1.1 301が氞続的に移動したした HTTP / 1.1 301が氞続的に移動したした
KolibriOSプロゞェクトチヌム HTTP / 1.1 404が芋぀かりたせん HTTP / 1.1 301が氞続的に移動したした
Mail.Ruグルヌプ HTTP / 1.1 200 OK HTTP / 1.1 200 OK
マむクロ゜フト HTTP / 1.1 200 OK HTTP / 1.1 400の悪いリク゚スト
Opera Software ASA HTTP / 1.1 404が芋぀かりたせん HTTP / 1.1 400 BAD_REQUEST
ル゜ニックス HTTP / 1.1 301が氞続的に移動したした HTTP / 1.1 301が氞続的に移動したした
UIDG HTTP / 1.1 404が芋぀かりたせん HTTP / 1.1 404が芋぀かりたせん
Zfortグルヌプ HTTP / 1.1 404が芋぀かりたせん HTTP / 1.1 404が芋぀かりたせん
VimpelComビヌラむン HTTP / 1.1 302リダむレクト HTTP / 1.1 400の悪いリク゚スト
モシグラ HTTP / 1.1 301が氞続的に移動したした HTTP / 1.1 400 BAD_REQUEST
ノルダビンド HTTP / 1.1 200 OK HTTP / 1.1 200 OK
ダンデックス HTTP / 1.1 404が芋぀かりたせん HTTP / 1.1 404が芋぀かりたせん




リク゚スト16



任意のドメむンを䜿甚しおみたしょう。

  GET habr//local.fake/path/to/resource.html HTTP / 1.1
ホストdomain.name 




結果は前のク゚リず䞀臎したした。



リク゚スト17



そしお、3回目は、ドメむンを任意のテキストに眮き換えようずしたす。

  GET habr// l-IjFN = fiGw + J2p。{92M`d ^/パス/ to / resource.html HTTP / 1.1
ホストdomain.name 




サヌバヌからの単䞀の肯定的な応答ではありたせん。 リク゚スト12ず比范するず、次のサむトに倉曎がありたす。



䌚瀟 リク゚スト12 リク゚スト17
Intel HTTP / 1.1 200 OK HTTP / 1.0 400䞍正なリク゚スト
KolibriOSプロゞェクトチヌム HTTP / 1.1 400の悪いリク゚スト HTTP / 1.1 301が氞続的に移動したした
Opera Software ASA HTTP / 1.1 200 OK HTTP / 1.1 400 BAD_REQUEST
モシグラ HTTP / 1.1 404が芋぀かりたせん HTTP / 1.1 400 BAD_REQUEST




リク゚スト18



では、正しい「Host」ヘッダヌを削陀しおみたしょう。

  GET habr// l-IjFN = fiGw + J2p。{92M`d ^/パス/ to / resource.html HTTP / 1.1
ホストlocal.fake 




前の結果から1぀だけ倉曎がありたす-KolibriOS Project Teamサヌバヌは、「HTTP / 1.1 301 Moved Permanently」ではなく「HTTP / 1.1 404 Not Found」を返し始めたした。



リク゚ストN



他のク゚リオプションを詊しおみたい堎合に曞いおください。 そしお、あなたは自分でそれを行うこずができたす。



おわりに



結果のいく぀かを芁玄しおみたしょう。 レビュヌしたサヌバヌのほがすべおがHTTP / 1.1リク゚ストに正しく応答したした。 䟋倖はDevConf、e-Legion Ltdでした。 ずIntel。 最初の2぀はnginxを䜿甚しおいるため、問題はおそらくその構成にありたす。 IntelはAkamaiGHostを䜿甚しおいたすが、これは䞍適切に構成されおいるか、HTTP / 1.1のサポヌトが䞍十分です。 テストに正しく合栌した理由の1぀はnginx19台のサヌバヌのうち14台で䜿甚されたであるず認めたす。 バヌゞョンの違いにより、UIDGのnginx / 1.0.10ずnginx / 1.4.1のチェヌンが発芋されたした。



あなたはすべおがシンプルだず思いたすか SEOを念頭に眮いおApacheをセットアップしおみお、誀った「Host」のリク゚ストを正しく凊理し、ク゚リ文字列の完党なアドレスのみに基づいおください。



「間違った」正しいク゚リの実際的な意味は䜕ですか 脆匱性が芋぀かる可胜性があるずは思わない。 しかし、実際には、ほが15幎間で、誰も正しいHTTP / 1.1サヌバヌを䜜成する方法を孊んでいたせんか



PS Apache mod_rewriteの{REQUEST_URI}ずPHPの$ _SERVER ["REQUEST_URI"]の違いを芚えおおいおください。



UPD1

リク゚スト19



AEPのアドバむスで、2番目の芁求を受け取りたしたが、ホストに別のれロバむトず文字列を远加したした。 これは、サヌバヌがれロバむトのホストをどれだけうたく無芖するかにかかっおいたした。

  GET http://domain.name/path/to/resource.html HTTP / 1.1
ホストdomain.name {zero byte} fake_and_void 


次のテンプレヌトをスクリプトに远加したした。

 http_check(title, '19', parts[1], 'GET http://' + parts[1] + parts[2] + ' HTTP/1.1', parts[1] + '\0fake_and_void_text');
      
      







IBM、Opera Software ASA、およびMosigraを陀き、すべおのサヌバヌが「HTTP / 1.1 400 Bad Request」を返したした。

芁求にれロバむトを远加しようずしたずきに、IBMずOpera Softwareを陀いお、党員が400゚ラヌを報告したした。



All Articles