Заголовки скручивания multipart/ форма уже отправлены

Уважаемые пользователи Stackru, я столкнулся с проблемой. Это выглядит следующим образом: В настоящее время я программирую инструмент управления для pfsense, который должен отправить многокомпонентную форму, которую сервер должен проверить и обработать. Это должно включить основанное на ваучере управление доступом на интерфейсе. Однако я получаю сообщение об ошибке, что мои заголовки уже отправлены. Я не отправил их.

мой код выглядит следующим образом:

protected function doCurl($resourceID=null, $post=null)
{
    //volledige url
    $url = Yii::app()->params->pfsense['host'].$resourceID;

    $ch = curl_init();
    if($post != null)
    {
        $post_string = "";
        foreach($post as $key=>$value) 
        { 
            if($key != 'enctype')
            {
                $post_string .= $key.'='.$value.'&'; 
            }
            else
            {
                curl_setopt($ch, CURLOPT_HTTPHEADER, array(
                                        'Content-Type: multipart/form-data'
                                        ));
            }
        }
        rtrim($post_string, '&');
        //var_dump($post);
        /**/
        curl_setopt($ch,CURLOPT_POST, count($post));
        curl_setopt($ch,CURLOPT_POSTFIELDS, $post_string);
        //var_dump($post_string);
    }
    else
    {
        curl_setopt($ch, CURLOPT_HEADER, true);
    }
    curl_setopt($ch, CURLOPT_URL, $url);
    //omdat het certificaat niet klopt zetten we de verificatie uit.
    curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
    curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, false);
    //we setten de useragent en de timeout. Useragent omdat sommige websites iets anders voorschotelen per browser. 
    //timeout voor als er iets gebeurd wat niet moet
    curl_setopt($ch,CURLOPT_USERAGENT,Yii::app()->params->pfsense['useragent']);
    curl_setopt($ch,CURLOPT_COOKIEJAR, Yii::app()->params->pfsense['cookiepath']);
    curl_setopt($ch,CURLOPT_COOKIEFILE, Yii::app()->params->pfsense['cookiepath']);
    curl_setopt($ch, CURLOPT_AUTOREFERER, true );
    curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
    curl_setopt($ch,CURLOPT_CONNECTTIMEOUT,10);
    curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true);
    $response = curl_exec($ch);
    $result = array( 'header' => '', 
                     'body' => '', 
                     'http_code' => '',
                     'last_url' => '');

    $header_size = curl_getinfo($ch,CURLINFO_HEADER_SIZE);
    $result['header'] = substr($response, 0, $header_size);
    $result['body'] = substr( $response, $header_size );
    $result['http_code'] = curl_getinfo($ch,CURLINFO_HTTP_CODE);
    $result['last_url'] = curl_getinfo($ch,CURLINFO_EFFECTIVE_URL);
    //curl_close($ch);
    return $result;        
}

public function curl($resourceID=null, $post=null)
{
    $result = $this->doCurl($resourceID, $post);
    if(strpos($result['body'], 'Login') == false && $result['http_code'] != 403)
    {
        //echo $result['body'];
        return $result;
    }
    else 
    {
        $loginpost = array(
                        '__csrf_magic' => substr($result['body'], strpos($result['body'],'sid:') , 55),
                        'login' => urlencode('Login'),
                        'usernamefld' => urlencode(Yii::app()->params->pfsense['pfuser']),
                        'passwordfld' => urlencode(Yii::app()->params->pfsense['pfpass'])
                    );
        $result = $this->doCurl('',$loginpost);
        $result = $this->doCurl($resourceID, $post);
        return $result;
    }
}

Это код, который позволяет отправлять запрос скручивания на сервер. Если возвращаемая страница является страницей входа, необходимо отправить информацию о входе в систему и отправить исходный запрос на публикацию заново.

