Barracuda Application Server C/C++ Reference
Native APIs, integration guides, and platform interfaces
HttpUpload

Detailed Description

HttpUpload is a collection of classes that makes it easy to implement a remote file manager.

HttpUpload which is internally using MultipartUpload, HttpAsynchReq, and HttpAsynchResp enables you to easily design code for uploading files using HTTP PUT and multipart POST.

The HttpResMgr in the example directory is a full file manager implementation that is internally using HttpUpload when the client requests a file upload. The following HttpDir C++ example shows how to use HttpUpload:

!#include <HttpUpload.h>
#include <HttpResRdr.h>

/* MyUploadDir is a specialized HttpDir that can upload and download
   any file from a IoIntf implemenation such as a DiskIo.

   We use multiple inheritance for implementing the HttpDir and HttpUpload
   (HttpUploadCbIntf) callback interface.
*/
class MyUploadDir :
   public HttpDir, public HttpUploadCbIntf
{
      HttpUpload upload; //The upload worker class.

      //HttpUploadCbIntf callback
      static void onFile(HttpUploadCbIntf* super,
                         HttpUploadNode* node,
                         BaBool completed);

      //HttpUploadCbIntf callback
      static void onError(HttpUploadCbIntf* super,
                          HttpUploadNode* node,
                          int ecode,
                          const char* extraEcode);

      //HttpDir callback
      static int doService(HttpDir* super,
                           const char* relPath,
                           HttpCommand* cmd);

   public:
      MyUploadDir(const char* dirName, IoIntfPtr io);
};


//Called at start of multipart POST and at end of successful upload.
void
MyUploadDir::onFile(HttpUploadCbIntf* super,
                    HttpUploadNode* node,
                    BaBool completed)
{
   MyUploadDir* o = (MyUploadDir*)super; // Upcast from base
   if(completed) //A PUT or multipart POST completed.
   {
      HttpAsynchResp* resp = node->getResponse();
      //Send a simple text response message to client.
      BufPrint* out = resp->getWriter();
      if(out)  //If socket OK
         out->printf("Upload of %s completed\n", node->getName());
   }
   else //If start of a multipart file. Not used for HTTP PUT.
   {
      // This is where one can authorize the upload.
      // See the HttpResMgr class for how to deny access, if needed.
   }
}


//Called if upload failed.
void 
MyUploadDir::onError(HttpUploadCbIntf* super,
                     HttpUploadNode* node,
                     int ecode,
                     const char* extraEcode)
{
   MyUploadDir* o = (MyUploadDir*)super; /* Upcast from base */
   HttpAsynchResp* resp = node->getResponse();
   //Send a simple text response message to client.
   BufPrint* out = resp->getWriter();  
   if(out)  //If socket OK
      out->printf("Upload of %s failed\n", node->getName());
}


//The overloaded HttpDir service funtion. See HttpDir for more info.
int
MyUploadDir::doService(HttpDir* super,const char* relPath,HttpCommand* cmd)
{
   MyUploadDir* o = (MyUploadDir*)super; // Upcast from base class

   //Check that the HTTP method type is one of GET, POST, PUT, OPTION, or
   // HEAD.
   if(cmd->request.checkMethods(
         &cmd->response, HttpMethod_Get | HttpMethod_Post | HttpMethod_Put))
   {
      // Condition failed or method type is OPTION.
      // Response sent by checkMethods.
      return 0;
   }

   //If a download request.
   if(cmd->request.getMethodType() == HttpMethod_Get)
   {
      IoStat st;
      IoIntfPtr io = o->upload.getIoIntf();
      if( ! io->statFp(io,relPath, &st) && ! st.isDir )
      {  //Send to client if file found and not a directory.
         HttpResRdr::sendFile(io, relPath, &st, cmd);
         return 0; //Signal found
      }
   }
   else //Assume upload request.
   {
      if(o->upload.service(relPath, cmd) < 0)
         cmd->response.sendError(415); //Request not supported.
      return 0; //Signal found .i.e. stop searching.
   }
   return -1; //Let the virtual file system send "not found".
}


//Initiate HttpDir, HttpUploadCbIntf and HttpUpload.
MyUploadDir::MyUploadDir(const char* dirName, IoIntfPtr io) :
   HttpDir(dirName),
   HttpUploadCbIntf(onFile, onError),
   upload(io, 0, this, 5)
{
   setService(service); //Overload and ignore default HttpDir::service
}
Collaboration diagram for HttpUpload:

Classes

struct  HttpUploadNode
 A HttpUploadNode is dynamically created by an HttpUpload instance for each concurrent upload. More...
 
