Create HTTPs request with phpWebrequest

I received several emails about my phpWebRequest php class, asking how we can create HTTPs POST request. Before I answer this I think it’s important to understant the HTTP authentication mechanism.

There are 2 kinds of authentication: Basic and Digest. I gonna describe only Basic since it’s very is to use in the phpWebRequest class.

Basic is the easiest authentication to setup, since it do not provide any encryption during the transmission of the HTTP request.
Here is what happens when you try to reach a secured page (on https://a.server.com/the/secure/page.dll)

Client:
GET /the/secure/page.dll HTTP/1.1
Server:
HTTP/1.1 401 Authorization Required
WWW-Authenticate: Basice realm="Basic Realm"

In the answer we have from the server, we can see that a Basic authentication is required. That means in our HTTP header we need to add a field called Authorization that contains the login and password to reach the secured page. In our case the login is myLogin and the password is myPasswrd . The new Authorization field value will be myLogin:myPasswd encoded as a base64 string so bXlMb2dpbjpteVBhc3N3ZCA=
We can now try to reach the page :

Client:
GET /the/secure/page.dll HTTP/1.1
Authorization: Basic bXlMb2dpbjpteVBhc3N3ZCA=
Server:
HTTP/1.1 200

Here is how to do that with the phpWebRequest class:

<?php
require_once('phpWebRequest.class.php');

$XMLString = '<?xml version="1.0" encoding="UTF-8"?><root><elems><e1>Element1</e1></elems></root>';

$rq = new PhpWebRequest();
$passwd =base64_encode("myLogin:myPasswd") ;

$rq->InitServer("256.256.256.256","/the/secure/page.dll");

$strSize = $rq->DataReaderFactory($XMLString);

$rq->InitRequest("POST");

$headerElements = array("Host" => "256.256.256.256",
						"Authorization" => "Basic ".$passwd,
                        "Connection" => "Close",
                        "Content-type" => "multipart/mixed",
                        "Content-length" => $strSize
                        );

$rq->CfgHeader($headerElements);

if($rq->SendRequest()){
    echo "Request sent !";
}
else{
    echo "ERROR";
}

?>

You can also have a look to the RFC2617 for more details on Basic and Digest.

How to Create/Read HTTP POST request

This post is actually a follow-up to my last one called http post streaming where I tried to create a php class that provides a way to send a HTTP POST request. I recoded the class and added new features (e.g. a way to read the body of an HTTP request, a dynamic way of setting the headers fields…etc.).

The body of an HTTP request can be easily read from php by using php://input stream. This stream return the raw POST data.

The phpWebRequest class is still under developpment but I post it because it may help some of you. (Of course anytime I add a feature I will update this post)

TO DO:

  • Finish the DataReaderFactory so we can use either read from an url or file to create the body of the request.
  • Create an HTTPs support

 

phpWebRequest
 

<?php
/*
PhpWebRequest objects provide methods to send or read HTTP requests
Date: June-08
Author: Guillaume Nachury
Version: 0.1

*/

class PhpWebRequest{
//VERSION
var $version = "0.1";

//HTTP
var $boundary;
var $method;
var $header;
var $body;
var $protocol;
var $headerElements; 

//SERVER
var $address;
var $path;
var $port;

var $isOverSSL = false;

//FEED
var $xml;

/**
* InitServer()
* $a = server address
* $p = path to the ressource
* $prt = port (by default 80)
*/
function InitServer($a,$p,$prt=80){
$this->address = $a;
$this->path = $p;
$this->port = $prt;
}

/**
* InitRequest()
* $m = the HTTP method you wanna use
* $secured = in case we use HTTPS
* $bounds = a string to create a boundary (unused since v 0.1)
*/
function InitRequest($m, $secured = false, $bounds="PhpWebRequest"){
$this->method = $m;
$this->boundary = md5($bounds);
$this->isOverSSL = $secured;
if($this->isOverSSL === false){
$this->protocol = "HTTP/1.1";
}
else{
$this->protocol = "HTTPS";
}
}

/**
* DataReaderFactory()
* a factory that can read data from either a file, an URL or a String to be used as the content of the request
* $u = the path to the data ( for a file start with file://
* for an URL start with http://
* for string just enter chars)
*/
function DataReaderFactory($u){
//if we wanna read from a file
if(strpos($u,'file://' ) === true){

}
//or from a remote web page
elseif(strpos($u,'http://' ) === true){

}
//a string have been passed
else{
$this->xml=$u;
return strlen($this->xml);
}
}

/**
* CfgHeader()
* Create the HTTP header fields
* $attributesArray = an array of headers that MUST have keys
* keys = field name
* value = field calue
*/
function CfgHeader($attributesArray){
while(list($k,$v) = each($attributesArray)){
$this->headerElements .= $k.": ".$v."\n";
}
}

/**
* CraftRequest()
* Create a HTTP request
*/
function CraftRequest(){
$this->header = $this->method." ".$this->path." ".$this->protocol. "\n".$this->headerElements."\n";
$this->body = $this->xml."\n";
}

/**
* SendRequest()
* Send the request, return true if successfully sent
*/
function SendRequest(){
$this->CraftRequest();
$request = $this->header.$this->body;

$fs = fsockopen($this->address,$this->port);
if(!$fs){
return false;
}
else{
fputs($fs,$request);
fflush($fs);
fclose($fs);
return true;
}

}

/**
* readHTTPRequest()
* return the HTTP request BODY
*/
function readHTTPRequest(){
return @file_get_contents('php://input');
}

}
?>

Usage :

<?php
require_once('phpWebRequest.class.php');

$rq = new PhpWebRequest();
$rq->InitServer("127.0.0.1","/aPath/test.php");
$strSize = $rq->DataReaderFactory("the body of the request");
$rq->InitRequest("POST");

//header fields
$headerElements = array("Host" => "127.0.0.1",
"Connection" => "Close",
"Content-type" => "multipart/mixed",
"Content-length" => $strSize
);
//load the headers
$rq->CfgHeader($headerElements);

//send it
if($rq->SendRequest()){
echo "Request sent !";
}
else{
echo "ERROR";
}

?>

If you have any question feel free to send me an email.

HTTP POST Streaming

Yesterday I’ve been asked by a friend how we can easily http stream data from php. That was a really intersting question because it can be very useful in some case (e.g. when working with EDI). So I just made him a proof of concept.
I used socket to generate a POST HTTP request 

<?php
class PostRequest{
	//SERVER
	var $address;
	var $path;
	var $port;
	
	//XML
	var $xmlFile;
	
	//HTTP 
	var $boundary;
	
	
	
	function initRequest($addr, $p, $prt=80){
		$this->address = $addr;
		$this->path = $p;	
		$this->port = $prt;
		$this->boundary = md5("myString");
		
	}
	
	function setXML($x){
		$this->xmlFile = $x;
	}
	
	function send(){
	$fs = fsockopen($this->address, $this->port);
	if(!$fs){
		return false;	
		}
	else{
		$header ="POST ".$this->path." HTTP/1.0 200\r\nMIME-Version: 1.0\r\nContent-Type: multipart/mixed; boundary=".$this->boundary."\r\n\n";
		$this->body ="--".$this->boundary."\n
						Content-type: text/plain\n\n".$this->xmlFile."\n--".$this->boundary."\n";
						
		$request = $header.$this->body;
		
		
		fputs($fs,$request);
		fflush();
	fclose();
		return true;	
	
		}
	
	}



?>

I post the code but I will update it very soon since I’ve only made few test and I think it must be tweaked