12

I'm trying to login to a site via PHP cURL and I'm only getting "Bad Request" responses.

I played around with hosts file and set it to my server to check which Request Headers my browser sends and compare it to the request headers sent by cURL.

Everything is equal, except of:

Browser:

Content-Type: application/x-www-form-urlencoded
Content-Length: 51

PHP cURL:

Content-Length: 51, 359
Content-Type: application/x-www-form-urlencoded; boundary=----------------------------5a377b7e6ba7

I already set that values with this command, but it still sends the wrong headers:

curl_setopt($this->hCurl, CURLOPT_HTTPHEADER, array(
    'Expect:',
    'Content-Type: application/x-www-form-urlencoded',
    'Content-Length: 51' 
));
Mark Amery
  • 143,130
  • 81
  • 406
  • 459
Simon
  • 594
  • 2
  • 6
  • 25

1 Answers1

34

You shouldn't have to set the content-length yourself. If you use cURL to send an HTTP POST, it will calculate the content length for you.

If you set the CURLOPT_POSTFIELDS value as an array, it will automatically submit the request as multipart/form-data and use a boundary. If you pass a string, it will use application/x-www-form-urlencoded so make sure you pass a urlencoded string to CURLOPT_POSTFIELDS and not an array since you want form-urlencoded.

You need to be doing this:

$data = 'name=' . urlencode($value) . '&name2=' . urlencode($value2);
curl_setopt($this->hCurl, CURLOPT_POSTFIELDS, $data);

// NOT

$dataArray = array('name' => 'value', 'name2' => 'value2');
curl_setopt($this->hCurl, CURLOPT_POSTFIELDS, $dataArray);

In either case, you do not need to set the content length, but you have to use the first method to get application/x-www-form-urlencoded encoding on the form.

If that doesn't help, post all the code relevant to setting up the curl request, (all the options, and data you are passing to it) and that should help solve the problem.

EDIT:

Added is an example I came up with that works (I get failed login).

<?php

$URL_HOME  = 'http://ilocalis.com/';
$LOGIN_URL = 'https://ilocalis.com/login.php';

$ch = curl_init($URL_HOME);
curl_setopt($ch, CURLOPT_HEADER, 0);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($ch, CURLOPT_FOLLOWLOCATION, 1);

$home = curl_exec($ch);

//echo $home;

$post = array('username' => 'drew', 'password' => 'testing 123');
$query = http_build_query($post);

curl_setopt($ch, CURLOPT_URL, $LOGIN_URL);
curl_setopt($ch, CURLOPT_POST, 1);
curl_setopt($ch, CURLOPT_POSTFIELDS, $query);

$login = curl_exec($ch);

echo $login;
drew010
  • 68,777
  • 11
  • 134
  • 162
  • 1
    Thanks for your comment, I didn't know that there's a difference between passing an array and passing a string. But http_build_query($array) should work, too, doesn't it? Anyways - it didn't work either, unfortunately. When I don't specify the content-length myself, the page is returning a "HTTP Error 411 Length required" error. I'm trying to log in on http://ilocalis.com/ ( posting to https://ilocalis.com/login.php ) - if you want to try it yourself, you don't need an account because I even don't come to that point of loading the page and checking if the given credentials was right... Thanks! – Simon Feb 07 '12 at 18:39
  • Since the content length wasn't set, I wonder if the request method is not POST, or perhaps some other option is overriding that. In any case, I updated the post with a working example. Hopefully it gets you on the right track. It uses 1 curl object to make 2 separate requests. Note, if you need to make a GET query again, you have to set CURLOPT_POST back to 0. – drew010 Feb 07 '12 at 23:42
  • Thank. you. so. much. I didn't see the forest for the trees. I set curlopt_customrequest to "POST" because I used to pass an array to curlopt_postfields..... With using a string as you already mentioned it should work, but I accidentially forgot to remove the customrequest thing.. It's the small things that freak the shit out of us programmers when we don't get why it won't work.. ;) – Simon Feb 08 '12 at 09:10
  • 1
    @drew010 saved my life! I use `http_build_query()` now. – mgutt Mar 02 '12 at 13:39
  • Thank you so much, after hours of guessing and searching on google, a part in this answer solved my problem – nico gawenda Jun 08 '12 at 18:59
  • mad at myself that i did not remember the bit about converting to a string instead of array – loushou Jan 26 '14 at 06:57
  • 1
    THANK YOU @drew010 I've been having similar problem with one software and had been bashing my head for a week with this. Your explanation did it for me :)! – LukasS Apr 30 '15 at 12:53