# HTTP Client class

Net_HTTP_Client is an almost complete HTTP Client, implementing all HTTP methods and a subset of WebDAV the standard web publishing protocol.
Download httpclient.zip, a zip archive providing the class and documentation.

### Informations

Version : 0.7
Licence : GPL - You may send a mail if you enjoy this component
Lastmod : Aug 2001
Author : Leo West

### Documentation

- Sample use
  - A minimal example
  - Using HTTP/1.1 persistent connexions
- Main methods
  - Net_HTTP_Client( [host, port] )
  - Connect( host, port )
  - Disconnect()
  - setHeaders( headers )
  - removeHeader( headerName )
  - setCredentials( username, password )
  - setProtocolVersion( version )
  - setProxy( proxyHost, proxyPort )
  - addHeader( headerName, headerValue )
  - addCookie( cookieName, cookieValue )
  - removeCookies()
  - Get( uri )
  - getHeaders()
  - getBody()
  - Head( uri )
  - Options( uri )
  - Post( uri, query_params )
- WebDAV methods
  - Copy( srcUri, destUri, overwrite )
  - Delete( uri )
  - Move( srcUri, destUri, overwrite )
  - MkCol( uri )
  - PropFind( uri, scope )
  - Put( uri, filecontent )
  - Lock( uri, lockScope, lockType, lockOwner )
  - Unlock( uri, lockToken )
- Diagnostics and debug
  - getStatus()
  - getStatusMessage()
  - setDebug( flags )
  - Other methods
- Changelog
- References

### Sample use

#### A minimal example

include "Net/HTTP/Client.php";
$http = new Net_HTTP_Client();
$http->Connect( "somehost", 80 ) or die( "Connect problem" );
$status = $http->Get( "/index.html" );
if( $status != 200 )
die( "Problem : " . $http->getStatusMessage() );
else
echo $http->getBody();
$http->Disconnect();

#### Using HTTP/1.1 persistent connexions

$http = new Net_HTTP_Client( "dir.yahoo.com", 80 );
$http->setProtocolVersion( "1.1" );
$http->addHeader( "Host", "dir.yahoo.com" );
$http->addHeader( "Connection", "keep-alive" );
if( $http->Get( "/Reference/Libraries/" ) == 200 )
$page1 = $http->getBody();
if( $http->Get( "/News_and_Media/" ) == 200 )
$page2 = $http->getBody();
$http->disconnect();

### Main methods

#### Net_HTTP_Client( [host, port] )

Class constructor
parameters host and port are optional, but when defined, the connection is immediate.
seeAlso : Connect method

#### Connect( host, port )

Open the connection to the server
host is the server address (or IP)
port is the optional server listening port, defaults to 80
return true if successfull, false is connection failed. Use getStatusMessage to examine the error problem

#### Disconnect()

close the connection to the server

#### setHeaders( headers )

Define all HTTP headers to be sent during next requests.
headers is an array containing the headers in the form "headerName" => "headerValue"
header names are case sensitive in this class.

#### removeHeader( headerName )

unset a request header
headerName is the header name. Be aware i choose to use case sensitive headers.

#### setCredentials( username, password )

Set the username and password to access a protected resource on the server.
Only "Basic" authentication scheme is supported yet
username The user identifier
password The user password (clear form)

#### setProtocolVersion( version )

Define the HTTP protocol version to use
version is a string representing the version number, with one digit: "0.9", "1.0", "1.1"
return false if the version number is bad, true if OK
Note that for some obscure reasons, persistent connexions sometimes fail with some versions of PHP (4.0.6 notably)
Socket gurus, you may track down the problem in the processBody() code.

#### setProxy( proxyHost, proxyPort )

Instruct the class to use a connect through a proxy. Tested only against HTTP proxies (Squid etc.)
proxyHost is the proxy address, proxyPort the proxy port, usually 80 or 8080

#### addHeader( headerName, headerValue )

Define a request header to be sent during next requests. headerName is case sensitive
headerName HTTP header name
headerValue HTTP header value

#### addCookie( cookieName, cookieValue )

set a cookie to use for the next requests
cookie is a session-type cookie. cookieName cookie name
cookieValue cookie value
[since v0.7]

#### removeCookies( )

discards all defined cookies
[since v0.7]

#### Get( uri )

issue a GET http request
$uri is the URI of the document
Returns the status code received from server (200 if ok)
see Also getHeaders & getBody methods

#### getHeaders()

return the response headers. Headers are returned as an (headername => value) array.
To be called after a request, to examine the headers returned by server: Set-Cookie, Location or whatever.

$status = $http->Get( "/" );
...
// document is somewhere else
if( $status == 301 || $status == 302 || $status == 307 )
{
$headers = $http->getHeaders();
$status = $http->Get( $headers["Location"] );
}

#### getBody()

return a string containing the response body, to be used after a Get or Post call for instance.

#### Head( uri )

issue a HEAD request
$uri is a string containing the URI of the document ( the part of the URL after the host and port /)
Returns the status code received from server (200 if ok)
To examine the headers content, see getResponseHeaders method

#### Options( uri )

issue an OPTIONS request
uri document URI, usually "/"
Returns an array with the options supported by the server
[since v0.7]

#### Post( uri, query_params )

issue a POST http request
uri is the URI of the document
query_params is an hash array containg the form parameters to send
Returns the status code received from server (200 if ok)
Example

$params = array( "login" => "scott", "password" => "tiger" );
$status = $http->post( "/login.php", $params );

### WebDAV methods

