PsychichHTTP v2-dev
This commit is contained in:
@@ -2,52 +2,49 @@
|
||||
#include "PsychicRequest.h"
|
||||
#include <http_status.h>
|
||||
|
||||
PsychicResponse::PsychicResponse(PsychicRequest *request) :
|
||||
_request(request),
|
||||
_code(200),
|
||||
_status(""),
|
||||
_contentLength(0),
|
||||
_body("")
|
||||
PsychicResponse::PsychicResponse(PsychicRequest* request) : _request(request),
|
||||
_code(200),
|
||||
_status(""),
|
||||
_contentType(emptyString),
|
||||
_contentLength(0),
|
||||
_body("")
|
||||
{
|
||||
// get our global headers out of the way
|
||||
for (auto& header : DefaultHeaders::Instance().getHeaders())
|
||||
addHeader(header.field.c_str(), header.value.c_str());
|
||||
}
|
||||
|
||||
PsychicResponse::~PsychicResponse()
|
||||
{
|
||||
//clean up our header variables. we have to do this on desctruct since httpd_resp_send doesn't store copies
|
||||
for (HTTPHeader header : _headers)
|
||||
{
|
||||
free(header.field);
|
||||
free(header.value);
|
||||
}
|
||||
_headers.clear();
|
||||
}
|
||||
|
||||
void PsychicResponse::addHeader(const char *field, const char *value)
|
||||
void PsychicResponse::addHeader(const char* field, const char* value)
|
||||
{
|
||||
//these get freed after send by the destructor
|
||||
HTTPHeader header;
|
||||
header.field =(char *)malloc(strlen(field)+1);
|
||||
header.value = (char *)malloc(strlen(value)+1);
|
||||
// erase any existing ones.
|
||||
for (auto itr = _headers.begin(); itr != _headers.end();) {
|
||||
if (itr->field.equalsIgnoreCase(field))
|
||||
itr = _headers.erase(itr);
|
||||
else
|
||||
itr++;
|
||||
}
|
||||
|
||||
strlcpy(header.field, field, strlen(field)+1);
|
||||
strlcpy(header.value, value, strlen(value)+1);
|
||||
|
||||
_headers.push_back(header);
|
||||
// now add it.
|
||||
_headers.push_back({field, value});
|
||||
}
|
||||
|
||||
void PsychicResponse::setCookie(const char *name, const char *value, unsigned long secondsFromNow, const char *extras)
|
||||
void PsychicResponse::setCookie(const char* name, const char* value, unsigned long secondsFromNow, const char* extras)
|
||||
{
|
||||
time_t now = time(nullptr);
|
||||
|
||||
String output;
|
||||
output = urlEncode(name) + "=" + urlEncode(value);
|
||||
|
||||
//if current time isn't modern, default to using max age
|
||||
// if current time isn't modern, default to using max age
|
||||
if (now < 1700000000)
|
||||
output += "; Max-Age=" + String(secondsFromNow);
|
||||
//otherwise, set an expiration date
|
||||
else
|
||||
{
|
||||
output += "; Max-Age=" + String(secondsFromNow);
|
||||
// otherwise, set an expiration date
|
||||
else {
|
||||
time_t expirationTimestamp = now + secondsFromNow;
|
||||
|
||||
// Convert the expiration timestamp to a formatted string for the "expires" attribute
|
||||
@@ -57,11 +54,11 @@ void PsychicResponse::setCookie(const char *name, const char *value, unsigned lo
|
||||
output += "; Expires=" + String(expires);
|
||||
}
|
||||
|
||||
//did we get any extras?
|
||||
// did we get any extras?
|
||||
if (strlen(extras))
|
||||
output += "; " + String(extras);
|
||||
|
||||
//okay, add it in.
|
||||
// okay, add it in.
|
||||
addHeader("Set-Cookie", output.c_str());
|
||||
}
|
||||
|
||||
@@ -70,24 +67,24 @@ void PsychicResponse::setCode(int code)
|
||||
_code = code;
|
||||
}
|
||||
|
||||
void PsychicResponse::setContentType(const char *contentType)
|
||||
void PsychicResponse::setContentType(const char* contentType)
|
||||
{
|
||||
httpd_resp_set_type(_request->request(), contentType);
|
||||
_contentType = contentType;
|
||||
}
|
||||
|
||||
void PsychicResponse::setContent(const char *content)
|
||||
void PsychicResponse::setContent(const char* content)
|
||||
{
|
||||
_body = content;
|
||||
setContentLength(strlen(content));
|
||||
}
|
||||
|
||||
void PsychicResponse::setContent(const uint8_t *content, size_t len)
|
||||
void PsychicResponse::setContent(const uint8_t* content, size_t len)
|
||||
{
|
||||
_body = (char *)content;
|
||||
_body = (char*)content;
|
||||
setContentLength(len);
|
||||
}
|
||||
|
||||
const char * PsychicResponse::getContent()
|
||||
const char* PsychicResponse::getContent()
|
||||
{
|
||||
return _body;
|
||||
}
|
||||
@@ -99,17 +96,20 @@ size_t PsychicResponse::getContentLength()
|
||||
|
||||
esp_err_t PsychicResponse::send()
|
||||
{
|
||||
//esp-idf makes you set the whole status.
|
||||
// esp-idf makes you set the whole status.
|
||||
sprintf(_status, "%u %s", _code, http_status_reason(_code));
|
||||
httpd_resp_set_status(_request->request(), _status);
|
||||
|
||||
//our headers too
|
||||
// set the content type
|
||||
httpd_resp_set_type(_request->request(), _contentType.c_str());
|
||||
|
||||
// our headers too
|
||||
this->sendHeaders();
|
||||
|
||||
//now send it off
|
||||
// now send it off
|
||||
esp_err_t err = httpd_resp_send(_request->request(), getContent(), getContentLength());
|
||||
|
||||
//did something happen?
|
||||
// did something happen?
|
||||
if (err != ESP_OK)
|
||||
ESP_LOGE(PH_TAG, "Send response failed (%s)", esp_err_to_name(err));
|
||||
|
||||
@@ -118,38 +118,21 @@ esp_err_t PsychicResponse::send()
|
||||
|
||||
void PsychicResponse::sendHeaders()
|
||||
{
|
||||
//get our global headers out of the way first
|
||||
for (HTTPHeader header : DefaultHeaders::Instance().getHeaders())
|
||||
httpd_resp_set_hdr(_request->request(), header.field, header.value);
|
||||
|
||||
//now do our individual headers
|
||||
for (HTTPHeader header : _headers)
|
||||
httpd_resp_set_hdr(this->_request->request(), header.field, header.value);
|
||||
|
||||
// DO NOT RELEASE HEADERS HERE... released in the PsychicResponse destructor after they have been sent.
|
||||
// httpd_resp_set_hdr just passes on the pointer, but its needed after this call.
|
||||
// clean up our header variables after send
|
||||
// for (HTTPHeader header : _headers)
|
||||
// {
|
||||
// free(header.field);
|
||||
// free(header.value);
|
||||
// }
|
||||
// _headers.clear();
|
||||
// now do our individual headers
|
||||
for (auto& header : _headers)
|
||||
httpd_resp_set_hdr(this->_request->request(), header.field.c_str(), header.value.c_str());
|
||||
}
|
||||
|
||||
esp_err_t PsychicResponse::sendChunk(uint8_t *chunk, size_t chunksize)
|
||||
esp_err_t PsychicResponse::sendChunk(uint8_t* chunk, size_t chunksize)
|
||||
{
|
||||
/* Send the buffer contents as HTTP response chunk */
|
||||
esp_err_t err = httpd_resp_send_chunk(this->_request->request(), (char *)chunk, chunksize);
|
||||
if (err != ESP_OK)
|
||||
{
|
||||
ESP_LOGD(PH_TAG, "Sending chunk: %d", chunksize);
|
||||
esp_err_t err = httpd_resp_send_chunk(request(), (char*)chunk, chunksize);
|
||||
if (err != ESP_OK) {
|
||||
ESP_LOGE(PH_TAG, "File sending failed (%s)", esp_err_to_name(err));
|
||||
|
||||
/* Abort sending file */
|
||||
httpd_resp_sendstr_chunk(this->_request->request(), NULL);
|
||||
|
||||
/* Respond with 500 Internal Server Error */
|
||||
httpd_resp_send_err(this->_request->request(), HTTPD_500_INTERNAL_SERVER_ERROR, "Failed to send file");
|
||||
}
|
||||
|
||||
return err;
|
||||
@@ -159,4 +142,63 @@ esp_err_t PsychicResponse::finishChunking()
|
||||
{
|
||||
/* Respond with an empty chunk to signal HTTP response completion */
|
||||
return httpd_resp_send_chunk(this->_request->request(), NULL, 0);
|
||||
}
|
||||
}
|
||||
|
||||
esp_err_t PsychicResponse::redirect(const char* url)
|
||||
{
|
||||
if (!_code)
|
||||
setCode(301);
|
||||
addHeader("Location", url);
|
||||
return send();
|
||||
}
|
||||
|
||||
esp_err_t PsychicResponse::send(int code)
|
||||
{
|
||||
setCode(code);
|
||||
return send();
|
||||
}
|
||||
|
||||
esp_err_t PsychicResponse::send(const char* content)
|
||||
{
|
||||
if (!_code)
|
||||
setCode(200);
|
||||
if (_contentType.isEmpty())
|
||||
setContentType("text/html");
|
||||
setContent(content);
|
||||
return send();
|
||||
}
|
||||
|
||||
esp_err_t PsychicResponse::send(const char* contentType, const char* content)
|
||||
{
|
||||
if (!_code)
|
||||
setCode(200);
|
||||
setContentType(contentType);
|
||||
setContent(content);
|
||||
return send();
|
||||
}
|
||||
|
||||
esp_err_t PsychicResponse::send(int code, const char* contentType, const char* content)
|
||||
{
|
||||
setCode(code);
|
||||
setContentType(contentType);
|
||||
setContent(content);
|
||||
return send();
|
||||
}
|
||||
|
||||
esp_err_t PsychicResponse::send(int code, const char* contentType, const uint8_t* content, size_t len)
|
||||
{
|
||||
setCode(code);
|
||||
setContentType(contentType);
|
||||
setContent(content, len);
|
||||
return send();
|
||||
}
|
||||
|
||||
esp_err_t PsychicResponse::error(httpd_err_code_t code, const char* message)
|
||||
{
|
||||
return httpd_resp_send_err(_request->_req, code, message);
|
||||
}
|
||||
|
||||
httpd_req_t* PsychicResponse::request()
|
||||
{
|
||||
return _request->_req;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user