struct  HttpUploadCbIntf
 The HttpUploadCbIntf interface is an abstract class that must be implemented by code using the HttpUpload. More...
 
struct  HttpUpload
 The HttpUpload node is responsible for creating and starting HttpUploadNode instances. More...
 

Macros

#define HttpUploadCbIntf_constructor(o, onFile, onError)
 Install upload callbacks without allocating memory. More...
 
#define HttpUpload_getIoIntf(o)   (o)->io
 

Typedefs

typedef void(* HttpUploadCbIntf_OnFile) (struct HttpUploadCbIntf *o, struct HttpUploadNode *node, BaBool completed)
 Notify the application about a file or completed request. More...
 
typedef void(* HttpUploadCbIntf_OnError) (struct HttpUploadCbIntf *o, struct HttpUploadNode *node, int ecode, const char *extraEcode)
 Report upload failure or parent shutdown. More...
 
typedef struct HttpUploadCbIntf HttpUploadCbIntf
 The HttpUploadCbIntf interface is an abstract class that must be implemented by code using the HttpUpload. More...
 
typedef struct HttpUpload HttpUpload
 The HttpUpload node is responsible for creating and starting HttpUploadNode instances. More...
 

Functions

BA_API const char * HttpUploadNode_getName (struct HttpUploadNode *o)
 
BA_API const char * HttpUploadNode_getUrl (struct HttpUploadNode *o)
 
BA_API HttpAsynchRespHttpUploadNode_getResponse (struct HttpUploadNode *o)
 Switch from receiving the upload to producing its response. More...
 
BA_API struct HttpConnectionHttpUploadNode_getConnection (struct HttpUploadNode *o)
 
BA_API IoIntfPtr HttpUploadNode_getIoIntf (struct HttpUploadNode *o)
 
BA_API void * HttpUploadNode_getdata (struct HttpUploadNode *o)
 
BA_API HttpSessionHttpUploadNode_getSession (struct HttpUploadNode *o)
 
BA_API BaBool HttpUploadNode_isMultipartUpload (struct HttpUploadNode *o)
 
BA_API BaBool HttpUploadNode_isResponseMode (struct HttpUploadNode *o)
 
BA_API BaBool HttpUploadNode_initial (struct HttpUploadNode *o)
 
BA_API int HttpUploadNode_decrRef (struct HttpUploadNode *o)
 Release one retained reference. More...
 
BA_API void HttpUploadNode_incRef (struct HttpUploadNode *o)
 Retain a node beyond the current callback. More...
 
BA_API void set_inflategzip (IoIntf_InflateGzip ptr)
 Install the process-wide gzip upload adapter in builds with zlib support. More...
 
BA_API IoIntf_InflateGzip get_inflategzip (void)
 
BA_API void HttpUpload_constructor (HttpUpload *o, IoIntfPtr io, AllocatorIntf *alloc, HttpUploadCbIntf *uploadCb, int maxUploads)
 Initialize an HttpUpload instance. More...
 
BA_API void HttpUpload_destructor (HttpUpload *o)
 Abort active uploads and release their storage. More...
 
BA_API int HttpUpload_service (HttpUpload *o, const char *name, HttpCommand *cmd, void *userdata)
 Start an upload for a PUT or multipart POST request. More...
 
const char * HttpUploadNode::getName ()
 
const char * HttpUploadNode::getUrl ()
 
HttpAsynchRespHttpUploadNode::getResponse ()
 Switch from receiving the upload to producing its response. More...
 
struct HttpConnectionHttpUploadNode::getConnection ()
 
IoIntfPtr HttpUploadNode::getIoIntf ()
 
HttpSessionHttpUploadNode::getSession ()
 
bool HttpUploadNode::isMultipartUpload ()
 
 HttpUploadCbIntf::HttpUploadCbIntf (HttpUploadCbIntf_OnFile of, HttpUploadCbIntf_OnError oe)
 Initialize a HttpUploadCbIntf interface. More...
 
 HttpUpload::HttpUpload (IoIntfPtr io, AllocatorIntf *alloc, HttpUploadCbIntf *uploadCb, int maxUploads)
 Initialize an HttpUpload instance. More...
 
 HttpUpload::~HttpUpload ()
 Terminate the HttpUpload instance and all active HttpUploadNode instances. More...
 
int HttpUpload::service (const char *name, HttpCommand *cmd, void *userdata=0)
 The HttpUpload service method. More...
 
IoIntfPtr HttpUpload::getIoIntf ()
 

Macro Definition Documentation

