Raw HTTP - Using full URL in the GET line? - php

<?php
error_reporting(E_ALL);
ini_set('display_errors', '1');
header('content-type: text/plain');
$host='www.google.com';
$fp = fsockopen($host, 80);
$out = "GET http://www.google.com/ HTTP/1.1\r\n";
$out .= "Host: $host\r\n";
$out .= "Connection: Close\r\n\r\n";
fwrite($fp, $out);
while (!feof($fp)) {
echo fgets($fp, 128);
}
?>
this just works.
is it standards compliant?

Yes it is.
From the specification:
Request-Line = Method SP Request-URI SP HTTP-Version CRLF
...and...
Request-URI = "*" | absoluteURI | abs_path | authority

Yes, according to 5.1.2 of RFC 2616:
An example Request-Line would be:
GET http://www.w3.org/pub/WWW/TheProject.html HTTP/1.1
To allow for transition to absoluteURIs in all requests in future versions of HTTP, all HTTP/1.1 servers MUST accept the absoluteURI form in requests, even though HTTP/1.1 clients will only generate them in requests to proxies.

Related

How to make a request to over HTTPS via file_get_contents() without openssl by not verifying ssl?

I am making an application that deals with postbacks, and I wanted to make it so it would be able to postback to domains with https:// even if the person who is using the app doesn't have the openssl php extension. (It would warn them that their postbacks would be made non securely.)
I turned off openssl and tried the following, but it is giving me an error that I do not have https wrapper.
$arrContextOptions=array(
"ssl"=>array(
"verify_peer"=>false,
"verify_peer_name"=>false,
),
);
echo file_get_contents('https://httpbin.org/get?test=test', true, stream_context_create($arrContextOptions) );
Is it possible to make this request with file_get_contents?
Try this code:
<?php
$fp = fsockopen("ssl://somedomain/abc/", 2000 , $ErrNo, $ErrString, 30);
if (!$fp) {
echo "Error No : $ErrNo - $ErrString <br />\n";
} else {
$out = "POST / HTTP/1.1\r\n";
$out .= "Host: somedomain \r\n";
$out .= "Content-Type: application/xml; charset=utf-8;\r\n";
$out .= "Connection: Close\r\n\r\n";
fwrite($fp, $out);
while (!feof($fp)) {
echo fgets($fp, 128);
}
fclose($fp);
}
?>
I have research file_get_contents with --no-check-certificate
readmore here file_get_contents ignoring verify_peer=>false?

How to send cookie alongside http request from cookie.txt using fsockopen?

I was searching on how to use curl (send http request) without waiting for the response to complete, because i just want to trigger many action and dont expect the results. After time of searching, I found a solution Here, but i have a problem.The problem is i don't know how to pass cookie that I have saved in .txt and i want to send it using this request.
function curl_post_async($url, $params)
{
foreach ($params as $key => &$val) {
if (is_array($val)) $val = implode(',', $val);
$post_params[] = $key.'='.urlencode($val);
}
$post_string = implode('&', $post_params);
$parts=parse_url($url);
$fp = fsockopen($parts['host'],
isset($parts['port'])?$parts['port']:80,
$errno, $errstr, 30);
$out = "POST ".$parts['path']." HTTP/1.1\r\n";
$out.= "Host: ".$parts['host']."\r\n";
$out.= "Content-Type: application/x-www-form-urlencoded\r\n";
$out.= "Content-Length: ".strlen($post_string)."\r\n";
$out.= "Connection: Close\r\n\r\n";
if (isset($post_string)) $out.= $post_string;
fwrite($fp, $out);
fclose($fp);
}
How to send cookie from .txt files using above's code?
After research I solved how to send cookies from cookies.txt
When I search I found 2 formats of cookies
1. Netscape
# Netscape HTTP Cookie File
# https://curl.haxx.se/docs/http-cookies.html
# This file was generated by libcurl! Edit at your own risk.
#HttpOnly_.site.com TRUE / FALSE 1517538526 __cfduid dc0d1a86523f4fa68c7c9e19b084aa1651486002526
#HttpOnly_www.site.com FALSE / FALSE 1486006126 cisession a914d92115f6a6d73124ac5de4c49e070b872b98
2. Cookie default format (reference: Here)
csrf_cookie_name=cac551cc13952929efd2507797fff687; ci_session=umt92quvucfu333p1co19b83i3jaglm9;
I tried to send the cookie format no.1 using this line code
$out.= "Cookie: ".file_get_contents(getcwd().$cookie); //where getcwd().$cookie is location of the cookie.txt with format no.1
I tried that but it failed. But if the cookie.txt's cookie value is format no.2 I sent that cookie and it successfully sended and can be read.
Conclusion to send cookie:
$out.= "Cookie: csrf_cookie_name=cac551cc13952929efd2507797fff687; ci_session=umt92quvucfu333p1co19b83i3jaglm9;";

