I see come code from PHP manual
$fp = fsockopen("www.example.com", 80, $errno, $errstr, 30);
if (!$fp) {
echo "$errstr ($errno)<br />\n";
} else {
$out = "GET / HTTP/1.1\r\n";
$out .= "Host: www.example.com\r\n";
$out .= "Connection: Close\r\n\r\n";
fwrite($fp, $out);
while (!feof($fp)) {
echo fgets($fp, 128);
}
fclose($fp);
}
writing header by echo, is this going to work?
when just calling simple code like this:
echo 'hello';
where the http headers from?
What you're doing in this code is:
Open a socket connection to a remote HTTP server (www.example.com on port 80). This establishes a TCP connection to that port.
You then send (via fwrite) an HTTP request over this connection. HTTP is a protocol on top of TCP, and you're manually formulating your HTTP protocol headers here.
You're then reading (via fgets) the (HTTP) response of the remote server.
I'm guessing that you want to know why you see HTTP headers in this remote response, even though you're only doing echo 'hello'; on the remote server. The answer is because the web server running on that server is handling the HTTP transaction. You're not handling any details of the incoming HTTP request in PHP, and you're also not handling any details of the outgoing response. The web server on which PHP is running (likely Apache) is doing that.
The whole stack includes a TCP connection, which carries an HTTP request, which consists of HTTP headers and an HTTP body. On the server, the TCP connection is typically handled by the underlying operating system, which makes the connection available as a socket to the web server, where the web server "unwraps" the HTTP request to handle it and invoke PHP if necessary, and then the whole chain goes backwards for the response.
Related
My code should check email boxes via proxy with PHP using SSL.
Zend\Mail package provides implementation of both protocols without php extention and fits fine.
I partially override connect() method by code:
$this->socket = fsockopen($proxy, $proxy_port, $errno, $errstr, self::TIMEOUT_CONNECTION);
$this->sendRequest("CONNECT {$host}:{$port} HTTP/1.1");
$this->sendRequest("Host: {$host}:{$port}");
$this->sendRequest($userAgent);
$this->sendRequest("Proxy-Authorization: basic " . base64_encode("$user:$pass") . "\r\n");
// Remove 2 lines with proxy response
fgets($this->socket);
fgets($this->socket);
With unsecure connection everything works fine, but not works for secured port.
Connections on 110 port rejected by server with "please use SSL/TLS", when script tries to connect on secure port 995, nothing happend, no any response from mail server.
Probably, I missed one more HTTP header or so.
Anybody knows which command need send to end server through HTTP tunnel to start SSL connection?
I have a webserver which serves the client with an octet stream on port 20000 (it's actually a socket.io server hosted with node.js). This is running on a shared hosting account with a regular Apache server running on port 80 (this cannot be turned off, hence the socket.io server is on port 20000). Due to firewalls and such, I cannot expect the user to be able to connect to port 20000 (or any other than 80). So, how can I serve the client with the octet stream produced by the socket.io server from the Apache server (sort of like a reverse proxy)? Unfortunately I cannot use mod_proxy on my Apache server given restraints of my hosting plan. I was thinking I could do this with a PHP page that opens a socket somehow.
Update: I also have Django for Python 3 installed on my server which could be useful. Please note that the proxy cannot simply request the target page and serve it back to the client since the data has to be transferred in real time.
Re "it cannot simply serve the target page back" ... this is not true because this is all an HTTP proxy is. Most protocol proxies use a socket (versus a file or pipe) and simply copy the data from socket to socket. An HTTP proxy does the same thing except every HTTP request requires a handshake, so the proxy will require a few packets back and forth before reaching the payload. You can create an HTTP GET proxy very easily in django. A POST proxy will need extra footwork.
I am not familiar with Socket.IO, but upon researching ... how does socket.io work? ... it appears it uses only "old" HTTP features and runs everything as REST. The REST is encapsulated as a transport inside of a persistent socket.
If you were looking for an TCP or IP-level proxy within Django, its not going to happen. Your apache server, and then WSGI/CGI/whatever closes the TCP socket off from you. The only way you'll be able to access it is with sufficient permissions to those parts of the server.
Here's what I'd do ... In django make a url pattern that captures the socket.io api, and have it connect to a view that does something like the following (untested pseudo code):
import urllib2, mimetypes
from django.http import HttpResponse
def ForwardToSocketIO(request):
# Capture the URL pattern
path = request.get_full_path()
# Create a URL opener
response = urllib2.urlopen('http://localhost:20000%s' % path)
# Capture and return response
django_response = HttpResponse(response.read())
django_response['Content-Type'] = 'octet-stream'
return django_response
Hope this helps. I don't have an octet stream available so apologies for not testing.
Seems possible not impossible. I have not done it before but know the way to do but again I don't know the impact of Firewall on port openning and closing. The basic Idea about doing thing is:
Get you request from port 80 to do things and for response of that request use different port to communicate with client. It would become a tunnel to recieve request from one port and get reply from the other port. Only one thing to be properly taken care of that termination of connection as soon as possible once the purpose is resolve unless it would create memory load on the server.
With the below example you can do the above things but suggest you to use them with caution and after proper testing.
ref: Programming with Sockets through PHP
This example shows a simple talkback server. Change the address and port variables to suit your setup and execute. You may then connect to the server with a command similar to: telnet 192.168.1.53 10000 (where the address and port match your setup). Anything you type will then be output on the server side, and echoed back to you. To disconnect, enter 'quit'.
<?php
error_reporting(E_ALL);
echo "<h2>TCP/IP Connection</h2>\n";
/* Get the port for the WWW service. */
$service_port = getservbyname('www', 'tcp');
/* Get the IP address for the target host. */
$address = gethostbyname('www.example.com');
/* Create a TCP/IP socket. */
$socket = socket_create(AF_INET, SOCK_STREAM, SOL_TCP);
if ($socket === false) {
echo "socket_create() failed: reason: " .
socket_strerror(socket_last_error()) . "\n";
} else {
echo "OK.\n";
}
echo "Attempting to connect to '$address' on port '$service_port'...";
$result = socket_connect($socket, $address, $service_port);
if ($result === false) {
echo "socket_connect() failed.\nReason: ($result) " .
socket_strerror(socket_last_error($socket)) . "\n";
} else {
echo "OK.\n";
}
$in = "HEAD / HTTP/1.1\r\n";
$in .= "Host: www.example.com\r\n";
$in .= "Connection: Close\r\n\r\n";
$out = '';
echo "Sending HTTP HEAD request...";
socket_write($socket, $in, strlen($in));
echo "OK.\n";
echo "Reading response:\n\n";
while ($out = socket_read($socket, 2048)) {
echo $out;
}
echo "Closing socket...";
socket_close($socket);
echo "OK.\n\n";
?>
I'm writing a tool that connects to a server, sends request, read response, and send other commands.
The problem is that the response the server send can vary in terms of lines (it's always at least one line, but can be 3, 5 lines), and he can send one line, wait a few seconds, then send others lines.
Is there a way to read all the incoming data until they stop?
Maybe I have to change for sockets?
Here are my tries :
$fp = fsockopen("www.example.com", 25, $errno, $errstr, 30);
-
while(fgets($fp, 1024)) {} // hangs
-
fgets($fp, 4096); // works, but doesn't get the multiple lines
-
while(!feof($fp)){
fgets($fp, 1024);
}
// hangs
-
while(($c = fgetc($fp))!==false) {
var_dump($c);
}
// hangs
You are using a TCP connection. A TCP connection will stay open unless one of the communication partners explicitly closes it.
This means
while(!feof($fp)) {
fgets($fp);
}
will hang forever unless the server closes the connection after transfer. (It seems that the remote server does not). This applies to while(fgets($fp, 1024)) {} as well.
The other option would be that the client (your PHP script) closes the connection. This can be done safely only if the client knows the size of the message and can decide when all the bytes has been sent.
Implementing this is a protocol feature, in HTTP for example the content-length header is used.
Having that you connecting to port 25, I assume that you are speaking with an SMTP server. SMTP manages the message length as a protocol feature. You'll need to implement the SMTP protocol.
About:
$message = fgets($fp, 4096);
It "works" only if it is sure that the message will never exceed 4096 bytes. The newlines are still in the result, you simply would need to
$lines = explode("\n", $message);
I don't understand when should we use stream wrapper and socket. Can anyone tell me when should we use stream wrapper and socket in PHP?
Please give me some example regarding the same.
StreamWrappers
Quoting the PHP Manual at Streams: Introduction:
A wrapper is additional code which tells the stream how to handle specific protocols/encodings. For example, the http wrapper knows how to translate a URL into an HTTP/1.0 request for a file on a remote server. There are many wrappers built into PHP by default (See Supported Protocols and Wrappers)
You use Stream wrappers whenever you are opening URLs, FTP connection, etc with functions like fopen or file_get_contents. Stream wrappers have the benefit that you do not need to know much about the protocol (unless you write your own custom wrapper).
Since you you funnel all access through the regular file functionsÂDocs, you do not need to learn another API which is a benefit. You likely already used Stream Wrappers without noticing it, for instance, when you did
$pageContent = file_get_contents('http://example.com');
somewhere in your code. Another benefit of Stream Wrapper is that you can put filters in front and modify the stream with minimal effort, for instance
$unzipped = file_get_contents('compress.zlib://http://example.com');
would run the content from that webpage through gzip decompression.
Sockets
Quoting the PHP Manual at Sockets: Introduction:
The socket extension implements a low-level interface to the socket communication functions based on the popular BSD sockets, providing the possibility to act as a socket server as well as a client.
Since PHP provides a number of Stream Wrappers out of the box and also has an API for almost everything, there is rarely any Use Case for using Sockets.
You use sockets when you need to implement at the protocol level to implement a client or a server for a certain protocol. This usually requires in-depth knowledge of the implemented protocol, for instance, to do the same as the file_get_contents call in the example above, you'd need to do (example quoted from manual, you even need to do more actually)
$fp = fsockopen("www.example.com", 80, $errno, $errstr, 30);
if (!$fp) {
echo "$errstr ($errno)<br />\n";
} else {
$out = "GET / HTTP/1.1\r\n";
$out .= "Host: www.example.com\r\n";
$out .= "Connection: Close\r\n\r\n";
fwrite($fp, $out);
while (!feof($fp)) {
echo fgets($fp, 128);
}
fclose($fp);
}
As you can see, instead of just calling the URL and let the Stream Wrapper handle all the nitty gritty details you need to know how to construct an HTTP request and how to parse a HTTP response.
You might also find this tutorial about Socket Programming helpful:
http://christophh.net/2012/07/24/php-socket-programming/
I have urls of the following format (I write it as as aregex):
http://exampledomain\.com/files/.+
The URL is requested by a client over my proxy server.
I inject a custom authorization header into this request.
This is no problem, I can do that with mod_proxy and mod_headers in apache.
However this url gives a 302 redirect to another source, that finally should arrive at the client.
This other url is SSL secured and looks like:
https://example.+\.exampledomain.\com/files/.+/.+
It needs the same authorization header than the other one. But because its hTTPS I cannot simply inject it using mod headers.
Therefore my plan is to set up a reverse proxy that I use to request the first HTTP URL with an authorization header. Behind is a script that fetches the request, parses out the second HTTPS URL and Downloads the source with the custom authorization header and passes the received file (bytes and http headers) through to the client.
I am familiar with Apache2 and PHP, therefore it would be nice to stick with theese. But its not necessary.
Just to clarify, we are talking about rapidshare links here. My company is having backup files and storage there, because its the cheapest cloud hosting. There are some job servers that need to fetch files, but I can not configure user/password on them. So the proxy server should add the premium authentication information.
I thought about something like:
proxy.php - this file is requested using the reverse proxy and served by a webserver
this proxy php is written to by a htaccess rewrite rule and by the revery proxy on http://one-or-my-domoains/request-uri-from-the-original-request (That is generated in apache)
$url = "http://example.com/".$_SERVER["REQUEST_URI"];
$opts = array(
'http'=>array(
'header'=>"Cookie: myauthvalue=example\r\n"
)
);
$context = stream_context_create($opts);
stream_context_set_default($context);
$http_content = get_headers($url, 1);
$ssl_location = $http_content['Location'];
$fp = fsockopen("ssl://".parse_url($ssl_location, PHP_URL_HOST), 443, $errno, $errstr, 30);
if (!$fp) {
echo "$errstr ($errno)<br />\n";
} else {
$out = "GET ".parse_url($PHP_URL_PATH, PHP_URL_HOST)." HTTP/1.1\r\n";
$out .= "Host: ".parse_url($ssl_location, PHP_URL_HOST)."\r\n";
$out .= "Cookie: myauthorization=something";
fwrite($fp, $out);
while (!feof($fp)) {
echo fgets($fp, 128);
}
fclose($fp);
}
So this should basically pass the ssl download to the standard http connection that the user initiates, instead of the redirect.
My question now is: Will this work? Did I miss something? Are there any caveeats?
I think it will be a reasonable amount of hassle, including the reverse proxy setup and all.
well i ended up just doing passthru('wget ....') wich works just fine ;)