◆ HttpUpload_getIoIntf

#define HttpUpload_getIoIntf (   o)    (o)->io
Parameters
[in]oInitialized uploader.
Returns
Borrowed destination I/O interface.

◆ HttpUploadCbIntf_constructor

#define HttpUploadCbIntf_constructor (   o,
  onFile,
  onError 
)
Value:
do { \
(o)->onFileFp=onFile; \
(o)->onErrorFp=onError; \
} while(0)

Install upload callbacks without allocating memory.

Parameters
[out]oCaller-owned callback interface, valid throughout upload use.
[in]onFileRequired file/completion callback.
[in]onErrorRequired failure callback.

Typedef Documentation

◆ HttpUpload

typedef struct HttpUpload HttpUpload

The HttpUpload node is responsible for creating and starting HttpUploadNode instances.

The class can create N concurrent HttpUploadNodes, where N is controlled by the 'maxUploads' attribute.

◆ HttpUploadCbIntf

The HttpUploadCbIntf interface is an abstract class that must be implemented by code using the HttpUpload.

The HttpUploadCbIntf methods are called at start of upload, end of upload, and if the upload failed.

◆ HttpUploadCbIntf_OnError

typedef void(* HttpUploadCbIntf_OnError) (struct HttpUploadCbIntf *o, struct HttpUploadNode *node, int ecode, const char *extraEcode)

Report upload failure or parent shutdown.

Parameters
[in,out]oBorrowed installed callback interface.
[in,out]nodeBorrowed upload node, valid during the callback.
[in]ecodeI/O error code, or FE_SOCKET for receive/parser failures. Parent shutdown reports IOINTF_IOERROR.
[in]extraEcodeBorrowed optional error text, valid during the callback; copy it if retaining it. Do not interpret it as a stable machine-readable code. Send any desired error response using HttpUploadNode_getResponse. The socket may already be unusable. Files can be partially written; cleanup is the application's responsibility. The library does not free userdata.

◆ HttpUploadCbIntf_OnFile

typedef void(* HttpUploadCbIntf_OnFile) (struct HttpUploadCbIntf *o, struct HttpUploadNode *node, BaBool completed)

Notify the application about a file or completed request.

Parameters
[in,out]oBorrowed callback interface installed in HttpUpload.
[in,out]nodeBorrowed upload node, valid during the callback.
[in]completedFALSE before opening each multipart file; TRUE when the complete upload request finishes and its last file closes successfully. PUT has a completion callback but no FALSE start notification. A multipart request can contain several files; TRUE is not a per-file event. Call HttpUploadNode_getResponse to reject a file before opening it or to send the final response. Callbacks can run synchronously during service, or later. Do not destroy the parent HttpUpload from a callback.

Function Documentation

◆ get_inflategzip()

BA_API IoIntf_InflateGzip get_inflategzip ( void  )
Returns
Installed process-wide gzip upload adapter, or NULL. Available in builds with zlib support. No ownership is transferred.

◆ getConnection()

struct HttpConnection * HttpUploadNode::getConnection ( )
Returns
Borrowed receive connection only after reception has reached a state that needs no lingering close and before response mode. Returns NULL while an incomplete upload needs closing or after response mode starts. The pointer is not an ownership transfer.

◆ getIoIntf() [1/2]

IoIntfPtr HttpUploadNode::getIoIntf ( )
Returns
Borrowed destination I/O interface owned by the application.

◆ getIoIntf() [2/2]

IoIntfPtr HttpUpload::getIoIntf ( )
Returns
Borrowed destination I/O interface passed to construction.
Borrowed destination I/O interface owned by the application.

◆ getName()

const char * HttpUploadNode::getName ( )
Returns
Borrowed NUL-terminated path within the I/O interface. PUT returns the destination path; multipart POST returns the current file path, or the destination directory before a file is selected. Copy it before the next file callback or node destruction.

◆ getResponse()

HttpAsynchResp * HttpUploadNode::getResponse ( )

Switch from receiving the upload to producing its response.

Calling before completion aborts reception. Send the desired response from the callback, including on success; obtaining the object alone does not establish that any response was delivered.

Returns
Borrowed embedded response object, never NULL for a valid node. Its connection can be unusable; check the response operation results. Do not destroy or free this object separately from the upload node.

◆ getSession()

HttpSession * HttpUploadNode::getSession ( )
Returns
Borrowed session found by its saved ID, or NULL if no session exists or it has expired.

The session object may expire at any time. See the explanation in the HttpSession for more information.

See also
HttpSession::incrRefCntr

◆ getUrl()

