PHP + Curl, HTTP POST Beispielcode?

491

Kann mir jemand zeigen, wie man mit einem HTTP-POST ein PHP-Curl macht?

Ich möchte Daten wie folgt senden:

username=user1, password=passuser1, gender=1

Zu www.domain.com

Ich erwarte, dass die Locke eine Antwort wie zurückgibt result=OK. Gibt es Beispiele?

mysqllearner
quelle

Antworten:

840
<?php
//
// A very simple PHP example that sends a HTTP POST to a remote site
//

$ch = curl_init();

curl_setopt($ch, CURLOPT_URL,"http://www.example.com/tester.phtml");
curl_setopt($ch, CURLOPT_POST, 1);
curl_setopt($ch, CURLOPT_POSTFIELDS,
            "postvar1=value1&postvar2=value2&postvar3=value3");

// In real life you should use something like:
// curl_setopt($ch, CURLOPT_POSTFIELDS, 
//          http_build_query(array('postvar1' => 'value1')));

// Receive server response ...
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);

$server_output = curl_exec($ch);

curl_close ($ch);

// Further processing ...
if ($server_output == "OK") { ... } else { ... }
?>
miku
quelle
47
Keine Notwendigkeit http_build_query(), mit Parametern umzugehen; Übergeben Sie einfach das Array an CURLOPT_POSTFIELDSist genug.
Raptor
8
@Raptor, der ein Array direkt für CURLOPT_POSTFIELDS bereitstellt, macht beim Curl tatsächlich einen etwas anderen POST-Typ. (Erwarten Sie: 100-weiter)
Oleg Popov
22
Auch wenn der Wert von CURLOPT_POSTFIELDSein Array ist, wird der Content-TypeHeader auf multipart/form-dataanstelle von gesetzt application/x-www-form-urlencoded. php.net/manual/en/function.curl-setopt.php
Chloe
2
Die Verwendung von CURLOPT_RETURNTRANSFER bedeutet, dass curl_exec die Antwort als Zeichenfolge zurückgibt, anstatt sie auszugeben.
BNP887
2
Ich schlage vor, trueanstelle von 1für zu verwenden CURLOPT_POST.
FluorescentGreen5
261

Verfahren

// set post fields
$post = [
    'username' => 'user1',
    'password' => 'passuser1',
    'gender'   => 1,
];

$ch = curl_init('http://www.example.com');
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_POSTFIELDS, $post);

// execute!
$response = curl_exec($ch);

// close the connection, release resources used
curl_close($ch);

// do anything you want with your response
var_dump($response);

Objektorientierter

<?php

// mutatis mutandis
namespace MyApp\Http;

class CurlPost
{
    private $url;
    private $options;

    /**
     * @param string $url     Request URL
     * @param array  $options cURL options
     */
    public function __construct($url, array $options = [])
    {
        $this->url = $url;
        $this->options = $options;
    }

    /**
     * Get the response
     * @return string
     * @throws \RuntimeException On cURL error
     */
    public function __invoke(array $post)
    {
        $ch = curl_init($this->url);

        foreach ($this->options as $key => $val) {
            curl_setopt($ch, $key, $val);
        }

        curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
        curl_setopt($ch, CURLOPT_POSTFIELDS, $post);

        $response = curl_exec($ch);
        $error    = curl_error($ch);
        $errno    = curl_errno($ch);

        if (is_resource($ch)) {
            curl_close($ch);
        }

        if (0 !== $errno) {
            throw new \RuntimeException($error, $errno);
        }

        return $response;
    }
}

Verwendungszweck

// create curl object
$curl = new \MyApp\Http\CurlPost('http://www.example.com');

try {
    // execute the request
    echo $curl([
        'username' => 'user1',
        'password' => 'passuser1',
        'gender'   => 1,
    ]);
} catch (\RuntimeException $ex) {
    // catch errors
    die(sprintf('Http error %s with code %d', $ex->getMessage(), $ex->getCode()));
}

Randnotiz hier: Es ist am besten, eine Art Schnittstelle zu erstellen, die AdapterInterfacebeispielsweise mit getResponse()method aufgerufen wird, und sie von der obigen Klasse implementieren zu lassen. Dann können Sie diese Implementierung jederzeit mit einem anderen Adapter Ihrer Art austauschen, ohne dass Ihre Anwendung Nebenwirkungen hat.

