add GetCookie

master
Ondřej Hruška 1 year ago
parent d062bed87d
commit 765b4ac507
  1. 14
      demo/server_demo.c
  2. 2
      spritehttpd/include/httpd-config.h
  3. 25
      spritehttpd/include/httpd.h
  4. 5
      spritehttpd/src/cgi-espfs.c
  5. 86
      spritehttpd/src/httpd.c

@ -75,26 +75,24 @@ httpd_cgi_state templateReplacer(HttpdConnData *conn, const char *token)
return HTTPD_CGI_DONE;
}
//
//int httpdGetCookie(HttpdConnData *conn, const char *name, char *buff, size_t buffLen)
//{
// httpdGetHeader(conn, "Cookie", )
//}
httpd_cgi_state cgiStartSession(HttpdConnData *conn)
{
httpdQueueHeader(conn, "X-Foo", "FOO");
httpdQueueHeader(conn, "X-Bar", "Bar");
char cbuf[100] = {};
httpdGetCookie(conn, "testCookie", cbuf, 100);
printf("Cookie val = %s\n", cbuf);
httpdSetCookie(conn, &(SetCookie) {
.name = "testCookie",
.value = "lala-lele",
// .domain = "localhost",
// .expires = "BABABABAx",
// .httponly = true,
.maxAge = -1,
.maxAge = 0,
// .path = "foo/bar/baz",
// .sameSite = COOKIE_SAMESITE_LAX,
// .secure = true,

@ -58,5 +58,3 @@
#define ESPFS_FILENAME_LEN 100
/// EspFs CGI file chunk buffer size
#define ESPFS_FILE_CHUNK_LEN 512
/// EspFs CGI header buffer (used to detect gzip)
#define ESPFS_HEADER_LEN 64

@ -102,6 +102,18 @@ void httpdEndHeaders(HttpdConnData *conn);
*/
int httpdGetHeader(HttpdConnData *conn, const char *header, char *buff, size_t buffLen);
/**
* Get pointer to a request header's value, if found. This is a way to read headers without
* copying or being limited by the copy buffer length.
*
* The returned string is a view into the headers buffer. The header is 0-terminated.
*
* @param conn
* @param header - name
* @return pointer to the header value, or NULL
*/
const char * httpdGetHeaderPtr(HttpdConnData *conn, const char *header);
/**
* Queue a header to be sent with the response.
*
@ -125,7 +137,7 @@ void httpdQueueHeader(HttpdConnData *conn, const char *header, const char *value
bool httpdQueueHeaderRaw(HttpdConnData *conn, HttpdQueuedHeader *queEntry);
/**
* Set cookie. This queues the cookie header.
* Set cookie. This queues the cookie header - can only be called before headers are sent.
*
* @param conn
* @param parm
@ -133,6 +145,17 @@ bool httpdQueueHeaderRaw(HttpdConnData *conn, HttpdQueuedHeader *queEntry);
*/
bool httpdSetCookie(HttpdConnData *conn, const SetCookie *parm);
/**
* Get cookie value, if present
*
* @param conn
* @param name - cookie name
* @param buff - copy buf
* @param buffLen - buf len
* @return 1 = OK
*/
bool httpdGetCookie(HttpdConnData *conn, const char *name, char *buff, size_t buffLen);
/**
* Send binary data
*

@ -75,7 +75,6 @@ static httpd_cgi_state serveStaticFile(HttpdConnData *hconn, const char *filepat
EspFsFile *file = hconn->cgiData;
size_t len;
uint8_t buff[ESPFS_FILE_CHUNK_LEN + 1];
char acceptEncodingBuffer[ESPFS_HEADER_LEN + 1];
if (hconn->conn == NULL) {
//Connection aborted. Clean up.
@ -112,8 +111,8 @@ static httpd_cgi_state serveStaticFile(HttpdConnData *hconn, const char *filepat
if (isGzip) {
// Check the browser's "Accept-Encoding" header. If the client does not
// advertise that he accepts GZIP send a warning message (telnet users for e.g.)
httpdGetHeader(hconn, "Accept-Encoding", acceptEncodingBuffer, ESPFS_HEADER_LEN);
if (strstr(acceptEncodingBuffer, "gzip") == NULL) {
const char *phdr = httpdGetHeaderPtr(hconn, "Accept-Encoding");
if (phdr && strstr(phdr, "gzip") == NULL) {
//No Accept-Encoding: gzip header present
httpdSendStr(hconn, gzipNonSupportedMessage);
espFsClose(file);

@ -29,8 +29,6 @@ _Static_assert(HTTPD_MAX_CONNECTIONS < 256, "HTTPD_MAX_CONNECTIONS must be at mo
static const HttpdBuiltInUrl *s_builtInUrls;
static const char *s_serverName = HTTPD_SERVERNAME;
//Connection pool
HttpdConnData s_connData[HTTPD_MAX_CONNECTIONS];
@ -140,6 +138,23 @@ static void httpdRetireConn(HttpdConnData *hconn)
//Get the value of a certain header in the HTTP client head
//Returns true when found, false when not found.
int httpdGetHeader(HttpdConnData *conn, const char *header, char *buff, size_t buffLen)
{
const char *p = httpdGetHeaderPtr(conn, header);
if (!p) {
return 0;
}
while (*p != 0 && buffLen > 1) { // && *p != '\r' && *p != '\n'
*buff++ = *p++;
buffLen--;
}
//Zero-terminate string
*buff = 0;
//All done :)
return 1;
}
const char * httpdGetHeaderPtr(HttpdConnData *conn, const char *header)
{
char *p = conn->priv.head;
p = p + strlen(p) + 1; //skip GET/POST part
@ -152,19 +167,11 @@ int httpdGetHeader(HttpdConnData *conn, const char *header, char *buff, size_t b
p = p + strlen(header) + 1;
//Skip past spaces after the colon
while (*p == ' ') { p++; }
//Copy from p to end
while (*p != 0 && *p != '\r' && *p != '\n' && buffLen > 1) {
*buff++ = *p++;
buffLen--;
}
//Zero-terminate string
*buff = 0;
//All done :)
return 1;
return p;
}
p += strlen(p) + 1; //Skip past end of string and \0 terminator
}
return 0;
return NULL;
}
void httpdQueueHeader(HttpdConnData *conn, const char *header, const char *value)
@ -234,24 +241,6 @@ bool httpdSetCookie(HttpdConnData *conn, const SetCookie *parm)
return false;
}
/*
Set-Cookie: <cookie-name>=<cookie-value>
Set-Cookie: <cookie-name>=<cookie-value>; Domain=<domain-value>
Set-Cookie: <cookie-name>=<cookie-value>; Expires=<date>
Set-Cookie: <cookie-name>=<cookie-value>; HttpOnly
Set-Cookie: <cookie-name>=<cookie-value>; Max-Age=<number>
Set-Cookie: <cookie-name>=<cookie-value>; Partitioned
Set-Cookie: <cookie-name>=<cookie-value>; Path=<path-value>
Set-Cookie: <cookie-name>=<cookie-value>; Secure
Set-Cookie: <cookie-name>=<cookie-value>; SameSite=Strict
Set-Cookie: <cookie-name>=<cookie-value>; SameSite=Lax
Set-Cookie: <cookie-name>=<cookie-value>; SameSite=None; Secure
// Multiple attributes are also possible, for example:
Set-Cookie: <cookie-name>=<cookie-value>; Domain=<domain-value>; Secure; HttpOnly
*/
#define COOKIE_PART_SET_COOKIE "Set-Cookie: "
#define COOKIE_PART_EXPIRES "; Expires="
#define COOKIE_PART_MAX_AGE "; Max-Age="
@ -295,7 +284,7 @@ bool httpdSetCookie(HttpdConnData *conn, const SetCookie *parm)
buflen += strlen(COOKIE_PART_HTTP_ONLY);
}
HttpdQueuedHeader *queEntry = httpdMalloc(buflen);
HttpdQueuedHeader *queEntry = httpdMalloc(sizeof(void*) + buflen);
if (!queEntry) {
http_error("httpdSetCookie - no mem");
return false;
@ -344,6 +333,41 @@ bool httpdSetCookie(HttpdConnData *conn, const SetCookie *parm)
}
bool httpdGetCookie(HttpdConnData *conn, const char *name, char *buff, size_t buffLen)
{
const char *p = httpdGetHeaderPtr(conn, "Cookie");
if (!p) return 0;
size_t namelen = strlen(name);
while (*p != 0 && *p != '\r' && *p != '\n') {
if (*p == ' ') { // skip whitespace
p++;
continue;
}
const char *next_semi = strchr(p, ';');
if (!next_semi) {
next_semi = p + strlen(p); // end of string
}
if (strstarts(p, name) && p[namelen] == '=') {
const char * valuestart = p + namelen + 1;
size_t valuelen = (size_t) (next_semi - valuestart);
if (valuelen >= buffLen - 1) {
valuelen = buffLen - 1;
}
strncpy(buff, valuestart, valuelen);
return true;
}
p = next_semi + 1;
}
return false;
}
void httdSetTransferMode(HttpdConnData *conn, httpd_transfer_opt mode)
{
if (mode == HTTPD_TRANSFER_CLOSE) {

Loading…
Cancel
Save