const char * HttpUploadNode::getUrl ( )
Returns
Borrowed URL generated from the request's current directory using HttpResponse::encodeRedirectURL with an empty relative path. It can include session encoding; it is not necessarily the original request URI or a URL identifying the current multipart file. Valid until node destruction.

◆ HttpUpload()

HttpUpload::HttpUpload ( IoIntfPtr  io,
AllocatorIntf alloc,
HttpUploadCbIntf uploadCb,
int  maxUploads 
)

Initialize an HttpUpload instance.

Parameters
ioRequired borrowed writable I/O interface, valid until all uploads are destroyed.
allocRequired borrowed allocator, valid until all uploads are destroyed. Pass AllocatorIntf_getDefault() to use the default.
uploadCbRequired borrowed callback interface with both callbacks installed; must outlive this uploader and every active node.
maxUploadsNonnegative maximum number of concurrent requests, not a byte limit or a limit on files within one multipart request. Zero disables uploads. The HttpUpload::service method sends a 503 HTTP response if the maximum number of concurrent uploads are reached.

◆ HttpUpload_constructor()

BA_API void HttpUpload_constructor ( HttpUpload o,
IoIntfPtr  io,
AllocatorIntf alloc,
HttpUploadCbIntf uploadCb,
int  maxUploads 
)

Initialize an HttpUpload instance.

Parameters
ioRequired borrowed writable I/O interface, valid until all uploads are destroyed.
allocRequired borrowed allocator, valid until all uploads are destroyed. Pass AllocatorIntf_getDefault() to use the default.
uploadCbRequired borrowed callback interface with both callbacks installed; must outlive this uploader and every active node.
maxUploadsNonnegative maximum number of concurrent requests, not a byte limit or a limit on files within one multipart request. Zero disables uploads. The HttpUpload::service method sends a 503 HTTP response if the maximum number of concurrent uploads are reached.
[out]oCaller-owned uploader storage.

◆ HttpUpload_destructor()

BA_API void HttpUpload_destructor ( HttpUpload o)

Abort active uploads and release their storage.

Parameters
[in,out]oInitialized uploader; not in a callback and no external node references outstanding. See HttpUpload::~HttpUpload for callback/lifetime rules.

◆ HttpUpload_service()

BA_API int HttpUpload_service ( HttpUpload o,
const char *  name,
HttpCommand cmd,
void *  userdata 
)

Start an upload for a PUT or multipart POST request.

Parameters
[in,out]oInitialized uploader.
[in]nameRequired copied destination path. For multipart POST, use a directory path ending in a slash when nonempty.
[in,out]cmdBorrowed current command; accepted requests become asynchronous.
[in]userdataBorrowed callback context, or NULL; never freed by the uploader.
Returns
-1 unsupported request, 0 accepted, 1 startup failure. Returns -1 for an unsupported request, 0 when accepted (callbacks may already have run), or 1 when startup failed. On startup failure the caller must release userdata unless a synchronous callback already released it. Existing HTTP error responses are preserved.

◆ HttpUploadCbIntf()

HttpUploadCbIntf::HttpUploadCbIntf ( HttpUploadCbIntf_OnFile  of,
HttpUploadCbIntf_OnError  oe 
)

Initialize a HttpUploadCbIntf interface.

Parameters
ofRequired file/completion callback; see HttpUploadCbIntf_OnFile.
oeRequired failure callback; see HttpUploadCbIntf_OnError.

◆ HttpUploadNode_decrRef()

BA_API int HttpUploadNode_decrRef ( struct HttpUploadNode o)

Release one retained reference.

Parameters
[in,out]oLive node with a nonzero reference count.
Returns
-1 if the count reached zero and the node was destroyed, otherwise 0. Do not access o after -1. Do not decrement an internal callback reference.

◆ HttpUploadNode_getConnection()

BA_API struct HttpConnection * HttpUploadNode_getConnection ( struct HttpUploadNode o)

Returns
Borrowed receive connection only after reception has reached a state that needs no lingering close and before response mode. Returns NULL while an incomplete upload needs closing or after response mode starts. The pointer is not an ownership transfer.
Parameters
[in,out]oLive upload node.

◆ HttpUploadNode_getdata()

BA_API void * HttpUploadNode_getdata ( struct HttpUploadNode o)
Parameters
[in]oLive upload node.
Returns
Borrowed userdata passed to service, possibly NULL.

◆ HttpUploadNode_getIoIntf()

BA_API IoIntfPtr HttpUploadNode_getIoIntf ( struct HttpUploadNode o)