следующий код - это код для вставки зоны:

 public function insertZone($post)
{
    $description = $post['description'];
    $interface = $post['interfaces'];
    $name = $post['name'];

    $post=null;
    $post['zone'] = $name;
    $post['descr'] = $description;
    $post['Submit'] = 'Continue';
    $result = $this->curl(Yii::app()->params->pfsense['pfpathtoinsertzone']);
    $post['__csrf_magic'] = substr($result['body'], strpos($result['body'],'sid:') , 55);
    var_dump($post);
    $result = $this->curl(Yii::app()->params->pfsense['pfpathtoinsertzone'], $post);
    var_dump($result['body']);
    //exit;
    if(strpos($result['body'], 'The following input errors were detected') == false)
    {
        $post = null;
        $post['enable'] = 'yes';
        $post['interfaces'] = $interface;
        $post['Submit'] = 'Save';
        $post['name'] = $name;

        $result = $this->editZone($post);
        if($result != false)
        {
            $post = null;
            $post['zone'] = $name;
            $post['enable'] = 'yes';
            $post['Submit'] = 'Save';

            $result = $this->curl(Yii::app()->params->pfsense['pfpathtovoucherroll'].$name);
            $post['__csrf_magic'] = substr($result['body'], strpos($result['body'],'sid:') , 55);

            $doc = new DOMDocument();
            $doc->loadHTML($result['body']);
            $doc->preserveWhiteSpace = false;
            if($childs = $doc->getElementsByTagName("textarea"))
            {
                foreach($childs as $child)
                {
                    if($child->nodeType == XML_TEXT_NODE)
                    {
                        continue;
                    }
                    if(strpos(trim($child->nodeValue),'BEGIN RSA PRIVATE KEY'))
                    {
                        $post['privatekey'] = trim($child->nodeValue);
                    }
                    elseif(strpos(trim($child->nodeValue),'BEGIN PUBLIC KEY'))
                    {
                        $post['publickey'] = trim($child->nodeValue);
                    }
                }
            }
            $post['charset'] = $doc->getElementById('charset')->attributes->getNamedItem('value')->nodeValue;
            $post['rollbits'] = $doc->getElementById('rollbits')->attributes->getNamedItem('value')->nodeValue;
            $post['ticketbits'] = $doc->getElementById('ticketbits')->attributes->getNamedItem('value')->nodeValue;
            $post['checksumbits'] = $doc->getElementById('checksumbits')->attributes->getNamedItem('value')->nodeValue;
            $post['magic'] = $doc->getElementById('magic')->attributes->getNamedItem('value')->nodeValue;
            $result = $this->curl(Yii::app()->params->pfsense['pfpathtovoucherroll'].$name, $post);
            if($result['http_code'] >= 100 && $result['http_code'] <= 299)
            {
                return true;
            }
            else
            {
                return false;
            }
        }
        else
        {
            return false;
        }
    }
    else 
    {
        return false;
    }
}

public function editZone($post)
{
    $zone = $post['name'];
    $interfaces = $post['interfaces'];
    $post = null;
    //$post['localauth_priv'] = 'yes';
    //$post['radiussrcip_attribute'] = strtolower($interfaces);
    if(is_array($interfaces))
    {
        $post['cinterface[]'] = array_map('strtolower', $interfaces);
    }
    else
    {
        $post['cinterface[]'] = strtolower($interfaces);
    }

    $post['auth_method'] = 'local';
    $post['radiussrcip_attribute'] = 'wan';
    $post['radiusvendor'] = 'default';
    $post['radmac_format'] = 'default';
    $post['enable'] = 'yes';
    $post['Submit'] = 'Save';
    $post["maxprocperip"] = '';
    $post["idletimeout"] = '';
    $post["timeout"] = '';
    $post["freelogins_count"] = '';
    $post["freelogins_resettimeout"] = '';
    $post["preauthurl"] = '';
    $post["redirurl"] = '';
    $post["blockedmacsurl"] = '';
    $post["bwdefaultdn"] = '';
    $post["bwdefaultup"] = '';
    $post["radiusip"] = '';
    $post["radiusport"] = '';
    $post["radiuskey"] = '';
    $post["radiusip2"] = '';
    $post["radiusport2"] = '';
    $post["radiuskey2"] = '';
    $post["radiusip3"] = '';
    $post["radiusport3"] = '';
    $post["radiuskey3"] = '';
    $post["radiusip4"] = '';
    $post["radiusport4"] = '';
    $post["reauthenticateacct"] = '';
    $post["radmac_secret"] = '';
    $post["radiusvendor"] = 'default';
    $post["radiusnasid"] = '';
    $post["radmac_format"] = 'default';
    $post["httpsname"] = '';
    $post['certref'] = '';
    $post['enctype'] = true;

    $post['zone'] = $zone;
    $post['enable'] = 'yes';
    $post['Submit'] = 'Save';

    $result = $this->curl(Yii::app()->params->pfsense['pfpathtoupdatezone'].$zone);
    //echo $result['last_url'];
    $post['__csrf_magic'] = substr($result['body'], strpos($result['body'],'sid:') , 55);
    //var_dump($post);
    $result = $this->curl(Yii::app()->params->pfsense['pfpathtoupdatezone'].$zone, $post);
    ini_set('xdebug.var_display_max_depth', -1);
    ini_set('xdebug.var_display_max_children', -1);
    ini_set('xdebug.var_display_max_data', -1);
    var_dump($result['body']);
    exit;
    if($result['http_code'] >= 100 && $result['http_code'] <= 299)
    {
        return true;
    }
    else
    {
        //var_dump($result);
        ///exit;
        return $result;
    }
}