Verwenden von HTTPS / Verschlüsseln des Datenverkehrs

Normalerweise gibt es ein Problem mit cURL in PHP unter dem Windows-Betriebssystem. Beim Versuch, eine Verbindung zu einem https-geschützten Endpunkt herzustellen, wird eine Fehlermeldung angezeigt certificate verify failed.

Was die meisten Leute hier tun, ist, der cURL-Bibliothek anzuweisen, Zertifikatfehler einfach zu ignorieren und fortzufahren ( curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);). Damit Ihr Code funktioniert, führen Sie eine große Sicherheitslücke ein und ermöglichen böswilligen Benutzern, verschiedene Angriffe auf Ihre App auszuführen, z. B. Man In The Middle- Angriffe oder ähnliches .

Mach das niemals. Stattdessen müssen Sie lediglich Ihre ändern php.iniund PHP mitteilen, wo sich Ihre CA CertificateDatei befindet, damit die Zertifikate korrekt überprüft werden können:

; modify the absolute path to the cacert.pem file
curl.cainfo=c:\php\cacert.pem

Die neuesten cacert.pemkönnen aus dem Internet heruntergeladen oder aus Ihrem bevorzugten Browser extrahiert werden . Denken Sie beim Ändern der php.inizugehörigen Einstellungen daran, den Webserver neu zu starten.

emix
quelle
4
Dies sollte wirklich die akzeptierte Antwort sein, da es die beste Vorgehensweise wäre, die HTTP-Bibliothek die Codierung Ihrer Variablen übernehmen zu lassen.
Eric Seastrand
4
Dies ist nicht immer der Fall. Ich habe Webserver gesehen, die erwarten, dass POST-Variablen auf eine bestimmte Weise codiert werden, was dazu führt, dass sie ansonsten fehlschlagen. Es scheint mir, dass http_build_query () dafür tatsächlich zuverlässiger ist als cURL.
César
4
Die HTTP-Spezifikation ist ziemlich einfach, wie die POST-Parameter aussehen sollen. Die Webserver-Software sollte ohnehin den Standards entsprechen.
Emix
1
Auf diese Weise zwingen Sie cURL, einen etwas anderen POST-Typ zu verwenden. (Erwarten Sie: 100-weiter). Überprüfen Sie diesen Artikel: support.urbanairship.com/entries/…
Oleg Popov
5
In der PHP-Dokumentation wird auf @ Césars Kommentar ausdrücklich Folgendes hingewiesen: "Durch die Übergabe eines Arrays an CURLOPT_POSTFIELDS werden die Daten als mehrteilige / Formulardaten codiert, während durch Übergabe einer URL-codierten Zeichenfolge die Daten als application / x-www-form codiert werden -urlencodiert . ". Ich habe kürzlich übermäßig viel Zeit damit verbracht, Fehler zu beheben, warum ein cURL-Aufruf auf einem Endpunkt eines Drittanbieters fehlschlug, um schließlich festzustellen, dass diese keine mehrteiligen / Formulardaten unterstützen.
Jake Z
31

Ein Live-Beispiel für die Verwendung von php curl_exec zum Erstellen eines HTTP-Posts:

Fügen Sie dies in eine Datei namens foobar.php ein:

<?php
  $ch = curl_init();
  $skipper = "luxury assault recreational vehicle";
  $fields = array( 'penguins'=>$skipper, 'bestpony'=>'rainbowdash');
  $postvars = '';
  foreach($fields as $key=>$value) {
    $postvars .= $key . "=" . $value . "&";
  }
  $url = "http://www.google.com";
  curl_setopt($ch,CURLOPT_URL,$url);
  curl_setopt($ch,CURLOPT_POST, 1);                //0 for a get request
  curl_setopt($ch,CURLOPT_POSTFIELDS,$postvars);
  curl_setopt($ch,CURLOPT_RETURNTRANSFER, true);
  curl_setopt($ch,CURLOPT_CONNECTTIMEOUT ,3);
  curl_setopt($ch,CURLOPT_TIMEOUT, 20);
  $response = curl_exec($ch);
  print "curl response is:" . $response;
  curl_close ($ch);
?>