How do I make a POST request over HTTPS in PHP?

I trying to work with the YouTube API and its ClientLogin. And that means that I need to make a POST request to their servers.
The URL to which I need to make the request to https://www.google.com/accounts/ClientLogin. The variables I need to send are Email, Passwd, source and service. So far, so good.
I found this neat function to make POST calls (see below), but it does not use HTTPS, which I think I must use. It all works but I think my POST request is being forwarded to HTTPS and therefore it does not give me the proper callback. When I try to var_dump, the returned data web page reloads and I end up at https://www.google.com/accounts/ClientLogin where I get proper data. But of course I need this data as an array or string.
So how do I make a POST request using HTTPS?
Se my code (which I found at Jonas’ Snippet Library) below:
function post_request($url, $data, $referer='') {
$data = http_build_query($data);
$url = parse_url($url);
$host = $url['host'];
$path = $url['path'];
$fp = fsockopen($host, 80, $errno, $errstr, 30);
if ($fp){
fputs($fp, "POST $path HTTP/1.1\r\n");
fputs($fp, "Host: $host\r\n");
if ($referer != '')
fputs($fp, "Referer: $referer\r\n");
fputs($fp, "Content-type: application/x-www-form-urlencoded\r\n");
fputs($fp, "Content-length: ". strlen($data) ."\r\n");
fputs($fp, "Connection: close\r\n\r\n");
fputs($fp, $data);
$result = '';
while(!feof($fp)) {
$result .= fgets($fp, 128);
}
}
else {
return array(
'status' => 'err',
'error' => "$errstr ($errno)"
);
}
fclose($fp);
$result = explode("\r\n\r\n", $result, 2);
$header = isset($result[0]) ? $result[0] : '';
$content = isset($result[1]) ? $result[1] : '';
return array(
'status' => 'ok',
'header' => $header,
'content' => $content
);
}
This is the response headers:
HTTP/1.1 200 OK
Content-Type: text/html; charset=UTF-8
Date: Tue, 03 May 2011 12:15:20 GMT
Expires: Tue, 03 May 2011 12:15:20 GMT
Cache-Control: private, max-age=0
X-Content-Type-Options: nosniff
X-XSS-Protection: 1; mode=block
Content-Length: 728
Server: GSE
Connection: close
The content I get back is some kind of form autosubmitted, which I think is because I use HTTP instead of HTTPS:
function autoSubmit() {
document.forms["hiddenpost"].submit();
}
Processing...
So, how do I do a HTTPS POST request?
As octopusgrabbus kindly pointed out, I need to use port 443 instead of 80. So I changed this, but now I get nothing back.
var_dump from function return:
array(3) {
["status"]=>
string(2) "ok"
["header"]=>
string(0) ""
["content"]=>
string(0) ""
}
I get no header and no content back. What is wrong?
I think you cannot talk directly HTTPS, as it is HTTP encrypted with the public certificate of the server you are connecting to. Maybe you can use some of the ssl functions in php. But, this will take you some time and frankly, there are easier things.
Just take a look at cURL (client URL), that has support for GET and POST requests, and also connecting to https servers.
You are opening your socket at port 80. The SSL port is 443.
If this is SSL, there is an official computer name tied to the secure cert that's present on that web server. You might need to connect using that official name.
When you open the socket, changing the port to 443 and the prepending the host with ssl:// should work. (I just had this issue with paypal and some third party code). This assumes you don't have a protocol in your host already.
So
$fp = fsockopen('ssl://' . $host, 443, $errno, $errstr, 30);
As Carlos pointed out cUrl is good for this sort of thing. But there's no need to completely change what you're using in this case, particularly when it's a single line change.

PHP: Connection: keep-alive problem reading socket data