Этот код работает, сначала вставляя зону с именем и описанием, а затем обновляя ее, чтобы активировать интерфейс и включить отображение страницы портала. Однако, если я отправил страницу без многокомпонентной формы (похоже, что это проблема), тогда аутентификация установлена ​​неправильно. Это установлено, но это не работает. Если я затем вручную изменяю настройку аутентификации (это радио-кнопка, если я выбираю другую радио-кнопку, а затем выбираю свою оригинальную радио-кнопку, она внезапно работает)

кто-нибудь знает, что я делаю не так? потому что с помощью следующего кода я получаю результат, что мои заголовки уже отправлены:

    $result = $this->curl(Yii::app()->params->pfsense['pfpathtoupdatezone'].$zone, $post);
    ini_set('xdebug.var_display_max_depth', -1);
    ini_set('xdebug.var_display_max_children', -1);
    ini_set('xdebug.var_display_max_data', -1);
    var_dump($result['body']);
    exit;

Я был бы признателен за любую помощь, которую я могу получить. заранее спасибо!

2 ответа

Решение

Если что-либо, что-либо вообще выводится, например, echo, var_dump, вы получите эту ошибку.

curl устанавливает заголовки application/x-www-form-urlencoded, Если данные поста отправляются в виде строки.

Если он отправляется как массив, он использует Content-Type: multipart/form-data. Если это не так, добавьте его, чтобы увидеть заголовок запроса:

Сейчас я точно не знаю, как вы это исправили, но у вас могут быть проблемы.

Похоже, ваши данные находятся в массиве, а затем отправлены в виде жалобы по неизвестной причине.

Это должно было остаться в массиве. Этот код выключен.

Остальное будет выполняться для каждого цикла foreach. Наверное, не повредит ничего, это просто ошибка

   foreach($post as $key=>$value) 
    { 
        if($key != 'enctype')
        {
            $post_string .= $key.'='.$value.'&'; 
        }
        else
        {
            curl_setopt($ch, CURLOPT_HTTPHEADER, array('Content-Type: multipart/form-data'));
        }
    }

Должно было:

    if($key == 'enctype'){
       curl_setopt($ch, CURLOPT_HTTPHEADER, array('Content-Type: multipart/form-data'));  

     }
     else{
        foreach($post as $key=>$value){ 
          $post_string .= $key.'='.$value.'&';
        } 
    }

Я думаю, что вы отправили данные в виде строки, или не совсем.

Это большой вопрос: if($key != 'enctype') Зачем? Это открытый исходный код?

Вышеуказанный цикл будет использоваться только в том случае, если данные поста должны были быть закодированы.

И эта часть:

if($key == 'enctype'){
   curl_setopt($ch, CURLOPT_HTTPHEADER, array('Content-Type: multipart/form-data'));  
}

Должно быть просто:

if($key == 'enctype'){
  $post_string = $post;
}

Таким образом, поскольку данные записи в массиве curl будут автоматически использовать Content-Type: multipart/form-data

Проблема в том, что если она будет отправлена ​​в виде строки, curl будет использовать application/x-www-form-urlencodedЗатем вы должны добавить это после цикла:

$post_string = urlencode($post_string);

Как это:

     else{
        foreach($post as $key=>$value){ 
          $post_string .= $key.'='.$value.'&';
        } 
        $post_string = urlencode($post_string);
      }

Что послужило причиной моей просьбы о работе: оказалось, что в запросе не было нужного энтипа. Однако было необходимо, чтобы запрос на обновление был отправлен 3-й раз. Не спрашивай меня почему.

Другие вопросы по тегам