Führen Sie es dann mit dem Befehl aus php foobar.php. Es gibt diese Art von Ausgabe auf dem Bildschirm aus:

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" 
"http://www.w3.org/TR/html4/strict.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<title>Title</title>

<meta http-equiv="Pragma" content="no-cache">
<meta http-equiv="Expires" content="0">
<body>
  A mountain of content...
</body>
</html>

Sie haben also einen PHP-POST an www.google.com gesendet und ihm einige Daten gesendet.

Wäre der Server so programmiert worden, dass er die Post-Variablen einliest, könnte er sich dazu entschließen, etwas anderes zu tun.

Eric Leschinski
quelle
$postvars .= $key . $value;sollte $postvars .= $key . $value ."&";oder nicht?
Manwal
Wenn Sie sich diese Antwort noch einmal ansehen , können Sie auch Ihre benutzerdefinierte Implementierung des Abfragezeichenfolgenkonverters durch http_build_query ersetzen. Geben Sie ihr einfach das $fieldsArray und es wird eine Abfragezeichenfolge ausgegeben.
Beachten Sie, dass Sie Ihre Daten verschlüsseln sollten, damit sie sicher übermittelt werden können.
wtf8_decode
3
Oh nein, versuche nicht, den Post-String selbst zu bauen! Verwenden Sie diese:curl_setopt($ch, CURLOPT_POSTFIELDS, http_build_query($fields));
Oriadam
3
-1, weil Sie Ihren Post-Vars nicht entkommen. Das Beispiel des OP sendet vom Benutzer übermittelte Benutzernamen und Kennwörter zur Authentifizierung. Mit Ihrer Lösung kann sich ein Benutzer mit einem & in seinem Passwort niemals anmelden. Der Kommentar von oriadam ist korrekt, aber Sie können Folgendes weglassen http_build_query:curl_setopt($ch, CURLOPT_POSTFIELDS, $fields);
Eric Seastrand
26

Es ist leicht zu erreichen mit:

<?php

$post = [
    'username' => 'user1',
    'password' => 'passuser1',
    'gender'   => 1,
];
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, 'http://www.domain.com');
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_POSTFIELDS, http_build_query($post));
$response = curl_exec($ch);
var_export($response);
V. Kovpak
quelle
13

Curl Post + Fehlerbehandlung + Header setzen [danke an @ mantas-d]:

function curlPost($url, $data=NULL, $headers = NULL) {
    $ch = curl_init($url);
    curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);

    if(!empty($data)){
        curl_setopt($ch, CURLOPT_POSTFIELDS, $data);
    }

    if (!empty($headers)) {
        curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
    }

    $response = curl_exec($ch);

    if (curl_error($ch)) {
        trigger_error('Curl Error:' . curl_error($ch));
    }

    curl_close($ch);
    return $response;
}


curlPost('google.com', [
    'username' => 'admin',
    'password' => '12345',
]);
MSS
quelle
Ihr Code schließt das Handle nicht und gibt keine Ressourcen frei, da Sie curl_close nach dem Auslösen einer Ausnahme verwenden. Sie sollten curl_close in einem finally-Block einfügen.
Emix
7
curlPost('google.com', [
    'username' => 'admin',
    'password' => '12345',
]);


function curlPost($url, $data) {
    $ch = curl_init($url);
    curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
    curl_setopt($ch, CURLOPT_POSTFIELDS, $data);
    $response = curl_exec($ch);
    $error = curl_error($ch);
    curl_close($ch);
    if ($error !== '') {
        throw new \Exception($error);
    }

    return $response;
}
Mantas D.
quelle
1
Ihr Code schließt das Handle nicht und gibt keine Ressourcen frei, da Sie curl_close nach dem Auslösen einer Ausnahme verwenden. Sie sollten curl_closein einem finallyBlock.
Emix
6

Wenn das Formular Weiterleitungen, Authentifizierung, Cookies, SSL (https) oder etwas anderes als ein vollständig offenes Skript verwendet, das POST-Variablen erwartet, werden Sie sehr schnell mit dem Zähneknirschen beginnen. Werfen Sie einen Blick auf Snoopy , das genau das tut, was Sie sich vorgestellt haben, ohne dass Sie einen Großteil des Overheads einrichten müssen.

