/* * 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"); } }