POST и headers

Discussion in 'PHP' started by alex.k12, 3 Jun 2009.

  1. alex.k12

    alex.k12 New Member

    Joined:
    3 May 2009
    Messages:
    19
    Likes Received:
    0
    Reputations:
    0
    Нужно сформировать правильный POST запрос в CURL. Сначала я делаю обычный запрос через браузер и ловлю отправленные и полученные хедеры и содержимое запроса (с помощью аддона firebug на файрфоксе), потом воспроизвожу это в своем запросе с помощью curl. Так вот, firebug выдает мне среди прочих хедеров следующие:

    Content-Type:multipart/form-data; boundary=---------------------------14162188131998
    Content-Length:118018

    Другой перехватчик хедеров, HttpAnalyzer, их не видит

    1. Важны ли эти заголовки при запросе, можно ли их опустить?
    2. Как правильно сформировать запрос с телом (картинкой) и параметрами?
    3. Как узнать Content-Length картинки перед отправкой? В гугле по этой теме есть очень много, но ничего по делу.
     
  2. NaX[no]rT

    NaX[no]rT Members of Antichat

    Joined:
    3 Sep 2005
    Messages:
    489
    Likes Received:
    201
    Reputations:
    202
    читаем и учимся http://ru.php.net/manual/de/function.curl-setopt.php
     
    _________________________
  3. Dr.TRO

    Dr.TRO Member

    Joined:
    29 Jan 2009
    Messages:
    20
    Likes Received:
    7
    Reputations:
    10
    1. Длина контента не оч вроде как ( если скачивал файлы думаю видел что иногдауказываеться какого он размера а иногда нет вот от указания или неуказания заголовка этого и зависит )
    2. http://ru.php.net/manual/ru/function.curl-setopt.php тонко намекну ( http://curl.haxx.se/libcurl/php/examples/httpfileupload.html )
    3. Ты картинку все равно
     
  4. d_x

    d_x Banned

    Joined:
    25 Mar 2008
    Messages:
    558
    Likes Received:
    650
    Reputations:
    210
    1. нельзя опускать
    2.
    Code:
    POST адрес HTTP/1.0
    Content-Type: multipart/form-data; boundary=некоторое_достаточно_уникальное_значение [boundary]
    Host: хост
    Content-Length: длина_содержимого
    [boundary]
    Content-Disposition: form-data; name="file"; filename="имя_файла"
    Content-Type: image/jpeg (тип)
    
    [содержимое картинки]
    [boundary]
    
    3. В content-length записывается длина всего отправляемого содержимого без заголовков. Определить можно strlen.
     
  5. alex.k12

    alex.k12 New Member

    Joined:
    3 May 2009
    Messages:
    19
    Likes Received:
    0
    Reputations:
    0
    Вот-вот. Это то самое, что возвращает мне перехватчик при отправке моего сообщения. Я только не пойму, где это настраивается. Или достаточно просто указать вот эти хедеры

    Content-Type: multipart/form-data; boundary=некоторое_достаточно_уникальное_значение
    Host: хост
    Content-Length: длина_содержимого
    Content-Disposition: form-data; name="file"; filename="имя_файла"
    Content-Type: image/jpeg (тип)

    в CURLOPT_HTTPHEADER и параметры в CURLOPT_POSTFIELDS, а всё остальное курл сформирует сам?

    Content-length узнал с помощью strlen(file_get_contents('имя_файла'));

    Заинтересовался вот этим:
    1. CURLOPT_INFILESIZE : при закачке файла на удаленный сервер, следует использовать этот параметр для указания ожидаемого размера файла. (указать вместо Content-Length хедера?)
    2. CURLOPT_UPLOAD : Установка этого параметра в ненулевое значение означает, что будет производиться закачка файла на удаленный сервер.(похоже тоже надо указать, поскольку я отправляю файл)
    3. CURLOPT_INFILE : Файл, содержащий данные для передачи. (может, надо использовать это вместо указания имени файла среди параметров CURLOPT_POSTFIELDS?)

    И еще, какая разница между указанием user-agent в хедерах CURLOPT_HTTPHEADER и в CURLOPT_USERAGENT?
     
    #5 alex.k12, 3 Jun 2009
    Last edited: 3 Jun 2009
  6. Dr.TRO

    Dr.TRO Member

    Joined:
    29 Jan 2009
    Messages:
    20
    Likes Received:
    7
    Reputations:
    10
    Code:
    function post_file ($url, $avars) {		
    	$parsed_url = parse_url($url);		
    	$host = $parsed_url['host'];
    	$path = $parsed_url['path'];	
    		if($avars['type'] == 'content'){
    		$file .= "filename=".$avars['filename']."&content=".$avars['value'];
    	}
    	if($avars['type'] == 'link'){
    		$filetemp = file_get_contents($avars['value']);
    		$filetopost = base64_encode($filetemp);
    		$file .= "filename=".$avars['filename']."&content=".$filetopost;
    	}
    	if(isset($parsed_url['query'])) {			
    		$query = $parsed_url['query'];			
    	}					
    	$socket = @fsockopen($host, 80, $errno, $errstr, $this->timeout) or die ("Не могу открыть сокет :".$errstr."(".$errno.")");	
    	if ( isset($query) ) {				
    		$out = "POST ".$path."?".$query." HTTP/1.1\r\n";				
    	} else {				
    		$out = "POST ".$path." HTTP/1.1\r\n";				
    	}			
    	$out .= "Host: ".$host."\r\n";			
    	$out .= "User-Agent: Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 5.1; YPC 3.0.1; .NET CLR 1.1.4322; .NET CLR 2.0.50727)\r\n";
    	$out .= "Content-Type: application/x-www-form-urlencoded\r\n";
    	$out .= "Content-Length: ".strlen($file)."\r\n";
    	if(!isset($headers['Connection'])) {						
    		$out .= "Connection: Close\r\n";				
    	}			
    	$out .= "\r\n";	
    	$out .= $file;
    	fwrite($socket, $out);		
    	while (!feof($socket)) {
    		$in .= fgets($socket, 128);
    	}		  
    	fclose($socket);	
    	return $in;						
    }
    post_file ($url ( string ), $avars ( array ), $headers ( array )) - запрос типа POST который в себе еще передает файл, $avars - данные запроса ( без них функция не выполниться ) ( должны идти массивом следущего типа :
    $avars['type'] => 'link' ( тип - ссылка на локальный файл для загрузки ( так как реализованно посредством функции file_get_contents можно попробовать и удаленные файлы)) || 'content' ( тип - содержимое )
    $avars['value'] => 'value' ( если тип - ссылка тогда здесь должна быть ссылка на файл, если же content то содержимое файла закодированое посредством функции base64_encode )
    $avars['filename'] => 'filename' ( имя файла в запросе )
    ), возвращает ответ сервера на запрос.
     
  7. попугай

    попугай Elder - Старейшина

    Joined:
    15 Jan 2008
    Messages:
    1,520
    Likes Received:
    401
    Reputations:
    196
    Самая известная статья для новичков.
    http://www.phpclub.ru/detail/article/http_request


    проще filesize('имя файла');
     
  8. .:EnoT:.

    .:EnoT:. Сексуальное чудовище

    Joined:
    29 May 2007
    Messages:
    803
    Likes Received:
    559
    Reputations:
    50
    Ему кажется пример с курлом был нужен..
    Простой POST передаётся строкой в CURLOPT_POSTFIELDS.
    POST с boundary передаётся туда же, только массивом. Всё, что в boundary передаётся с добавлением собачки @

    а вы тут намутили )
     
  9. Dr.TRO

    Dr.TRO Member

    Joined:
    29 Jan 2009
    Messages:
    20
    Likes Received:
    7
    Reputations:
    10
    смотри мой третий пост =\

    http://curl.haxx.se/libcurl/php/examples/httpfileupload.html
     
  10. alex.k12

    alex.k12 New Member

    Joined:
    3 May 2009
    Messages:
    19
    Likes Received:
    0
    Reputations:
    0
    Мне нужно абсолютно точно воспроизвести запрос из браузера в своей программе с помощью курла. Вот что надо отправить в хедерах:

    Code:
    (Request-Line)	POST /site.php?par=1 HTTP/1.1
    Host: www.anysite.ru
    User-Agent: Mozilla/5.0 (Windows; U; Windows NT 6.0; ru; rv:1.9.0.10) Gecko/2009042316 Firefox/3.0.10
    Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
    Accept-LanguageL: ru,en-us;q=0.7,en;q=0.3
    Accept-Encoding: gzip,deflate
    Accept-Charset: windows-1251,utf-8;q=0.7,*;q=0.7
    Keep-Alive: 43200
    Connection: keep-alive
    Referer: http://www.anysite.ru/fol/
    Cookie: PHPSESSID=2lpliicfgkjfnmjhbkm6dbn4t1
    Content-Type: multipart/form-data; boundary=---------------------------21718375316139
    Content-Length: 48176
    В самом POST-запросе надо отправить следующее:

    Code:
    Content-Type: multipart/form-data; boundary=---------------------------21718375316139
    Content-Length: 48176
    
    -----------------------------21718375316139
    Content-Disposition: form-data; name="param1"
    
    123
    -----------------------------21718375316139
    Content-Disposition: form-data; name="param2"
    
    123
    -----------------------------21718375316139
    Content-Disposition: form-data; name="email"
    
    
    -----------------------------21718375316139
    Content-Disposition: form-data; name="imagefile"; filename="pic.jpeg"
    Content-Type: image/jpeg
    
    ÿØÿà�JFIF��H�H��ÿþ�;CREATOR: gd-jpeg v1.0 (using IJG JPEG v62), quality = 80
    ÿÛ�C�
    
    (дальше пошло содержимое картинки)
    Для этого я пишу следующий запрос:

    PHP:
    $postdata = array( 'param1' => '123',
                       
    'param2' => '123',
                       
    'email' => '',
                       
    'imagefile' => "@".'c:\www\pic.jpg');

        
    $ch curl_init();

        
    $headers[] = 'Host:www.anysite.ru';    
        
    $headers[] = 'User-Agent: Mozilla/5.0 (Windows; U; Windows NT 6.0; ru; rv:1.9.0.10) Gecko/2009042316 Firefox/3.0.10';
        
    $headers[] = 'Accept:text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8';
        
    $headers[] = 'Accept-Language:ru,en-us;q=0.7,en;q=0.3';
        
    $headers[] = 'Accept-Encoding:gzip,deflate';
        
    $headers[] = 'Accept-Charset:windows-1251,utf-8;q=0.7,*;q=0.7';
        
    $headers[] = 'Keep-Alive:43200';
        
    $headers[] = 'Connection:keep-alive';
        
    $headers[] = 'Referer:http://www.anysite.ru/fol/';
        
    $headers[] = 'Cookie:PHPSESSID=2lpliicfgkjfnmjhbkm6dbn4t1';
        
    $headers[] = 'Content-Type:multipart/form-data; boundary=---------------------------21718375316139';
        
    $headers[] = 'Content-Length:48176';

        
    curl_setopt($chCURLOPT_HTTPHEADER$headers);
        
    curl_setopt($chCURLOPT_PROXY$proxy);
        
    curl_setopt($chCURLOPT_URL"http://www.anysite.ru/site.php?par=1");
        
    curl_setopt($chCURLOPT_RETURNTRANSFER1);
         
    curl_setopt($chCURLOPT_POST1);
        
    curl_setopt($chCURLOPT_HEADER0);
        
    curl_setopt($chCURLOPT_POSTFIELDS$postdata);
        
        
    $resultcurl_exec ($ch);
        
    curl_close ($ch);
    На сервере, куда я отправляю POST, стоит проверка на корректность запросов и не пропускает вот этот вот мой curl-запрос, значит что-то в нём не хватет или наоборот лишнее. Что?
     
    #10 alex.k12, 3 Jun 2009
    Last edited: 3 Jun 2009
  11. mailbrush

    mailbrush Well-Known Member

    Joined:
    24 Jun 2008
    Messages:
    1,997
    Likes Received:
    996
    Reputations:
    155
    Ну ты и намутил тут...
    PHP:
    $headers[] = "Cookie:PHPSESSID='2lpliicfgkjfnmjhbkm6dbn4t1';
    Закрывающую кавычку не поставил... И вообще - это быдлокод, почитай гугл, php.net.
     
  12. .:EnoT:.

    .:EnoT:. Сексуальное чудовище

    Joined:
    29 May 2007
    Messages:
    803
    Likes Received:
    559
    Reputations:
    50
    Ужос..

    PHP:
    $postdata = array( 'param1' => '123',
                       
    'param2' => '123',
                       
    'email'  => '',
                       
    'imagefile' => '@' realpath('pic.jpg')
                     );

    $ch curl_init('http://www.anysite.ru/site.php?par=1');
    curl_setopt($chCURLOPT_HEADER0);
    curl_setopt($chCURLOPT_RETURNTRANSFER1);
    curl_setopt($chCURLOPT_POST1);
    curl_setopt($chCURLOPT_POSTFIELDS$postdata);
    $resultcurl_exec ($ch);
    curl_close ($ch); 


    ВСЁ! Больше тебе не нужны никакие заголовки!
     
    1 person likes this.
  13. alex.k12

    alex.k12 New Member

    Joined:
    3 May 2009
    Messages:
    19
    Likes Received:
    0
    Reputations:
    0
    mailbrush, это я всё упростил. на самом деле я беру id php-сессии из пришедших ранее set-cookie заголовков. Если ты думаешь, что проблема в id сессии, это 100% не так, тут всё правильно.

    Это как же, они не рассматриваются при проверке правильности запросов на сервере?
     
    #13 alex.k12, 3 Jun 2009
    Last edited: 3 Jun 2009
  14. alex.k12

    alex.k12 New Member

    Joined:
    3 May 2009
    Messages:
    19
    Likes Received:
    0
    Reputations:
    0
    Есть еще одна проблема, ошибка 417 Expectation Failed. Это баг сервера lighttpd, связанный с автоматической отправкой курлом хедера Expect: 100-continue.
    http://www.astahost.com/Help-Removing-Specific-Header-cURL-t14787.html
    Кто-нибудь сталкивался с этим?
     
  15. Dr.TRO

    Dr.TRO Member

    Joined:
    29 Jan 2009
    Messages:
    20
    Likes Received:
    7
    Reputations:
    10
    Блин отправляй все сокетом и не парь всем мозги
     
  16. mailbrush

    mailbrush Well-Known Member

    Joined:
    24 Jun 2008
    Messages:
    1,997
    Likes Received:
    996
    Reputations:
    155
    Какими сокетами??? Только курл!
     
  17. alex.k12

    alex.k12 New Member

    Joined:
    3 May 2009
    Messages:
    19
    Likes Received:
    0
    Reputations:
    0
    Почему же, можно и сокетами, только я с ними никогда не работал. Искал, но так и не понял алгоритма передачи параметров. Вот это возвращает Bad request (и понятно, нагородил тут)

    PHP:
        $body = Array(
        
    '-----------------------------23683118578968',
        
    'Content-Disposition: form-data; name="param1"',
        
    '\r\n',
        
    '123',
        
    '-----------------------------23683118578968',
        
    'Content-Disposition: form-data; name="param2"',
        
    '\r\n',
        
    '123',
        
    '-----------------------------23683118578968',
        
    'Content-Disposition: form-data; name="email"',
        
    '\r\n',
        
    '\r\n',
        
    '-----------------------------23683118578968',
        
    'Content-Disposition: form-data; name="imagefile"; filename="pic.jpg"',
        
    'Content-Type: image/jpeg',
        
    '\r\n',
        
    file_get_contents(realpath('pic.jpg')),
        
    '-----------------------------23683118578968',
        
    'Content-Disposition: form-data; name="param3"',
        
    '\r\n',
        
    '123');

        
    $clenght=strlen(implode("\r\n",$body));
        
        
    $a = array("POST http://www.anysite.ru/site.php?par=1 HTTP/1.1"
        
    "Host: www.anysite.ru"
        
    "User-Agent: Mozilla/5.0 (Windows; U; Windows NT 6.0; ru; rv:1.9.0.10) Gecko/2009042316 Firefox/3.0.10"
        
    "Accept:text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8"
        
    "Accept-Language:ru,en-us;q=0.7,en;q=0.3"
        
    "Accept-Encoding:gzip,deflate"
        
    "Accept-Charset:windows-1251,utf-8;q=0.7,*;q=0.7"
        
    "Keep-Alive:43200"
        
    "Connection:keep-alive"
        
    "Referer:http://www.anysite.ru/site/"
        
    "Cookie:PHPSESSID=$sessid"
        
    "Content-Type:multipart/form-data; boundary=---------------------------23683118578968",
        
    "Content-Length:$clenght",
        
    "\r\n"); 
        
        
    $post = array();
        
    $post $a $body;

        
    $f fsockopen('64.46.248.204','8080') or die('Can\'t connect'); 
        
    fwrite($f,implode("\r\n",$post)); 
        
    $in fread($f1048576);
        if (
    $in) {list(,$result) = explode("\r\n\r\n"$in2);}
        else 
    $result NULL;
        
    fclose($f);
     
  18. .:EnoT:.

    .:EnoT:. Сексуальное чудовище

    Joined:
    29 May 2007
    Messages:
    803
    Likes Received:
    559
    Reputations:
    50
    PHP:
    $post $a $body
    Это какбэ операция сложения, а не конкатенации.
    Замени хотя бы на:

    PHP:
    $post $a "\r\n" $body
    ну и это:
    PHP:
    fwrite($f,implode("\r\n",$post));
    на

    PHP:
    fwrite($f$post);
     
  19. alex.k12

    alex.k12 New Member

    Joined:
    3 May 2009
    Messages:
    19
    Likes Received:
    0
    Reputations:
    0
    Ну да, и затереть разделитель между хедерами и содержимым. Вообще я правильно мыслю? Или всё вот это
    PHP:
     $body = Array( 
        
    '-----------------------------23683118578968'
        
    'Content-Disposition: form-data; name="param1"'
        
    '\r\n'
        
    '123'
        
    '-----------------------------23683118578968'
        
    'Content-Disposition: form-data; name="param2"'
        
    '\r\n'
        
    '123'
        
    '-----------------------------23683118578968'
        
    'Content-Disposition: form-data; name="email"'
        
    '\r\n'
        
    '\r\n'
        
    '-----------------------------23683118578968'
        
    'Content-Disposition: form-data; name="imagefile"; filename="pic.jpg"'
        
    'Content-Type: image/jpeg'
        
    '\r\n'
        
    file_get_contents(realpath('pic.jpg')), 
        
    '-----------------------------23683118578968'
        
    'Content-Disposition: form-data; name="param3"'
        
    '\r\n'
        
    '123');
    можно заменить на это?

    PHP:
    $body "param1=123&param2=123&email=&imagefile=pic.jpg&param3=123";
     
    #19 alex.k12, 5 Jun 2009
    Last edited: 5 Jun 2009