Trying to write data to a socket and read the response.
$packet = "GET /get-database HTTP/1.1\r\n";
$packet .= "Host: 192.168.3.136:3689\r\n";
//$packet .= "Accept-Encoding: gzip\r\n";
$packet .= "Viewer-Only-Client: 1\r\n";
$packet .= "Connection: keep-alive\r\n\r\n";
socket_write($socket, $packet, strlen($packet));
do{
$buf = "";
$buf = socket_read($socket, 4096);
$data .= $buf;
}while($buf != "");
echo "$data\r\n\r\n";
If I set the Connection to close then it works and I'm able to read the response. The problem with that is, that after I read the data, I need to write back to the socket. The response contains an id that I need to send back for verification. If I write to the server on two separate sockets, it rejects the verification post back. So I can only assume, that I need to post on same "open connection" or "session".
Any thoughts?
I would like to figure out why I can't read from the socket with Connection: keep-alive
####### EDIT
There has been a little development on this.
I'm trying to make this very simple so I can pinpoint the problem:
Right now my code looks like this:
$fp = pfsockopen("192.168.3.136", "3689");
$content = "GET /login?id=a90347 HTTP/1.1\r\n";
$content .= "Connection: keep-alive\r\n\r\n";
fputs($fp, $content);
while (!feof($fp)) {
echo fgets($fp, 8192);
}
What happens is, as soon as I do my fputs, I get a response header from the server that looks like this:
HTTP/1.1 200 OK
Date: Fri, 05 Mar 2010 22:05:47 GMT
RIPT-Server: iTunesLib/3.0.2 (Mac OS X)
Content-Type: application/x-dmap-tagged
Content-Length: 32
And then my cursor just sits there. After anywhere from 15 seconds to a minute, I sometimes get the content, but I am still stuck in the while loop.
Does anyone know, if after the server has sent the response header, if I should be sending something back to it to let it know that I am ready for the content?
Again, I don't think this is the case, since when I look in the packets on the network, I can see the entire response. That and the fact that I do sometimes get the content of the response. It's really like PHP can't handle this or I am just way off base.
Still need help..... :(
Working Code
$fp = pfsockopen("192.168.3.136", "3689");
$header = "GET /login?id=5648349 HTTP/1.1\r\n";
$header .= "Connection: keep-alive\r\n\r\n";
fputs($fp, $header);
$headers = array();
while(true){
$line = fgets($fp, 8192);
if($line == "\r\n"){ break; }
$line_parts = explode(': ',$line);
echo $line_parts[1]."\r\n";
$headers[$line_parts[0]] = $line_parts[1];
}
$content = fread($fp,intval($headers['Content-Length']));
echo $content;
Now, I'll have to be wary of the "\r\n" test as I'm sure it's possible that some responses might only send a "\n" after the header.
Did you try setting the socket to nonblocking mode?
socket_set_nonblock($socket);
EDIT1: Ok. Just a hunch... try this...
$fp = pfsockopen("192.168.3.136", "3689");
$content = "GET /login?id=a90347 HTTP/1.1\r\n";
$content .= "Connection: keep-alive\r\n\r\n";
fputs($fp, $content);
$headers = array();
do
{
$line = fgets($fp, 8192);
$line_parts = ecplode(': ',$line);
$headers[$line_parts[0]] = $line_parts[1];
} while($line != '');
$content = fread($fp,intval($headers['Content-Length']));
echo $content;

Seeking in remote flv files using PHP

I'm string to seek in a remotely hosted FLV file and have it stream locally. Streaming from start works, but when I try to 'seek', player stops.
I'm using this script to seek to remote file
$fp = fsockopen($host, 80, $errno, $errstr, 30);
$out = "GET $path_to_flv HTTP/1.1\r\n";
$out .= "Host: $host\r\n";
$out .= "Range: bytes=$pos-$end\r\n";
$out .= "Connection: Close\r\n\r\n";
fwrite($fp, $out);
$content = false;
while (!feof($fp))
{
$data = fgets($fp, 1024);
if($content) echo $data;
if($data == "\r\n")
{
$content = true;
header("Content-Type: video/x-flv");
header("Content-Length: " . (urlfilesize($file) - $pos));
if($pos > 0)
{
print("FLV");
print(pack('C', 1));
print(pack('C', 1));
print(pack('N', 9));
print(pack('N', 9));
}
}
}
fclose($fp);
Any ideas ?
UPDATE
so apparently, even though the server signals it accepts range requests (with the Accept-Ranges: bytes), it does not actually do so. to see if there is another way to make the flv seekable, let's have a look at the communication between flash player and server (i use wireshark for this):
the request when starting the player is:
GET /files/xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx/ HTTP/1.1
Host: xxxxxx.megavideo.com
<some more headers>
<no range header>
this is answered with a response like that:
HTTP/1.0 200 OK
Server: Apache/1.3.37 (Debian GNU/Linux) PHP/4.4.7
Content-Type: video/flv
ETag: "<video-id>"
Content-Length: <length of complete video>
<some more headers>
<the flv content>
now when i seek in the flash player, another request is sent. it is almost the same as the initial one, with the following difference:
GET /files/xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx/8800968 HTTP/1.1
<same headers as first request>
which gets answered with a response almost the same as the initial one, with a difference only in the Content-Length header.
which lets me assume that the 8800968 at the end of the request url is the "seek range" (the byte offset in the file after seeking) we are looking for, and the second response Content-Length is the initial Content-Length (the length of the whole file) minus this range. which is the case indeed.
with this information, it should be possible to get what you want. good luck!
UPDATE END
this will only work if the server supports HTTP RANGE requests. if it does, it will return a 206 Partial Content response code with a Content-Range header and your requested range of bytes. check for these in the response to your request.

Categories