SFML/DSFML/import/dsfml/network/http.d

395 lines
15 KiB
D

/*
* DSFML - SFML Library binding in D language.
* Copyright (C) 2008 Julien Dagorn (sirjulio13@gmail.com)
*
* This software is provided 'as-is', without any express or
* implied warranty. In no event will the authors be held
* liable for any damages arising from the use of this software.
*
* Permission is granted to anyone to use this software for any purpose,
* including commercial applications, and to alter it and redistribute
* it freely, subject to the following restrictions:
*
* 1. The origin of this software must not be misrepresented;
* you must not claim that you wrote the original software.
* If you use this software in a product, an acknowledgment
* in the product documentation would be appreciated but
* is not required.
*
* 2. Altered source versions must be plainly marked as such,
* and must not be misrepresented as being the original software.
*
* 3. This notice may not be removed or altered from any
* source distribution.
*/
module dsfml.network.http;
import dsfml.system.stringutil;
import dsfml.system.common;
/**
* HTTP methods enumeration
*/
enum HttpMethod
{
GET, ///< Request in get mode, standard method to retrieve a page
POST, ///< Request in post mode, usually to send data to a page
HEAD ///< Request a page's header only
}
/**
* HTTP response status code
*/
enum HttpStatus
{
// 2xx: success
OK = 200, ///< Most common code returned when operation was successful
CREATED = 201, ///< The resource has successfully been created
ACCEPTED = 202, ///< The request has been accepted, but will be processed later by the server
NOCONTENT = 204, ///< Sent when the server didn't send any data in return
// 3xx: redirection
MULTIPLECHOICES = 300, ///< The requested page can be accessed from several locations
MOVEDPERMANENTLY = 301, ///< The requested page has permanently moved to a new location
MOVEDTEMPORARILY = 302, ///< The requested page has temporarily moved to a new location
NOTMODIFIED = 304, ///< For conditionnal requests, means the requested page hasn't changed and doesn't need to be refreshed
// 4xx: client error
BADREQUEST = 400, ///< The server couldn't understand the request (syntax error)
UNAUTHORIZED = 401, ///< The requested page needs an authentification to be accessed
FORBIDDEN = 403, ///< The requested page cannot be accessed at all, even with authentification
NOTFOUND = 404, ///< The requested page doesn't exist
// 5xx: server error
INTERNALSERVERERROR = 500, ///< The server encountered an unexpected error
NOTIMPLEMENTED = 501, ///< The server doesn't implement a requested feature
BADGATEWAY = 502, ///< The gateway server has received an error from the source server
SERVICENOTAVAILABLE = 503, ///< The server is temporarily unavailable (overloaded, in maintenance, ...)
// 10xx: SFML custom codes
INVALIDRESPONSE = 1000, ///< Response is not a valid HTTP one
CONNECTIONFAILED = 1001 ///< Connection with server failed
}
/**
* This class provides methods for manipulating the HTTP protocol (described in
* RFC 1945).
* It can connect to a website, get files, send requests
*/
class Http : DSFMLObject
{
/**
* Wrapper for a http request, which is basically :
* - a header with a method, a target URI and a set of field/value pairs
* - an optional body (for POST requests)
*/
static class Response : DSFMLObject
{
override void dispose()
{
sfHttpResponse_Destroy(m_ptr);
}
/**
* Get the value of a field
*
* Params:
* field = Name of the field to get (case-insensitive)
* Returns:
* Value of the field, or enpty string if not found
*/
char[] getField(char[] field)
{
return fromStringz(sfHttpResponse_GetField(m_ptr, toStringz(field)));
}
/**
* Get the header status code
*
* Returns:
* header status code
*/
HttpStatus getStatus()
{
return sfHttpResponse_GetStatus(m_ptr);
}
/**
* Get the major HTTP version number of the response
*
* Returns:
* Major version number
*/
uint getMajorHTTPVersion()
{
return sfHttpResponse_GetMajorVersion(m_ptr);
}
/**
* Get the minor HTTP version number of the response
*
* Returns:
* Minor version number
*/
uint getMinorHTTPVersion()
{
return sfHttpResponse_GetMinorVersion(m_ptr);
}
/**
* Get the body of the response. The body can contain :
* - the requested page (for GET requests)
* - a response from the server (for POST requests)
* - nothing (for HEAD requests)
* - an error message (in case of an error)
*
* Returns:
* the response body
*/
char[] getBody()
{
return fromStringz(sfHttpResponse_GetBody(m_ptr));
}
private:
this(void* ptr)
{
super(ptr);
}
// External ================================================================
extern (C)
{
typedef void function(void*) pf_sfHttpResponse_Destroy;
typedef char* function(void*, char*) pf_sfHttpResponse_GetField;
typedef HttpStatus function(void*) pf_sfHttpResponse_GetStatus;
typedef uint function(void*) pf_sfHttpResponse_GetMajorVersion;
typedef uint function(void*) pf_sfHttpResponse_GetMinorVersion;
typedef char* function(void*) pf_sfHttpResponse_GetBody;
static pf_sfHttpResponse_Destroy sfHttpResponse_Destroy;
static pf_sfHttpResponse_GetField sfHttpResponse_GetField;
static pf_sfHttpResponse_GetStatus sfHttpResponse_GetStatus;
static pf_sfHttpResponse_GetMajorVersion sfHttpResponse_GetMajorVersion;
static pf_sfHttpResponse_GetMinorVersion sfHttpResponse_GetMinorVersion;
static pf_sfHttpResponse_GetBody sfHttpResponse_GetBody;
}
static this()
{
DllLoader dll = DllLoader.load("csfml-network");
sfHttpResponse_Destroy = cast(pf_sfHttpResponse_Destroy)dll.getSymbol("sfHttpResponse_Destroy");
sfHttpResponse_GetField = cast(pf_sfHttpResponse_GetField)dll.getSymbol("sfHttpResponse_GetField");
sfHttpResponse_GetStatus = cast(pf_sfHttpResponse_GetStatus)dll.getSymbol("sfHttpResponse_GetStatus");
sfHttpResponse_GetMajorVersion = cast(pf_sfHttpResponse_GetMajorVersion)dll.getSymbol("sfHttpResponse_GetMajorVersion");
sfHttpResponse_GetMinorVersion = cast(pf_sfHttpResponse_GetMinorVersion)dll.getSymbol("sfHttpResponse_GetMinorVersion");
sfHttpResponse_GetBody = cast(pf_sfHttpResponse_GetBody)dll.getSymbol("sfHttpResponse_GetBody");
}
}
/**
* Wrapper for a HTTP response which is basically :
* - a header with a status code and a set of field/value pairs
* - a body (the content of the requested resource)
*/
static class Request : DSFMLObject
{
/**
* Constructor
*
* Params:
* requestMethod = Method to use for the request (Get by default)
* uri = Target URI ("/" by default -- index page)
* requestBody = Content of the request's body (empty by default)
*/
this(HttpMethod requestMethod = HttpMethod.GET, char[] uri = "/", char[] requestBody = "")
{
super(sfHttpRequest_Create());
sfHttpRequest_SetMethod(m_ptr, requestMethod);
sfHttpRequest_SetURI(m_ptr, toStringz(uri));
sfHttpRequest_SetBody(m_ptr, toStringz(requestBody));
}
/**
* Set the value of a field. Field is created if it doesn't exists.
*
* Params:
* field = name of the field to set (case-insensitive)
* value = value of the field
*/
void setField(char[] field, char[] value)
{
sfHttpRequest_SetField(m_ptr, toStringz(field), toStringz(value));
}
/**
* Set the request method.
*
* Params:
* requestMethod = Method to use for the request.
*/
void setMethod(HttpMethod requestMethod)
{
sfHttpRequest_SetMethod(m_ptr, requestMethod);
}
/**
* Set the target URI of the request.
*
* Params:
* uri = URI to request, local to the host.
* Returns:
*/
void setURI(char[] uri)
{
sfHttpRequest_SetURI(m_ptr, toStringz(uri));
}
/**
* Set the HTTP version of the request.
*
* Params:
* major = Major version number
* minor = Minor version number
*/
void setHttpVersion(uint major, uint minor)
{
sfHttpRequest_SetHttpVersion(m_ptr, major, minor);
}
/**
* Set the body of the request. This parameter is optionnal and make sense
* only for POST requests.
*
* Params:
* requestBody = Content of the request body.
*/
void setBody(char[] requestBody)
{
sfHttpRequest_SetBody(m_ptr, toStringz(requestBody));
}
private:
// External ================================================================
extern (C)
{
typedef void* function() pf_sfHttpRequest_Create;
typedef void function(void*) pf_sfHttpRequest_Destroy;
typedef void function(void*, char*, char*) pf_sfHttpRequest_SetField;
typedef void function(void*, HttpMethod) pf_sfHttpRequest_SetMethod;
typedef void function(void*, char*) pf_sfHttpRequest_SetURI;
typedef void function(void*, uint, uint) pf_sfHttpRequest_SetHttpVersion;
typedef void function(void*, char*) pf_sfHttpRequest_SetBody;
static pf_sfHttpRequest_Create sfHttpRequest_Create;
static pf_sfHttpRequest_Destroy sfHttpRequest_Destroy;
static pf_sfHttpRequest_SetField sfHttpRequest_SetField;
static pf_sfHttpRequest_SetMethod sfHttpRequest_SetMethod;
static pf_sfHttpRequest_SetURI sfHttpRequest_SetURI;
static pf_sfHttpRequest_SetHttpVersion sfHttpRequest_SetHttpVersion;
static pf_sfHttpRequest_SetBody sfHttpRequest_SetBody;
}
static this()
{
DllLoader dll = DllLoader.load("csfml-network");
sfHttpRequest_Create = cast(pf_sfHttpRequest_Create)dll.getSymbol("sfHttpRequest_Create");
sfHttpRequest_Destroy = cast(pf_sfHttpRequest_Destroy)dll.getSymbol("sfHttpRequest_Destroy");
sfHttpRequest_SetField = cast(pf_sfHttpRequest_SetField)dll.getSymbol("sfHttpRequest_SetField");
sfHttpRequest_SetMethod = cast(pf_sfHttpRequest_SetMethod)dll.getSymbol("sfHttpRequest_SetMethod");
sfHttpRequest_SetURI = cast(pf_sfHttpRequest_SetURI)dll.getSymbol("sfHttpRequest_SetURI");
sfHttpRequest_SetHttpVersion = cast(pf_sfHttpRequest_SetHttpVersion)dll.getSymbol("sfHttpRequest_SetHttpVersion");
sfHttpRequest_SetBody = cast(pf_sfHttpRequest_SetBody)dll.getSymbol("sfHttpRequest_SetBody");
}
}
/**
* Constructor
*/
this()
{
super(sfHttp_Create());
}
/**
* Constructor
*
* Params:
* host = Web server to connect to
* port = port to use for connection (0 by default -- use the standard port of the protocol)
*/
this(char[] host, ushort port = 0)
{
super(sfHttp_Create());
sfHttp_SetHost(m_ptr, toStringz(host), port);
}
override void dispose()
{
sfHttp_Destroy(m_ptr);
}
/**
* Set the target host.
*
* Params:
* host = Web server to connect to
* port = port to use for connection (0 by default -- use the standard port of the protocol)
*/
void setHost(char[] host, ushort port = 0)
{
sfHttp_SetHost(m_ptr, toStringz(host), port);
}
/**
* Send a HTTP request and return the server's response.
* You must be connected to a host before sending requests.
* Any missing mandatory header field will be added with an appropriate value.
*
* Warning : this function waits for the server's response and may
* not return instantly; use a thread if you don't want to block your
* application.
*
* Params:
* req = Request to send
*
* Returns:
* Server's response
*/
Response sendRequest(Request req)
{
return new Response( sfHttp_SendRequest(m_ptr, req.getNativePointer) );
}
private:
// External ====================================================================
extern (C)
{
typedef void* function() pf_sfHttp_Create;
typedef void function(void*) pf_sfHttp_Destroy;
typedef void function(void*, char*, ushort) pf_sfHttp_SetHost;
typedef void* function(void*, void*) pf_sfHttp_SendRequest;
static pf_sfHttp_Create sfHttp_Create;
static pf_sfHttp_Destroy sfHttp_Destroy;
static pf_sfHttp_SetHost sfHttp_SetHost;
static pf_sfHttp_SendRequest sfHttp_SendRequest;
}
static this()
{
DllLoader dll = DllLoader.load("csfml-network");
sfHttp_Create = cast(pf_sfHttp_Create)dll.getSymbol("sfHttp_Create");
sfHttp_Destroy = cast(pf_sfHttp_Destroy)dll.getSymbol("sfHttp_Destroy");
sfHttp_SetHost = cast(pf_sfHttp_SetHost)dll.getSymbol("sfHttp_SetHost");
sfHttp_SendRequest = cast(pf_sfHttp_SendRequest)dll.getSymbol("sfHttp_SendRequest");
}
}