While I'm trying to send a GET request to an address with php I receive HTTP 400 BAD REQUEST message and I can't figure out why.
Here's my code:
function redirect($url)
{
error_reporting(E_ERROR | E_PARSE);
$components = parse_url($url);
$port = $components["port"];
$ip = $components["host"];
$path = $components["path"];
//create and connect socket with the parameters entered by the user
//$sock = socket_create(AF_INET,SOCK_STREAM,SOL_TCP);
echo "Establishing connection to the given adress...\n";
//Connection timeout limit is set to 10 seconds...
if(!isset($port))
{
$port = 80;
}
$sock = fsockopen($ip, $port,$errno, $errstr, 10) or die("Unable to connect...");
$request = "GET $path HTTP/1.1" . "\r\n\r\n";
fwrite($sock, $request);
while ($header = stream_get_line($sock, 1024, "\r\n")) {
$response.= $header . "\n";
}
echo $response;
$loc = "";
if (preg_match("/Location:\'(.*)\\n/", $response, $results))
$loc = $results[1];
echo $loc;
}
Any suggestions?
A GET request also contains a header wich include things like the useragent oder the encoding, you should have a look at what you need to send and what's optional
For this specific problem I've found a solution. If you want to get the headers from the request that I sent in the question above, you can use php's get_headers($url) method. It retrieves the headers that I was looking for. I'm really new to protocols and web-services and also to php (1 or 1.5 weeks), therefore I may have asked a silly question and not have been specific enough. Anyways thank you very much for your answers.
Have a nice day!
Related
Closed. This question does not meet Stack Overflow guidelines. It is not currently accepting answers.
This question does not appear to be about programming within the scope defined in the help center.
Closed 11 months ago.
Improve this question
I have a php script that creates an xml sitemap. At the end, I use
shell_exec('ping -c1 www.google.com/webmasters/tools/ping?sitemap=sitemapurl');
to submit the updated sitemap to Google Webmaster tools.
Having read the Google documentation, I'm unsure whether I need to do this each time or not. Entering the link in the code manually, results in a success page from google, but using the ping command I receive no confirmation. I would also like to know if there is any way of checking if the command has actually worked.
Here is a script to automatically submit your site map to google, bing/msn and ask:
/*
* Sitemap Submitter
* Use this script to submit your site maps automatically to Google, Bing.MSN and Ask
* Trigger this script on a schedule of your choosing or after your site map gets updated.
*/
//Set this to be your site map URL
$sitemapUrl = "http://www.example.com/sitemap.xml";
// cUrl handler to ping the Sitemap submission URLs for Search Engines…
function myCurl($url){
$ch = curl_init($url);
curl_setopt($ch, CURLOPT_HEADER, 0);
curl_exec($ch);
$httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
curl_close($ch);
return $httpCode;
}
//Google
$url = "http://www.google.com/webmasters/sitemaps/ping?sitemap=".$sitemapUrl;
$returnCode = myCurl($url);
echo "<p>Google Sitemaps has been pinged (return code: $returnCode).</p>";
//Bing / MSN
$url = " https://www.bing.com/webmaster/ping.aspx?siteMap=".$sitemapUrl;
$returnCode = myCurl($url);
echo "<p>Bing / MSN Sitemaps has been pinged (return code: $returnCode).</p>";
//ASK
$url = "http://submissions.ask.com/ping?sitemap=".$sitemapUrl;
$returnCode = myCurl($url);
echo "<p>ASK.com Sitemaps has been pinged (return code: $returnCode).</p>";
you can also send yourself an email if the submission fails:
function return_code_check($pingedURL, $returnedCode) {
$to = "webmaster#yoursite.com";
$subject = "Sitemap ping fail: ".$pingedURL;
$message = "Error code ".$returnedCode.". Go check it out!";
$headers = "From: hello#yoursite.com";
if($returnedCode != "200") {
mail($to, $subject, $message, $headers);
}
}
Hope that helps
Since commands like shell_exec(), exec(), passthru() etc. are blocked by many hosters, you should use curl and check for a response code of 200.
You could also use fsockopen if curl is not available. I'm going to check for the code snippet and update the answer when I found it.
UPDATE:
Found it. I knew I used it somewhere. The funny coincedence: It was in my Sitemap class xD
You can find it here on github: https://github.com/func0der/Sitemap. It is in the Sitemap\SitemapOrg class.
There is a also an example for the curl call implemented.
Either way, here is the code for stand alone implementation.
/**
* Call url with fsockopen and return the response status.
*
* #param string $url
* The url to call.
*
* #return mixed(boolean|int)
* The http status code of the response. FALSE if something went wrong.
*/
function _callWithFSockOpen($url) {
$result = FALSE;
// Parse url.
$url = parse_url($url);
// Append query to path.
$url['path'] .= '?'.$url['query'];
// Setup fsockopen.
$port = 80;
$timeout = 10;
$fso = fsockopen($url['host'], $port, $errno, $errstr, $timeout);
// Proceed if connection was successfully opened.
if ($fso) {
// Create headers.
$headers = 'GET ' . $url['path'] . 'HTTP/1.0' . "\r\n";
$headers .= 'Host: ' . $url['host'] . "\r\n";
$headers .= 'Connection: closed' . "\r\n";
$headers .= "\r\n";
// Write headers to socket.
fwrite($fso, $headers);
// Set timeout for stream read/write.
stream_set_timeout($fso, $timeout);
// Use a loop in case something unexpected happens.
// I do not know what, but that why it is unexpected.
while (!feof($fso)){
// 128 bytes is getting the header with the http response code in it.
$buffer = fread($fso, 128);
// Filter only the http status line (first line) and break loop on success.
if(!empty($buffer) && ($buffer = substr($buffer, 0, strpos($buffer, "\r\n")))){
break;
}
}
// Match status.
preg_match('/^HTTP.+\s(\d{3})/', $buffer, $match);
// Extract status.
list(, $status) = $match;
$result = $status;
}
else {
// #XXX: Throw exception here??
}
return (int) $result;
}
If you guys find any harm or improvement in this code, do not hesitate to open up a ticket/pull request on GitHub, please. ;)
Simplest solution: file_get_contents("https://www.google.com/webmasters/tools/ping?sitemap={$sitemap}");
That will work on every major hosting provider. If you want optional error reporting, here's a start:
$data = file_get_contents("https://www.google.com/webmasters/tools/ping?sitemap={$sitemap}");
$status = ( strpos($data,"Sitemap Notification Received") !== false ) ? "OK" : "ERROR";
echo "Submitting Google Sitemap: {$status}\n";
As for how often you should do it, as long as your site can handle the extra traffic from Google's bots without slowing down, you should do this every time a change has been made.
In javascript or jquery you a function can do a callback to remote webpage. The remote page does some processing and something/nothing maybe returned to the calling function.
For example: $.ajax(http://someurl.php?querystring)
How do I do this in php?
<?php
'Doing some stuff
remote_call(http://someurl.php?querystring) 'Let the page know I did stuff
'more php
?>
Everywhere I can find is either talking about a php function callback or reading file contents. I don't want to read the file contents, I just want to call the remote page and move on. Is it possible?
I can't answer my own question in this forum so I am putting the answer here.
Here is what worked for me. YMMV
$host = "http://somedomain.com/process.php?querystring";
curlMe($host);
function curlMe($host)
{
$ch = curl_init($host);
curl_setopt($ch, CURLOPT_HEADER, 0);
curl_exec($ch);
curl_close($ch);
}
You could just make a async request to the remote page by closing the socket immediately so the php code doesn't block and forget about the result.
<?php
private function request($body) {
$protocol = "http";
$host = "domain.com";
$port = 80;
$path = "/somepage.php" . $body;
$timeout = 10;
try {
# Open our socket to the API Server.
$socket = fsockopen($protocol . "://" . $host, $port,
$errno, $errstr, $timeout);
# Create the request body, and make the request.
$req = $this->create_body($host, $path, $content);
fwrite($socket, $req);
# ...
} catch (Exception $e) {
# ...
}
}
?>
I am kinda new to PHP however I used JSP a lot before (I have quite information) and everything was easier with Java classes.
So, now, I want to perform a POST request on a HTTPS page (not HTTP) and need to get returned cookies and past it to another GET request and return the final result. Aim is to make a heavy page for mobile phones more compatible to view in a mobile browser by bypassing the login page and directly taking to the pages which are also served in an ajax user interface.
I am stuck, my code does not work, it says it is Bad Request.
Bad Request
Your browser sent a request that this
server could not understand. Reason:
You're speaking plain HTTP to an
SSL-enabled server port. Instead use
the HTTPS scheme to access this URL,
please.
<?php
$content = '';
$flag = false;
$post_query = 'SOME QUERY'; // name-value pairs
$post_query = urlencode($post_query) . "\r\n";
$host = 'HOST';
$path = 'PATH';
$fp = fsockopen($host, '443');
if ($fp) {
fputs($fp, "POST $path HTTP/1.0\r\n");
fputs($fp, "Host: $host\r\n");
fputs($fp, "Content-length: ". strlen($post_query) ."\r\n\r\n");
fputs($fp, $post_query);
while (!feof($fp)) {
$line = fgets($fp, 10240);
if ($flag) {
$content .= $line;
} else {
$headers .= $line;
if (strlen(trim($line)) == 0) {
$flag = true;
}
}
}
fclose($fp);
}
echo $headers;
echo $content;
?>
From past experience, I've never used PHP's internal functions like fsocketopen() for external data posting. The best way to do these actions are using CURL, which gives much more ease and is massively more powerful for developers to leverage.
for example, look at these functions
http://php.net/curl_setopt
and look at the one with URL, POST, POSTDATA, and COOKIESFILES which is for .JAR, which you get then retrieve and that you can use file_get_contents() to send the data using GET.
I am accessing a url which needs authentication, so for authentication i am using cookie something like this
$out = "GET $path HTTP/1.0\r\nHost: $host\r\nCookie: user=$cookie\r\n\r\n";
$fp = fsockopen($host, 80, $errno, $errstr, 30) or htmlerror('Bandwidth limit exceeded, please try again later.');
fwrite($fp, $out);
so i wanted to know whether instead of cookie how can i use directly username and password in variable $out
Thank You
I had a quick view on HTTP GET REQUEST, you might try to insert something into the query part of the URI
$out = 'GET /*?*username=$user&password=$encryptedPW HTTP/1.1'
$out .= '/n' . 'Host: $host'
it didnt work, just using it with cookie
I would like to create a batch script, to go through 20,000 links in a DB, and weed out all the 404s and such. How would I get the HTTP status code for a remote url?
Preferably not using curl, since I dont have it installed.
CURL would be perfect but since you don't have it, you'll have to get down and dirty with sockets. The technique is:
Open a socket to the server.
Send an HTTP HEAD request.
Parse the response.
Here is a quick example:
<?php
$url = parse_url('http://www.example.com/index.html');
$host = $url['host'];
$port = $url['port'];
$path = $url['path'];
$query = $url['query'];
if(!$port)
$port = 80;
$request = "HEAD $path?$query HTTP/1.1\r\n"
."Host: $host\r\n"
."Connection: close\r\n"
."\r\n";
$address = gethostbyname($host);
$socket = socket_create(AF_INET, SOCK_STREAM, SOL_TCP);
socket_connect($socket, $address, $port);
socket_write($socket, $request, strlen($request));
$response = split(' ', socket_read($socket, 1024));
print "<p>Response: ". $response[1] ."</p>\r\n";
socket_close($socket);
?>
UPDATE: I've added a few lines to parse the URL
If im not mistaken none of the php built-in functions return the http status of a remote url, so the best option would be to use sockets to open a connection to the server, send a request and parse the response status:
pseudo code:
parse url => $host, $port, $path
$http_request = "GET $path HTTP/1.0\nHhost: $host\n\n";
$fp = fsockopen($host, $port, $errno, $errstr, $timeout), check for any errors
fwrite($fp, $request)
while (!feof($fp)) {
$headers .= fgets($fp, 4096);
$status = <parse $headers >
if (<status read>)
break;
}
fclose($fp)
Another option is to use an already build http client class in php that can return the headers without fetching the full page content, there should be a few open source classes available on the net...
This page looks like it has a pretty good setup to download a page using either curl or fsockopen, and can get the HTTP headers using either method (which is what you want, really).
After using that method, you'd want to check $output['info']['http_code'] to get the data you want.
Hope that helps.
You can use PEAR's HTTP::head function.
http://pear.php.net/manual/en/package.http.http.head.php