2013-10-22 7 views
5

sto risoluzione dei problemi alcuni problemi con annuncio a un sito remoto, in particolare l'host remoto non restituisce mai alcun dato (stringa vuota).PHP stream_context_create e HTTP headers - array o stringhe, r n alla fine, Content-Length optional?

Prima cerco di risolvere qualsiasi altra cosa, voglio per assicurarsi che il codice chiamante è in realtà corretto. Il codice è:

$context = stream_context_create(array('http' => array(
    'method'  => "POST", 
    'header'  => "Content-Type: application/xml", 
    'timeout'  => 60.0, 
    'ignore_errors' => true, # return body even if HTTP status != 200 
    'content'  => $send_xml 
))); 

$response = trim(file_get_contents($this->bulk_service_url, false, $context)); 

Tutte le mie domande appartengono alla opzione "header" ed è valori, e come formattare correttamente e scrivere. La documentazione PHP, la discussione al di sotto di esso e persino la ricerca stackoverflow danno risultati molto incoerenti.

1) devo includere l'intestazione Content-Length, e in caso contrario, PHP lo calcolerà correttamente? The documentation non lo include, ma ho visto molte persone includerlo manualmente, è quindi rispettato o sovrascritto da PHP?

2) devo passare l'opzione intestazione come una stringa o un array associativo? Manuale dice stringa, la maggioranza passa come una stringa, ma this comment dice che se PHP è stato compilato con l'opzione --with-curlwrapper, devi passarlo come una matrice. Questo è un comportamento molto incoerente.

3) quando passa come una stringa, devo includere terminazione \r\n personaggi? Soprattutto quando si specifica una sola intestazione. Il manuale non fornisce un esempio del genere, il primo commento sulla pagina del manuale lo include, il secondo non ha, ancora una volta, una chiara regola su come specificarlo. PHP gestisce automaticamente entrambi i casi?

Il server utilizza PHP 5.3.

+0

Penso che dovresti usare cURL invece di file_get_contents –

risposta

2

contesto Preparazione tenta di aggiungere:

  1. ContentLength: {here_calculated_length} in chiave 'header' preceduto da \ r \ n
  2. "\ r \ n" alla fine della chiave 'header'.

Così dovrebbe essere simile:

$dl = strlen($send_xml);//YOUR_DATA_LENGTH 
$context = stream_context_create(array('http' => array(
      'method'  => "POST", 
      'header'  => "Content-Type: application/xml\r\nContentLength: $dl\r\n", 
      'timeout'  => 60.0, 
      'ignore_errors' => true, # return body even if HTTP status != 200 
      'content'  => $send_xml 
     ))); 
4

Si dovrebbe davvero memorizzare le intestazioni al codice come un array e finalizzare la preparazione appena prima di inviare la richiesta ...

function prepareHeaders($headers) { 
    $flattened = array(); 

    foreach ($headers as $key => $header) { 
    if (is_int($key)) { 
     $flattened[] = $header; 
    } else { 
     $flattened[] = $key.': '.$header; 
    } 
    } 

    return implode("\r\n", $flattened); 
} 

$headers = array(
    'Content-Type' => 'application/xml', 
    'ContentLength' => $dl, 
); 

$context = stream_context_create(array('http' => array(
    'method'  => "POST", 
    'header'  => prepareHeaders($headers), 
    'timeout'  => 60.0, 
    'ignore_errors' => true, 
    'content'  => $send_xml 
))); 

$response = trim(file_get_contents($url, FALSE, $context)); 
0

Solo un piccolo miglioramento del suggerimento di @doublejosh, nel caso in cui aiuti qualcuno:

$headers = array(
    'Content-Type' => 'application/xml', 
    'Content-Length' => strlen($send_xml) 
); 

$context = stream_context_create(['http' => [ 
    'method'  => "POST", 
    'header'  => array_map(function ($h, $v) {return "$h: $v";}, array_keys($headers), $headers), 
    'timeout'  => 60.0, 
    'ignore_errors'=> true, 
    'content'  => $send_xml 
    ] 
]);