mirror of
https://github.com/pgbackrest/pgbackrest.git
synced 2025-01-06 03:53:59 +02:00
Replace OBJECT_DEFINE_GET() with *Pub struct pattern.
This macro was originally intended to simplify the creation of simple getters but it has been superseded by the pattern introduced in 79a2d02c
.
Remove instances of OBJECT_DEFINE_GET() to avoid confusion with the new pattern.
This commit is contained in:
parent
b715c70b46
commit
cc85c4f03d
@ -24,15 +24,13 @@ Object type
|
|||||||
***********************************************************************************************************************************/
|
***********************************************************************************************************************************/
|
||||||
struct HttpClient
|
struct HttpClient
|
||||||
{
|
{
|
||||||
|
HttpClientPub pub; // Publicly accessible variables
|
||||||
MemContext *memContext; // Mem context
|
MemContext *memContext; // Mem context
|
||||||
TimeMSec timeout; // Request timeout
|
|
||||||
IoClient *ioClient; // Io client (e.g. TLS or socket client)
|
IoClient *ioClient; // Io client (e.g. TLS or socket client)
|
||||||
|
|
||||||
List *sessionReuseList; // List of HTTP sessions that can be reused
|
List *sessionReuseList; // List of HTTP sessions that can be reused
|
||||||
};
|
};
|
||||||
|
|
||||||
OBJECT_DEFINE_GET(Timeout, const, HTTP_CLIENT, TimeMSec, timeout);
|
|
||||||
|
|
||||||
/**********************************************************************************************************************************/
|
/**********************************************************************************************************************************/
|
||||||
HttpClient *
|
HttpClient *
|
||||||
httpClientNew(IoClient *ioClient, TimeMSec timeout)
|
httpClientNew(IoClient *ioClient, TimeMSec timeout)
|
||||||
@ -52,8 +50,11 @@ httpClientNew(IoClient *ioClient, TimeMSec timeout)
|
|||||||
|
|
||||||
*this = (HttpClient)
|
*this = (HttpClient)
|
||||||
{
|
{
|
||||||
.memContext = MEM_CONTEXT_NEW(),
|
.pub =
|
||||||
|
{
|
||||||
.timeout = timeout,
|
.timeout = timeout,
|
||||||
|
},
|
||||||
|
.memContext = MEM_CONTEXT_NEW(),
|
||||||
.ioClient = ioClient,
|
.ioClient = ioClient,
|
||||||
.sessionReuseList = lstNewP(sizeof(HttpSession *)),
|
.sessionReuseList = lstNewP(sizeof(HttpSession *)),
|
||||||
};
|
};
|
||||||
@ -121,5 +122,5 @@ httpClientToLog(const HttpClient *this)
|
|||||||
{
|
{
|
||||||
return strNewFmt(
|
return strNewFmt(
|
||||||
"{ioClient: %s, reusable: %u, timeout: %" PRIu64"}", strZ(ioClientToLog(this->ioClient)), lstSize(this->sessionReuseList),
|
"{ioClient: %s, reusable: %u, timeout: %" PRIu64"}", strZ(ioClientToLog(this->ioClient)), lstSize(this->sessionReuseList),
|
||||||
this->timeout);
|
httpClientTimeout(this));
|
||||||
}
|
}
|
||||||
|
@ -19,9 +19,6 @@ completes and tries to call httpClientReuse() on an HttpClient that has been fre
|
|||||||
/***********************************************************************************************************************************
|
/***********************************************************************************************************************************
|
||||||
Object type
|
Object type
|
||||||
***********************************************************************************************************************************/
|
***********************************************************************************************************************************/
|
||||||
#define HTTP_CLIENT_TYPE HttpClient
|
|
||||||
#define HTTP_CLIENT_PREFIX httpClient
|
|
||||||
|
|
||||||
typedef struct HttpClient HttpClient;
|
typedef struct HttpClient HttpClient;
|
||||||
|
|
||||||
#include "common/io/client.h"
|
#include "common/io/client.h"
|
||||||
@ -47,6 +44,21 @@ Constructors
|
|||||||
***********************************************************************************************************************************/
|
***********************************************************************************************************************************/
|
||||||
HttpClient *httpClientNew(IoClient *ioClient, TimeMSec timeout);
|
HttpClient *httpClientNew(IoClient *ioClient, TimeMSec timeout);
|
||||||
|
|
||||||
|
/***********************************************************************************************************************************
|
||||||
|
Getters/Setters
|
||||||
|
***********************************************************************************************************************************/
|
||||||
|
typedef struct HttpClientPub
|
||||||
|
{
|
||||||
|
TimeMSec timeout; // Request timeout
|
||||||
|
} HttpClientPub;
|
||||||
|
|
||||||
|
__attribute__((always_inline)) static inline TimeMSec
|
||||||
|
httpClientTimeout(const HttpClient *this)
|
||||||
|
{
|
||||||
|
ASSERT_INLINE(this != NULL);
|
||||||
|
return ((const HttpClientPub *)this)->timeout;
|
||||||
|
}
|
||||||
|
|
||||||
/***********************************************************************************************************************************
|
/***********************************************************************************************************************************
|
||||||
Functions
|
Functions
|
||||||
***********************************************************************************************************************************/
|
***********************************************************************************************************************************/
|
||||||
@ -56,11 +68,6 @@ HttpSession *httpClientOpen(HttpClient *this);
|
|||||||
// Request/response finished cleanly so session can be reused
|
// Request/response finished cleanly so session can be reused
|
||||||
void httpClientReuse(HttpClient *this, HttpSession *session);
|
void httpClientReuse(HttpClient *this, HttpSession *session);
|
||||||
|
|
||||||
/***********************************************************************************************************************************
|
|
||||||
Getters/Setters
|
|
||||||
***********************************************************************************************************************************/
|
|
||||||
TimeMSec httpClientTimeout(const HttpClient *this);
|
|
||||||
|
|
||||||
/***********************************************************************************************************************************
|
/***********************************************************************************************************************************
|
||||||
Macros for function logging
|
Macros for function logging
|
||||||
***********************************************************************************************************************************/
|
***********************************************************************************************************************************/
|
||||||
|
@ -44,12 +44,9 @@ Object type
|
|||||||
***********************************************************************************************************************************/
|
***********************************************************************************************************************************/
|
||||||
struct HttpRequest
|
struct HttpRequest
|
||||||
{
|
{
|
||||||
|
HttpRequestPub pub; // Publicly accessible variables
|
||||||
MemContext *memContext; // Mem context
|
MemContext *memContext; // Mem context
|
||||||
HttpClient *client; // HTTP client
|
HttpClient *client; // HTTP client
|
||||||
const String *verb; // HTTP verb (GET, POST, etc.)
|
|
||||||
const String *path; // HTTP path
|
|
||||||
const HttpQuery *query; // HTTP query
|
|
||||||
const HttpHeader *header; // HTTP headers
|
|
||||||
const Buffer *content; // HTTP content
|
const Buffer *content; // HTTP content
|
||||||
|
|
||||||
HttpSession *session; // Session for async requests
|
HttpSession *session; // Session for async requests
|
||||||
@ -58,11 +55,6 @@ struct HttpRequest
|
|||||||
OBJECT_DEFINE_MOVE(HTTP_REQUEST);
|
OBJECT_DEFINE_MOVE(HTTP_REQUEST);
|
||||||
OBJECT_DEFINE_FREE(HTTP_REQUEST);
|
OBJECT_DEFINE_FREE(HTTP_REQUEST);
|
||||||
|
|
||||||
OBJECT_DEFINE_GET(Verb, const, HTTP_REQUEST, const String *, verb);
|
|
||||||
OBJECT_DEFINE_GET(Path, const, HTTP_REQUEST, const String *, path);
|
|
||||||
OBJECT_DEFINE_GET(Query, const, HTTP_REQUEST, const HttpQuery *, query);
|
|
||||||
OBJECT_DEFINE_GET(Header, const, HTTP_REQUEST, const HttpHeader *, header);
|
|
||||||
|
|
||||||
/***********************************************************************************************************************************
|
/***********************************************************************************************************************************
|
||||||
Process the request
|
Process the request
|
||||||
***********************************************************************************************************************************/
|
***********************************************************************************************************************************/
|
||||||
@ -111,17 +103,19 @@ httpRequestProcess(HttpRequest *this, bool waitForResponse, bool contentCache)
|
|||||||
String *requestStr =
|
String *requestStr =
|
||||||
strNewFmt(
|
strNewFmt(
|
||||||
"%s %s%s%s " HTTP_VERSION CRLF_Z HTTP_HEADER_USER_AGENT ":" PROJECT_NAME "/" PROJECT_VERSION CRLF_Z,
|
"%s %s%s%s " HTTP_VERSION CRLF_Z HTTP_HEADER_USER_AGENT ":" PROJECT_NAME "/" PROJECT_VERSION CRLF_Z,
|
||||||
strZ(this->verb), strZ(this->path), this->query == NULL ? "" : "?",
|
strZ(httpRequestVerb(this)), strZ(httpRequestPath(this)), httpRequestQuery(this) == NULL ? "" : "?",
|
||||||
this->query == NULL ? "" : strZ(httpQueryRenderP(this->query)));
|
httpRequestQuery(this) == NULL ? "" : strZ(httpQueryRenderP(httpRequestQuery(this))));
|
||||||
|
|
||||||
// Add headers
|
// Add headers
|
||||||
const StringList *headerList = httpHeaderList(this->header);
|
const StringList *headerList = httpHeaderList(httpRequestHeader(this));
|
||||||
|
|
||||||
for (unsigned int headerIdx = 0; headerIdx < strLstSize(headerList); headerIdx++)
|
for (unsigned int headerIdx = 0; headerIdx < strLstSize(headerList); headerIdx++)
|
||||||
{
|
{
|
||||||
const String *headerKey = strLstGet(headerList, headerIdx);
|
const String *headerKey = strLstGet(headerList, headerIdx);
|
||||||
|
|
||||||
strCatFmt(requestStr, "%s:%s" CRLF_Z, strZ(headerKey), strZ(httpHeaderGet(this->header, headerKey)));
|
strCatFmt(
|
||||||
|
requestStr, "%s:%s" CRLF_Z, strZ(headerKey),
|
||||||
|
strZ(httpHeaderGet(httpRequestHeader(this), headerKey)));
|
||||||
}
|
}
|
||||||
|
|
||||||
// Add blank line to end of headers and write the request as a buffer so secrets do not show up in logs
|
// Add blank line to end of headers and write the request as a buffer so secrets do not show up in logs
|
||||||
@ -143,7 +137,7 @@ httpRequestProcess(HttpRequest *this, bool waitForResponse, bool contentCache)
|
|||||||
// Wait for response
|
// Wait for response
|
||||||
if (waitForResponse)
|
if (waitForResponse)
|
||||||
{
|
{
|
||||||
result = httpResponseNew(session, this->verb, contentCache);
|
result = httpResponseNew(session, httpRequestVerb(this), contentCache);
|
||||||
|
|
||||||
// Retry when response code is 5xx. These errors generally represent a server error for a request that
|
// Retry when response code is 5xx. These errors generally represent a server error for a request that
|
||||||
// looks valid. There are a few errors that might be permanently fatal but they are rare and it seems best
|
// looks valid. There are a few errors that might be permanently fatal but they are rare and it seems best
|
||||||
@ -206,12 +200,15 @@ httpRequestNew(HttpClient *client, const String *verb, const String *path, HttpR
|
|||||||
|
|
||||||
*this = (HttpRequest)
|
*this = (HttpRequest)
|
||||||
{
|
{
|
||||||
.memContext = MEM_CONTEXT_NEW(),
|
.pub =
|
||||||
.client = client,
|
{
|
||||||
.verb = strDup(verb),
|
.verb = strDup(verb),
|
||||||
.path = strDup(path),
|
.path = strDup(path),
|
||||||
.query = httpQueryDupP(param.query),
|
.query = httpQueryDupP(param.query),
|
||||||
.header = param.header == NULL ? httpHeaderNew(NULL) : httpHeaderDup(param.header, NULL),
|
.header = param.header == NULL ? httpHeaderNew(NULL) : httpHeaderDup(param.header, NULL),
|
||||||
|
},
|
||||||
|
.memContext = MEM_CONTEXT_NEW(),
|
||||||
|
.client = client,
|
||||||
.content = param.content == NULL ? NULL : bufDup(param.content),
|
.content = param.content == NULL ? NULL : bufDup(param.content),
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -260,13 +257,13 @@ httpRequestError(const HttpRequest *this, HttpResponse *response)
|
|||||||
// Output path/query
|
// Output path/query
|
||||||
strCatZ(error, ":\n*** Path/Query ***:");
|
strCatZ(error, ":\n*** Path/Query ***:");
|
||||||
|
|
||||||
strCatFmt(error, "\n%s", strZ(this->path));
|
strCatFmt(error, "\n%s", strZ(httpRequestPath(this)));
|
||||||
|
|
||||||
if (this->query != NULL)
|
if (httpRequestQuery(this) != NULL)
|
||||||
strCatFmt(error, "?%s", strZ(httpQueryRenderP(this->query, .redact = true)));
|
strCatFmt(error, "?%s", strZ(httpQueryRenderP(httpRequestQuery(this), .redact = true)));
|
||||||
|
|
||||||
// Output request headers
|
// Output request headers
|
||||||
const StringList *requestHeaderList = httpHeaderList(this->header);
|
const StringList *requestHeaderList = httpHeaderList(httpRequestHeader(this));
|
||||||
|
|
||||||
if (!strLstEmpty(requestHeaderList))
|
if (!strLstEmpty(requestHeaderList))
|
||||||
{
|
{
|
||||||
@ -278,7 +275,7 @@ httpRequestError(const HttpRequest *this, HttpResponse *response)
|
|||||||
|
|
||||||
strCatFmt(
|
strCatFmt(
|
||||||
error, "\n%s: %s", strZ(key),
|
error, "\n%s: %s", strZ(key),
|
||||||
httpHeaderRedact(this->header, key) ? "<redacted>" : strZ(httpHeaderGet(this->header, key)));
|
httpHeaderRedact(httpRequestHeader(this), key) ? "<redacted>" : strZ(httpHeaderGet(httpRequestHeader(this), key)));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -312,7 +309,7 @@ String *
|
|||||||
httpRequestToLog(const HttpRequest *this)
|
httpRequestToLog(const HttpRequest *this)
|
||||||
{
|
{
|
||||||
return strNewFmt(
|
return strNewFmt(
|
||||||
"{verb: %s, path: %s, query: %s, header: %s, contentSize: %zu}", strZ(this->verb), strZ(this->path),
|
"{verb: %s, path: %s, query: %s, header: %s, contentSize: %zu}", strZ(httpRequestVerb(this)), strZ(httpRequestPath(this)),
|
||||||
this->query == NULL ? "null" : strZ(httpQueryToLog(this->query)), strZ(httpHeaderToLog(this->header)),
|
httpRequestQuery(this) == NULL ? "null" : strZ(httpQueryToLog(httpRequestQuery(this))),
|
||||||
this->content == NULL ? 0 : bufUsed(this->content));
|
strZ(httpHeaderToLog(httpRequestHeader(this))), this->content == NULL ? 0 : bufUsed(this->content));
|
||||||
}
|
}
|
||||||
|
@ -77,6 +77,49 @@ typedef struct HttpRequestNewParam
|
|||||||
|
|
||||||
HttpRequest *httpRequestNew(HttpClient *client, const String *verb, const String *path, HttpRequestNewParam param);
|
HttpRequest *httpRequestNew(HttpClient *client, const String *verb, const String *path, HttpRequestNewParam param);
|
||||||
|
|
||||||
|
/***********************************************************************************************************************************
|
||||||
|
Getters/Setters
|
||||||
|
***********************************************************************************************************************************/
|
||||||
|
typedef struct HttpRequestPub
|
||||||
|
{
|
||||||
|
const String *verb; // HTTP verb (GET, POST, etc.)
|
||||||
|
const String *path; // HTTP path
|
||||||
|
const HttpQuery *query; // HTTP query
|
||||||
|
const HttpHeader *header; // HTTP headers
|
||||||
|
} HttpRequestPub;
|
||||||
|
|
||||||
|
// Request path
|
||||||
|
__attribute__((always_inline)) static inline const String *
|
||||||
|
httpRequestPath(const HttpRequest *this)
|
||||||
|
{
|
||||||
|
ASSERT_INLINE(this != NULL);
|
||||||
|
return ((const HttpRequestPub *)this)->path;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Request query
|
||||||
|
__attribute__((always_inline)) static inline const HttpQuery *
|
||||||
|
httpRequestQuery(const HttpRequest *this)
|
||||||
|
{
|
||||||
|
ASSERT_INLINE(this != NULL);
|
||||||
|
return ((const HttpRequestPub *)this)->query;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Request headers
|
||||||
|
__attribute__((always_inline)) static inline const HttpHeader *
|
||||||
|
httpRequestHeader(const HttpRequest *this)
|
||||||
|
{
|
||||||
|
ASSERT_INLINE(this != NULL);
|
||||||
|
return ((const HttpRequestPub *)this)->header;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Request verb
|
||||||
|
__attribute__((always_inline)) static inline const String *
|
||||||
|
httpRequestVerb(const HttpRequest *this)
|
||||||
|
{
|
||||||
|
ASSERT_INLINE(this != NULL);
|
||||||
|
return ((const HttpRequestPub *)this)->verb;
|
||||||
|
}
|
||||||
|
|
||||||
/***********************************************************************************************************************************
|
/***********************************************************************************************************************************
|
||||||
Functions
|
Functions
|
||||||
***********************************************************************************************************************************/
|
***********************************************************************************************************************************/
|
||||||
@ -89,21 +132,6 @@ void httpRequestError(const HttpRequest *this, HttpResponse *response) __attribu
|
|||||||
// Move to a new parent mem context
|
// Move to a new parent mem context
|
||||||
HttpRequest *httpRequestMove(HttpRequest *this, MemContext *parentNew);
|
HttpRequest *httpRequestMove(HttpRequest *this, MemContext *parentNew);
|
||||||
|
|
||||||
/***********************************************************************************************************************************
|
|
||||||
Getters/Setters
|
|
||||||
***********************************************************************************************************************************/
|
|
||||||
// Request verb
|
|
||||||
const String *httpRequestVerb(const HttpRequest *this);
|
|
||||||
|
|
||||||
// Request path
|
|
||||||
const String *httpRequestPath(const HttpRequest *this);
|
|
||||||
|
|
||||||
// Request query
|
|
||||||
const HttpQuery *httpRequestQuery(const HttpRequest *this);
|
|
||||||
|
|
||||||
// Request headers
|
|
||||||
const HttpHeader *httpRequestHeader(const HttpRequest *this);
|
|
||||||
|
|
||||||
/***********************************************************************************************************************************
|
/***********************************************************************************************************************************
|
||||||
Destructor
|
Destructor
|
||||||
***********************************************************************************************************************************/
|
***********************************************************************************************************************************/
|
||||||
|
@ -33,14 +33,10 @@ Object type
|
|||||||
***********************************************************************************************************************************/
|
***********************************************************************************************************************************/
|
||||||
struct HttpResponse
|
struct HttpResponse
|
||||||
{
|
{
|
||||||
|
HttpResponsePub pub; // Publicly accessible variables
|
||||||
MemContext *memContext; // Mem context
|
MemContext *memContext; // Mem context
|
||||||
|
|
||||||
HttpSession *session; // HTTP session
|
HttpSession *session; // HTTP session
|
||||||
IoRead *contentRead; // Read interface for response content
|
|
||||||
|
|
||||||
unsigned int code; // Response code (e.g. 200, 404)
|
|
||||||
String *reason; // Response reason e.g. (OK, Not Found)
|
|
||||||
HttpHeader *header; // Response headers
|
|
||||||
|
|
||||||
bool contentChunked; // Is the response content chunked?
|
bool contentChunked; // Is the response content chunked?
|
||||||
uint64_t contentSize; // Content size (ignored for chunked)
|
uint64_t contentSize; // Content size (ignored for chunked)
|
||||||
@ -54,11 +50,6 @@ struct HttpResponse
|
|||||||
OBJECT_DEFINE_MOVE(HTTP_RESPONSE);
|
OBJECT_DEFINE_MOVE(HTTP_RESPONSE);
|
||||||
OBJECT_DEFINE_FREE(HTTP_RESPONSE);
|
OBJECT_DEFINE_FREE(HTTP_RESPONSE);
|
||||||
|
|
||||||
OBJECT_DEFINE_GET(IoRead, , HTTP_RESPONSE, IoRead *, contentRead);
|
|
||||||
OBJECT_DEFINE_GET(Code, const, HTTP_RESPONSE, unsigned int, code);
|
|
||||||
OBJECT_DEFINE_GET(Header, const, HTTP_RESPONSE, const HttpHeader *, header);
|
|
||||||
OBJECT_DEFINE_GET(Reason, const, HTTP_RESPONSE, const String *, reason);
|
|
||||||
|
|
||||||
/***********************************************************************************************************************************
|
/***********************************************************************************************************************************
|
||||||
When response is done close/reuse the connection
|
When response is done close/reuse the connection
|
||||||
***********************************************************************************************************************************/
|
***********************************************************************************************************************************/
|
||||||
@ -224,9 +215,12 @@ httpResponseNew(HttpSession *session, const String *verb, bool contentCache)
|
|||||||
|
|
||||||
*this = (HttpResponse)
|
*this = (HttpResponse)
|
||||||
{
|
{
|
||||||
|
.pub =
|
||||||
|
{
|
||||||
|
.header = httpHeaderNew(NULL),
|
||||||
|
},
|
||||||
.memContext = MEM_CONTEXT_NEW(),
|
.memContext = MEM_CONTEXT_NEW(),
|
||||||
.session = httpSessionMove(session, memContextCurrent()),
|
.session = httpSessionMove(session, memContextCurrent()),
|
||||||
.header = httpHeaderNew(NULL),
|
|
||||||
};
|
};
|
||||||
|
|
||||||
MEM_CONTEXT_TEMP_BEGIN()
|
MEM_CONTEXT_TEMP_BEGIN()
|
||||||
@ -261,12 +255,12 @@ httpResponseNew(HttpSession *session, const String *verb, bool contentCache)
|
|||||||
if (spacePos != 3)
|
if (spacePos != 3)
|
||||||
THROW_FMT(FormatError, "response status '%s' must have a space after the status code", strZ(status));
|
THROW_FMT(FormatError, "response status '%s' must have a space after the status code", strZ(status));
|
||||||
|
|
||||||
this->code = cvtZToUInt(strZ(strSubN(status, 0, (size_t)spacePos)));
|
this->pub.code = cvtZToUInt(strZ(strSubN(status, 0, (size_t)spacePos)));
|
||||||
|
|
||||||
// Read reason phrase. A missing reason phrase will be represented as an empty string.
|
// Read reason phrase. A missing reason phrase will be represented as an empty string.
|
||||||
MEM_CONTEXT_BEGIN(this->memContext)
|
MEM_CONTEXT_BEGIN(this->memContext)
|
||||||
{
|
{
|
||||||
this->reason = strSub(status, (size_t)spacePos + 1);
|
this->pub.reason = strSub(status, (size_t)spacePos + 1);
|
||||||
}
|
}
|
||||||
MEM_CONTEXT_END();
|
MEM_CONTEXT_END();
|
||||||
|
|
||||||
@ -289,7 +283,7 @@ httpResponseNew(HttpSession *session, const String *verb, bool contentCache)
|
|||||||
String *headerKey = strLower(strTrim(strSubN(header, 0, (size_t)colonPos)));
|
String *headerKey = strLower(strTrim(strSubN(header, 0, (size_t)colonPos)));
|
||||||
String *headerValue = strTrim(strSub(header, (size_t)colonPos + 1));
|
String *headerValue = strTrim(strSub(header, (size_t)colonPos + 1));
|
||||||
|
|
||||||
httpHeaderAdd(this->header, headerKey, headerValue);
|
httpHeaderAdd(this->pub.header, headerKey, headerValue);
|
||||||
|
|
||||||
// Read transfer encoding (only chunked is supported)
|
// Read transfer encoding (only chunked is supported)
|
||||||
if (strEq(headerKey, HTTP_HEADER_TRANSFER_ENCODING_STR))
|
if (strEq(headerKey, HTTP_HEADER_TRANSFER_ENCODING_STR))
|
||||||
@ -336,8 +330,8 @@ httpResponseNew(HttpSession *session, const String *verb, bool contentCache)
|
|||||||
// rather than also checking if the io object exists.
|
// rather than also checking if the io object exists.
|
||||||
MEM_CONTEXT_BEGIN(this->memContext)
|
MEM_CONTEXT_BEGIN(this->memContext)
|
||||||
{
|
{
|
||||||
this->contentRead = ioReadNewP(this, .eof = httpResponseEof, .read = httpResponseRead);
|
this->pub.contentRead = ioReadNewP(this, .eof = httpResponseEof, .read = httpResponseRead);
|
||||||
ioReadOpen(this->contentRead);
|
ioReadOpen(httpResponseIoRead(this));
|
||||||
}
|
}
|
||||||
MEM_CONTEXT_END();
|
MEM_CONTEXT_END();
|
||||||
|
|
||||||
@ -393,19 +387,6 @@ httpResponseContent(HttpResponse *this)
|
|||||||
FUNCTION_TEST_RETURN(this->content);
|
FUNCTION_TEST_RETURN(this->content);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**********************************************************************************************************************************/
|
|
||||||
bool
|
|
||||||
httpResponseCodeOk(const HttpResponse *this)
|
|
||||||
{
|
|
||||||
FUNCTION_TEST_BEGIN();
|
|
||||||
FUNCTION_TEST_PARAM(HTTP_RESPONSE, this);
|
|
||||||
FUNCTION_TEST_END();
|
|
||||||
|
|
||||||
ASSERT(this != NULL);
|
|
||||||
|
|
||||||
FUNCTION_TEST_RETURN(this->code / 100 == 2);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**********************************************************************************************************************************/
|
/**********************************************************************************************************************************/
|
||||||
String *
|
String *
|
||||||
httpResponseToLog(const HttpResponse *this)
|
httpResponseToLog(const HttpResponse *this)
|
||||||
@ -413,7 +394,7 @@ httpResponseToLog(const HttpResponse *this)
|
|||||||
return strNewFmt(
|
return strNewFmt(
|
||||||
"{code: %u, reason: %s, header: %s, contentChunked: %s, contentSize: %" PRIu64 ", contentRemaining: %" PRIu64
|
"{code: %u, reason: %s, header: %s, contentChunked: %s, contentSize: %" PRIu64 ", contentRemaining: %" PRIu64
|
||||||
", closeOnContentEof: %s, contentExists: %s, contentEof: %s, contentCached: %s}",
|
", closeOnContentEof: %s, contentExists: %s, contentEof: %s, contentCached: %s}",
|
||||||
this->code, strZ(this->reason), strZ(httpHeaderToLog(this->header)), cvtBoolToConstZ(this->contentChunked),
|
httpResponseCode(this), strZ(httpResponseReason(this)), strZ(httpHeaderToLog(httpResponseHeader(this))),
|
||||||
this->contentSize, this->contentRemaining, cvtBoolToConstZ(this->closeOnContentEof), cvtBoolToConstZ(this->contentExists),
|
cvtBoolToConstZ(this->contentChunked), this->contentSize, this->contentRemaining, cvtBoolToConstZ(this->closeOnContentEof),
|
||||||
cvtBoolToConstZ(this->contentEof), cvtBoolToConstZ(this->content != NULL));
|
cvtBoolToConstZ(this->contentExists), cvtBoolToConstZ(this->contentEof), cvtBoolToConstZ(this->content != NULL));
|
||||||
}
|
}
|
||||||
|
@ -31,11 +31,59 @@ Constructors
|
|||||||
***********************************************************************************************************************************/
|
***********************************************************************************************************************************/
|
||||||
HttpResponse *httpResponseNew(HttpSession *session, const String *verb, bool contentCache);
|
HttpResponse *httpResponseNew(HttpSession *session, const String *verb, bool contentCache);
|
||||||
|
|
||||||
|
/***********************************************************************************************************************************
|
||||||
|
Getters/Setters
|
||||||
|
***********************************************************************************************************************************/
|
||||||
|
typedef struct HttpResponsePub
|
||||||
|
{
|
||||||
|
IoRead *contentRead; // Read interface for response content
|
||||||
|
unsigned int code; // Response code (e.g. 200, 404)
|
||||||
|
HttpHeader *header; // Response headers
|
||||||
|
String *reason; // Response reason e.g. (OK, Not Found)
|
||||||
|
} HttpResponsePub;
|
||||||
|
|
||||||
|
// Read interface used to get the response content. This is intended for reading content that may be very large and will not be held
|
||||||
|
// in memory all at once. If the content must be loaded completely for processing (e.g. XML) then httpResponseContent() is simpler.
|
||||||
|
__attribute__((always_inline)) static inline IoRead *
|
||||||
|
httpResponseIoRead(HttpResponse *this)
|
||||||
|
{
|
||||||
|
ASSERT_INLINE(this != NULL);
|
||||||
|
return ((const HttpResponsePub *)this)->contentRead;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Response code
|
||||||
|
__attribute__((always_inline)) static inline unsigned int
|
||||||
|
httpResponseCode(const HttpResponse *this)
|
||||||
|
{
|
||||||
|
ASSERT_INLINE(this != NULL);
|
||||||
|
return ((const HttpResponsePub *)this)->code;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Response headers
|
||||||
|
__attribute__((always_inline)) static inline const HttpHeader *
|
||||||
|
httpResponseHeader(const HttpResponse *this)
|
||||||
|
{
|
||||||
|
ASSERT_INLINE(this != NULL);
|
||||||
|
return ((const HttpResponsePub *)this)->header;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Response reason
|
||||||
|
__attribute__((always_inline)) static inline const String *
|
||||||
|
httpResponseReason(const HttpResponse *this)
|
||||||
|
{
|
||||||
|
ASSERT_INLINE(this != NULL);
|
||||||
|
return ((const HttpResponsePub *)this)->reason;
|
||||||
|
}
|
||||||
|
|
||||||
/***********************************************************************************************************************************
|
/***********************************************************************************************************************************
|
||||||
Functions
|
Functions
|
||||||
***********************************************************************************************************************************/
|
***********************************************************************************************************************************/
|
||||||
// Is this response code OK, i.e. 2XX?
|
// Is this response code OK, i.e. 2XX?
|
||||||
bool httpResponseCodeOk(const HttpResponse *this);
|
__attribute__((always_inline)) static inline bool
|
||||||
|
httpResponseCodeOk(const HttpResponse *this)
|
||||||
|
{
|
||||||
|
return httpResponseCode(this) / 100 == 2;
|
||||||
|
}
|
||||||
|
|
||||||
// Fetch all response content. Content will be cached so it can be retrieved again without additional cost.
|
// Fetch all response content. Content will be cached so it can be retrieved again without additional cost.
|
||||||
const Buffer *httpResponseContent(HttpResponse *this);
|
const Buffer *httpResponseContent(HttpResponse *this);
|
||||||
@ -43,25 +91,6 @@ const Buffer *httpResponseContent(HttpResponse *this);
|
|||||||
// Move to a new parent mem context
|
// Move to a new parent mem context
|
||||||
HttpResponse *httpResponseMove(HttpResponse *this, MemContext *parentNew);
|
HttpResponse *httpResponseMove(HttpResponse *this, MemContext *parentNew);
|
||||||
|
|
||||||
/***********************************************************************************************************************************
|
|
||||||
Getters/Setters
|
|
||||||
***********************************************************************************************************************************/
|
|
||||||
// Is the response still being read?
|
|
||||||
bool httpResponseBusy(const HttpResponse *this);
|
|
||||||
|
|
||||||
// Read interface used to get the response content. This is intended for reading content that may be very large and will not be held
|
|
||||||
// in memory all at once. If the content must be loaded completely for processing (e.g. XML) then httpResponseContent() is simpler.
|
|
||||||
IoRead *httpResponseIoRead(HttpResponse *this);
|
|
||||||
|
|
||||||
// Response code
|
|
||||||
unsigned int httpResponseCode(const HttpResponse *this);
|
|
||||||
|
|
||||||
// Response headers
|
|
||||||
const HttpHeader *httpResponseHeader(const HttpResponse *this);
|
|
||||||
|
|
||||||
// Response reason
|
|
||||||
const String *httpResponseReason(const HttpResponse *this);
|
|
||||||
|
|
||||||
/***********************************************************************************************************************************
|
/***********************************************************************************************************************************
|
||||||
Destructor
|
Destructor
|
||||||
***********************************************************************************************************************************/
|
***********************************************************************************************************************************/
|
||||||
|
@ -34,27 +34,6 @@ Create a local "this" variable of the correct type from a THIS_VOID parameter
|
|||||||
***********************************************************************************************************************************/
|
***********************************************************************************************************************************/
|
||||||
#define THIS(type) type *this = thisVoid
|
#define THIS(type) type *this = thisVoid
|
||||||
|
|
||||||
/***********************************************************************************************************************************
|
|
||||||
Define a function used to get an object member variable.
|
|
||||||
|
|
||||||
If the object type/prefix is "Object"/"object" then the macro:
|
|
||||||
|
|
||||||
OBJECT_DEFINE_GET(Size, const, OBJECT, size_t, size);
|
|
||||||
|
|
||||||
will define the function as:
|
|
||||||
|
|
||||||
size_t objectSize(const Object *this)
|
|
||||||
|
|
||||||
No function logging in required because no functions can be called which means no errors can be thrown.
|
|
||||||
***********************************************************************************************************************************/
|
|
||||||
#define OBJECT_DEFINE_GET(name, objectQualifier, objectMacro, returnType, objectMember) \
|
|
||||||
returnType \
|
|
||||||
GLUE(objectMacro##_PREFIX, name)(objectQualifier objectMacro##_TYPE *this) \
|
|
||||||
{ \
|
|
||||||
ASSERT(this != NULL); \
|
|
||||||
return this->objectMember; \
|
|
||||||
}
|
|
||||||
|
|
||||||
/***********************************************************************************************************************************
|
/***********************************************************************************************************************************
|
||||||
Define a function used by the caller to move an object from one context to another
|
Define a function used by the caller to move an object from one context to another
|
||||||
|
|
||||||
|
@ -14,16 +14,14 @@ Object type
|
|||||||
***********************************************************************************************************************************/
|
***********************************************************************************************************************************/
|
||||||
struct Wait
|
struct Wait
|
||||||
{
|
{
|
||||||
|
WaitPub pub; // Publicly accessible variables
|
||||||
MemContext *memContext; // Context that contains the wait handler
|
MemContext *memContext; // Context that contains the wait handler
|
||||||
TimeMSec waitTime; // Total time to wait (in usec)
|
TimeMSec waitTime; // Total time to wait (in usec)
|
||||||
TimeMSec remainTime; // Wait time remaining (in usec)
|
|
||||||
TimeMSec sleepTime; // Next sleep time (in usec)
|
TimeMSec sleepTime; // Next sleep time (in usec)
|
||||||
TimeMSec sleepPrevTime; // Previous time slept (in usec)
|
TimeMSec sleepPrevTime; // Previous time slept (in usec)
|
||||||
TimeMSec beginTime; // Time the wait began (in epoch usec)
|
TimeMSec beginTime; // Time the wait began (in epoch usec)
|
||||||
};
|
};
|
||||||
|
|
||||||
OBJECT_DEFINE_GET(Remaining, const, WAIT, TimeMSec, remainTime);
|
|
||||||
|
|
||||||
OBJECT_DEFINE_FREE(WAIT);
|
OBJECT_DEFINE_FREE(WAIT);
|
||||||
|
|
||||||
/**********************************************************************************************************************************/
|
/**********************************************************************************************************************************/
|
||||||
@ -46,9 +44,12 @@ waitNew(TimeMSec waitTime)
|
|||||||
|
|
||||||
*this = (Wait)
|
*this = (Wait)
|
||||||
{
|
{
|
||||||
|
.pub =
|
||||||
|
{
|
||||||
|
.remainTime = waitTime,
|
||||||
|
},
|
||||||
.memContext = MEM_CONTEXT_NEW(),
|
.memContext = MEM_CONTEXT_NEW(),
|
||||||
.waitTime = waitTime,
|
.waitTime = waitTime,
|
||||||
.remainTime = waitTime,
|
|
||||||
};
|
};
|
||||||
|
|
||||||
// Calculate first sleep time -- start with 1/10th of a second for anything >= 1 second
|
// Calculate first sleep time -- start with 1/10th of a second for anything >= 1 second
|
||||||
@ -100,7 +101,7 @@ waitMore(Wait *this)
|
|||||||
// Store new sleep times
|
// Store new sleep times
|
||||||
this->sleepPrevTime = this->sleepTime;
|
this->sleepPrevTime = this->sleepTime;
|
||||||
this->sleepTime = sleepNextTime;
|
this->sleepTime = sleepNextTime;
|
||||||
this->remainTime = this->waitTime - elapsedTime;
|
this->pub.remainTime = this->waitTime - elapsedTime;
|
||||||
}
|
}
|
||||||
// Else set sleep to zero so next call will return false
|
// Else set sleep to zero so next call will return false
|
||||||
else
|
else
|
||||||
|
@ -19,18 +19,28 @@ Constructors
|
|||||||
***********************************************************************************************************************************/
|
***********************************************************************************************************************************/
|
||||||
Wait *waitNew(TimeMSec waitTime);
|
Wait *waitNew(TimeMSec waitTime);
|
||||||
|
|
||||||
|
/***********************************************************************************************************************************
|
||||||
|
Getters/Setters
|
||||||
|
***********************************************************************************************************************************/
|
||||||
|
typedef struct WaitPub
|
||||||
|
{
|
||||||
|
TimeMSec remainTime; // Wait time remaining (in usec)
|
||||||
|
} WaitPub;
|
||||||
|
|
||||||
|
// How much time is remaining? Recalculated each time waitMore() is called.
|
||||||
|
__attribute__((always_inline)) static inline TimeMSec
|
||||||
|
waitRemaining(const Wait *this)
|
||||||
|
{
|
||||||
|
ASSERT_INLINE(this != NULL);
|
||||||
|
return ((const WaitPub *)this)->remainTime;
|
||||||
|
}
|
||||||
|
|
||||||
/***********************************************************************************************************************************
|
/***********************************************************************************************************************************
|
||||||
Functions
|
Functions
|
||||||
***********************************************************************************************************************************/
|
***********************************************************************************************************************************/
|
||||||
// Wait and return whether the caller has more time left
|
// Wait and return whether the caller has more time left
|
||||||
bool waitMore(Wait *this);
|
bool waitMore(Wait *this);
|
||||||
|
|
||||||
/***********************************************************************************************************************************
|
|
||||||
Getters/Setters
|
|
||||||
***********************************************************************************************************************************/
|
|
||||||
// How much time is remaining? Recalculated each time waitMore() is called.
|
|
||||||
TimeMSec waitRemaining(const Wait *this);
|
|
||||||
|
|
||||||
/***********************************************************************************************************************************
|
/***********************************************************************************************************************************
|
||||||
Destructor
|
Destructor
|
||||||
***********************************************************************************************************************************/
|
***********************************************************************************************************************************/
|
||||||
|
@ -306,7 +306,7 @@ testRun(void)
|
|||||||
// -----------------------------------------------------------------------------------------------------------------
|
// -----------------------------------------------------------------------------------------------------------------
|
||||||
TEST_TITLE("no output from server");
|
TEST_TITLE("no output from server");
|
||||||
|
|
||||||
client->timeout = 0;
|
client->pub.timeout = 0;
|
||||||
|
|
||||||
hrnServerScriptAccept(http);
|
hrnServerScriptAccept(http);
|
||||||
|
|
||||||
@ -469,7 +469,7 @@ testRun(void)
|
|||||||
httpQueryAdd(query, strNew("name"), strNew("/path/A Z.txt"));
|
httpQueryAdd(query, strNew("name"), strNew("/path/A Z.txt"));
|
||||||
httpQueryAdd(query, strNew("type"), strNew("test"));
|
httpQueryAdd(query, strNew("type"), strNew("test"));
|
||||||
|
|
||||||
client->timeout = 5000;
|
client->pub.timeout = 5000;
|
||||||
|
|
||||||
HttpRequest *request = NULL;
|
HttpRequest *request = NULL;
|
||||||
HttpResponse *response = NULL;
|
HttpResponse *response = NULL;
|
||||||
|
Loading…
Reference in New Issue
Block a user