Anthony
quelle
Wenn Sie bei der curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
Aktienbibliothek
Der einzige Nachteil ist, dass Sie sich immer noch mit dem Setzen einer Cookie-JAR und anderen potenziellen Problemen befassen müssen (z. B. ob Sie Weiterleitungen folgen, wie Sie mit nicht HTTP-basierter Authentifizierung umgehen usw.). 6 Jahre später würde ich das allgemeinere Konzept eines "Headless-Browsers" anstelle dieser spezifischen Bibliothek empfehlen (oder irgendetwas auf SourceForge, wie veraltet, richtig?). Und obwohl ich mich im Allgemeinen nur direkt mit Curl-Optionen befasse, würde ich trotzdem raten Betrachten Sie eine Headless-Browser-Bibliothek, die PSR-7- kompatibel ist (Guzzle ist die einzige, die ich sofort kenne), um Kopfschmerzen zu vermeiden.
Anthony
3

Eine einfachere Antwort, wenn Sie Informationen an Ihre eigene Website weitergeben, ist die Verwendung einer SESSION-Variablen. Beginnen Sie die PHP-Seite mit:

session_start();

Wenn es irgendwann Informationen gibt, die Sie in PHP generieren und an die nächste Seite der Sitzung weiterleiten möchten, anstatt eine POST-Variable zu verwenden, weisen Sie sie einer SESSION-Variablen zu. Beispiel:

$_SESSION['message']='www.'.$_GET['school'].'.edu was not found.  Please try again.'

Dann verweisen Sie auf der nächsten Seite einfach auf diese SESSION-Variable. HINWEIS: Stellen Sie nach der Verwendung sicher, dass Sie es zerstören, damit es nach der Verwendung nicht bestehen bleibt:

if (isset($_SESSION['message'])) {echo $_SESSION['message']; unset($_SESSION['message']);}
user2532795
quelle
3

Hier sind einige Boilerplate-Codes für PHP + Curl http://www.webbotsspidersscreenscrapers.com/DSP_download.php

Die Aufnahme in diese Bibliothek vereinfacht die Entwicklung

<?php
# Initialization
include("LIB_http.php");
include("LIB_parse.php");
$product_array=array();
$product_count=0;

# Download the target (store) web page
$target = "http://www.tellmewhenitchanges.com/buyair";
$web_page = http_get($target, "");
    ...
?>
AzizSM
quelle
2

Wenn Sie versuchen, sich vor Ort mit Cookies anzumelden.

Dieser Code:

if ($server_output == "OK") { ... } else { ... }

Funktioniert möglicherweise nicht, wenn Sie versuchen, sich anzumelden, da viele Websites den Status 200 zurückgeben, der Beitrag jedoch nicht erfolgreich ist.

Eine einfache Möglichkeit, um zu überprüfen, ob der Anmeldebeitrag erfolgreich ist, besteht darin, zu überprüfen, ob erneut Cookies gesetzt werden. Wenn in der Ausgabe eine Set-Cookies-Zeichenfolge vorhanden ist, bedeutet dies, dass die Beiträge nicht erfolgreich sind und eine neue Sitzung gestartet wird.

Auch der Beitrag kann erfolgreich sein, aber der Status kann stattdessen umgeleitet werden 200.

Um sicherzugehen, dass der Beitrag erfolgreich ist, versuchen Sie Folgendes:

Folgen Sie dem Speicherort nach dem Beitrag, um zu der Seite zu gelangen, auf die der Beitrag umleitet:

curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true);

Und dann prüfen Sie, ob in der Anfrage neue Cookies vorhanden sind:

if (!preg_match('/^Set-Cookie:\s*([^;]*)/mi', $server_output)) 

{echo 'post successful'; }

else { echo 'not successful'; }
Atanas Atanasov
quelle
1

Beispiele für das Senden von Formularen und Rohdaten :

$curlHandler = curl_init();

curl_setopt_array($curlHandler, [
    CURLOPT_URL => 'https://postman-echo.com/post',
    CURLOPT_RETURNTRANSFER => true,

    /**
     * Specify POST method
     */
    CURLOPT_POST => true,

    /**
     * Specify array of form fields
     */
    CURLOPT_POSTFIELDS => [
        'foo' => 'bar',
        'baz' => 'biz',
    ],
]);

$response = curl_exec($curlHandler);

curl_close($curlHandler);

echo($response);
Serhii Andriichuk
quelle