Returns
Borrowed destination I/O interface owned by the application.
Parameters
[in,out]oLive upload node.

◆ HttpUploadNode_getName()

BA_API const char * HttpUploadNode_getName ( struct HttpUploadNode o)

Returns
Borrowed NUL-terminated path within the I/O interface. PUT returns the destination path; multipart POST returns the current file path, or the destination directory before a file is selected. Copy it before the next file callback or node destruction.
Parameters
[in,out]oLive upload node.

◆ HttpUploadNode_getResponse()

BA_API HttpAsynchResp * HttpUploadNode_getResponse ( struct HttpUploadNode o)

Switch from receiving the upload to producing its response.

Calling before completion aborts reception. Send the desired response from the callback, including on success; obtaining the object alone does not establish that any response was delivered.

Returns
Borrowed embedded response object, never NULL for a valid node. Its connection can be unusable; check the response operation results. Do not destroy or free this object separately from the upload node.
Parameters
[in,out]oLive upload node.

◆ HttpUploadNode_getSession()

BA_API HttpSession * HttpUploadNode_getSession ( struct HttpUploadNode o)

Returns
Borrowed session found by its saved ID, or NULL if no session exists or it has expired.

The session object may expire at any time. See the explanation in the HttpSession for more information.

See also
HttpSession::incrRefCntr
Parameters
[in,out]oLive upload node.

◆ HttpUploadNode_getUrl()

BA_API const char * HttpUploadNode_getUrl ( struct HttpUploadNode o)

Returns
Borrowed URL generated from the request's current directory using HttpResponse::encodeRedirectURL with an empty relative path. It can include session encoding; it is not necessarily the original request URI or a URL identifying the current multipart file. Valid until node destruction.
Parameters
[in,out]oLive upload node.

◆ HttpUploadNode_incRef()

BA_API void HttpUploadNode_incRef ( struct HttpUploadNode o)

Retain a node beyond the current callback.

Parameters
[in,out]oLive node; increments its U8 reference counter. Do not exceed 255 total references, including internal callback references. Pair each external increment with decrRef; stop external use before parent destruction. Serialize access with the server. This does not make the node thread-safe.

◆ HttpUploadNode_initial()

BA_API BaBool HttpUploadNode_initial ( struct HttpUploadNode o)
Parameters
[in]oLive upload node.
Returns
Saved HttpResponse_initial state from the command at upload startup.

◆ HttpUploadNode_isMultipartUpload()

BA_API BaBool HttpUploadNode_isMultipartUpload ( struct HttpUploadNode o)

Returns
True for multipart POST, false for PUT.
Parameters
[in,out]oLive upload node.

◆ HttpUploadNode_isResponseMode()

BA_API BaBool HttpUploadNode_isResponseMode ( struct HttpUploadNode o)
Parameters
[in]oLive upload node.
Returns
TRUE after an asynchronous response connection has been installed; FALSE otherwise. This does not test whether sending will succeed.

◆ isMultipartUpload()

bool HttpUploadNode::isMultipartUpload ( )
Returns
True for multipart POST, false for PUT.

◆ service()

int HttpUpload::service ( const char *  name,
HttpCommand cmd,
void *  userdata = 0 
)

The HttpUpload service method.

This method is typically called from a HttpDir or HttpPage service method.

Parameters
nameRequired NUL-terminated destination, copied before return:
  • if PUT: path + name relative to the I/O interface.
  • if POST: directory path relative to the I/O interface, ending in a slash when nonempty. The full path+name is constructed from the name in the multipart message.
cmdBorrowed current command; call from its service handler. An accepted upload takes over asynchronous request processing.
userdataOptional borrowed context (default NULL), retrievable with HttpUploadNode_getdata. Keep it valid until callbacks finish. The uploader does not free it.
Returns
-1 for an unsupported request, 0 when accepted, or 1 on startup failure. See HttpUpload_service for callback-state ownership.

◆ set_inflategzip()

BA_API void set_inflategzip ( IoIntf_InflateGzip  ptr)

Install the process-wide gzip upload adapter in builds with zlib support.

Parameters
[in]ptrCallback used to open gzip-decoding output resources, or NULL to disable that adaptation. Configure before concurrent uploads begin.
See also
IoIntf_InflateGzip

◆ ~HttpUpload()

HttpUpload::~HttpUpload ( )

Terminate the HttpUpload instance and all active HttpUploadNode instances.

Calls the error callback for each active node. Do not call from an upload callback or while external node references remain. The I/O interface, allocator and callback interface are not destroyed; caller-provided userdata is not freed.