#### Copy( srcUri, destUri, overwrite )

Copy an existing file on the server into a new place, using the COPY request
srcUri is the current file location on the server. dont forget the heading "/"
destUri is the destination location on the server. this is *not* a full URL
overwrite indicates whether to overwrite (true) or leave (false) an existing destination. overwrite by default
Returns the status code 204 (Unchanged) if OK.
$status = $http->Copy( "/sources/client.php", "/backup/client-0.4.php", true );

#### Delete( uri )

Delete a file on the server using the "DELETE" HTTP-DAV request
uri the location of the file on the server.
Returns the status code (204 if OK)
Note: This HTTP method is *not* widely supported, and only partially supports "collection"
deletion, as the XML response is not parsed.

#### Move( srcUri, destUri, overwrite )

Move or rename a resource on the server, using the MOVE request.
srcUri is the current file location on the server. dont forget the heading /
destUri the destination location on the server. this is *not* a full URL
overwrite is a boolean set to true to overwrite an existing destination.
Return the response status code as a string, 204 (Unchanged) if OK.

#### MkCol( uri )

Send a MKCOL HTTP-DAV request
Create a collection (usually a directory) on the server.
uri is the collection's location on the server.
Return the status code, 201 (Created) if OK

#### PropFind( uri, scope )

Retrieves meta informations about a resource on the server, using the WebDAV PROPFIND method
The XML reply body is not parsed, therfore you will have to do it :)
uri the location of the file on the server
scope set the scope of the request, (somehow similar to the LDAP scope notion):
To retrieve infos about the node only (0), for the node and its direct children (1), or "Infinity" infos for the node and all its descendant nodes.
Returns the response status code, 207 (Multi-Status) if OK

#### Put( uri, filecontent )

Send a PUT request
PUT is the method to sending a file on the server. it is *not* widely supported
uri the location of the file on the server. dont forget the heading "/"
filecontent is the content of the file. binary content accepted
Returns the status code as a string, 201 (Created) if OK.

#### Lock( uri, lockScope, lockType, lockOwner )

WARNING: experimental
Lock a ressource on the server and return 200 if locking went OK.
The XML reply is not parsed for now [translate: Your help is welcome].
uri URL of the resource to lock
lockScope scope of the lock. Use "exclusive" for an private lock, "inclusive" for a shared lock.
lockType Access type for the lock : Use "write", ?
lockOwner An URL representing the owner of this lock

$reply = $http->Lock( "/docs/manual.html", "inclusive", "write", "leo@leo.com" );
if( $reply != 200 ) {
$msg = $http->getStatusMessage();
die( "Unlock problem, server says $msg" );
} else {
$xmlResponse = $http->getBody();
// TODO : parse the XML response here
}

#### Unlock( uri, lockToken )

WARNING: experimental
Release a lock on a remote file and return the response code (204 if unlock OK)
uri The relative URL of the resource to unlock
lockToken The lock token given at lock time, eg: opaquelocktoken:e71d4fae-5dec-22d6-fea5-00a0c91e6be4

$token = "opaquelocktoken:e71d4fae-5dec-22d6-fea5-00a0c91e6be4";
$reply = $http->Unlock( "/docs/manual.html", $token );
if( $reply != 204 ) {
$msg = $http->getStatusMessage();
die( "Unlock problem, server says $msg" );
}

### Diagnostics and debug

#### getStatus()

Return the server status code for the last request.
HTTP codes are divided in classes (where x is a digit)
- 20x : request processed OK
- 30x : document moved
- 40x : client error ( bad url, document not found, etc...)
- 50x : server error

#### getStatusMessage()

Returns the full response status of the last request, in the form "CODE Message"
Example : 404 Document not found

#### setDebug( flags )

Turn on debug messages
$client->setDebug( DBGTRACE | DBGINDATA );
Flags is a bit mask of following debug modes:

DBGTRACE | to trace methods calls stack
DBGINDATA | to debug data received from server
DBGOUTDATA | to debug data sent
DBGLOW | to debug low-level (usually internal) methods
DBGSOCK | to debug socket-level stuff

#### Other methods

sendCommand, makeURI, processReply, processHeader, processBody, readReply, flushReply
These methods are private therefore not documented and USUALLY NOT FOR DIRECT USE.

### Changelog

    	0.1 initial version
    	0.2 documentation completed
    	    + getHeaders(), getBody()
    		 o Post(), Connect()
    	0.3 DAV enhancements:
    		 + Put() method
    	0.4 continued DAV support
    		 + Delete(), Move(), MkCol(), Propfind()  methods
    		 o added url property, remove host and port properties
    		 o Connect, Net_HTTP_Client (use of this.url)
    		 o processBody() : use non-blocking to fix a socket pblm
    	0.5 debug support
    		 + setDebug()
    		 + debug levels definitions (DBG*)
    	0.6 + Lock() method
    		 + setCredentials() method and fix - thanks Thomas Olsen
    		 + support for Get( full_url )
    		 o fix POST call (duplicate content-length) - thanks to Javier Sixto
    	0.7 + OPTIONS method support
    	    + addCookie and removeCookies methods
    	    o fix the "0" problem
    	    o fix undefined variable warning

### References

RFC2616 "Hypertext Transfer Protocol -- HTTP/1.1"
http://lwest.free.fr/doc/protocols/http/rfc2616.html
RFC2518 "HTTP Extensions for Distributed Authoring WEBDAV"
http://lwest.free.fr/doc/protocols/http/rfc2518.html
WebDAV Community Site
http://www.webdav.org