#pragma once #include #include #include #include #include /* needed for ssize_t */ #include "httpd-platform.h" #include "httpd-types.h" #include "httpd-routes.h" #ifndef GIT_HASH #define GIT_HASH "unknown" #endif // we must not use this macro outside the library, as the git hash is not defined there #define HTTPDVER "0.4+MightyPork/libesphttpd#" GIT_HASH // default servername #ifndef HTTPD_SERVERNAME #define HTTPD_SERVERNAME "SpriteHTTPD " HTTPDVER #endif //Max length of request head. This is statically allocated for each connection. #ifndef HTTPD_MAX_HEAD_LEN #define HTTPD_MAX_HEAD_LEN 1024 #endif //Max post buffer len. This is dynamically malloc'ed if needed. #ifndef HTTPD_MAX_POST_LEN #define HTTPD_MAX_POST_LEN 2048 #endif //Max send buffer len. This is allocated on the stack. #ifndef HTTPD_MAX_SENDBUFF_LEN #define HTTPD_MAX_SENDBUFF_LEN 2048 #endif //Receive buffer #ifndef HTTPD_RECV_BUF_LEN #define HTTPD_RECV_BUF_LEN 2048 #endif //If some data can't be sent because the underlaying socket doesn't accept the data (like the nonos //layer is prone to do), we put it in a backlog that is dynamically malloc'ed. This defines the max //size of the backlog. #ifndef HTTPD_MAX_BACKLOG_SIZE #define HTTPD_MAX_BACKLOG_SIZE (4*1024) #endif //Max len of CORS token. This is allocated in each connection #ifndef HTTPD_MAX_CORS_TOKEN_LEN #define HTTPD_MAX_CORS_TOKEN_LEN 256 #endif #ifndef HTTPD_MAX_CONNECTIONS #define HTTPD_MAX_CONNECTIONS 4 #endif /** * Get the server version string * * @return version */ const char *httpdGetVersion(void); /** * Use this as a cgi function to redirect one url to another. */ httpd_cgi_state cgiRedirect(HttpdConnData *connData); /** * This CGI function redirects to a fixed url of http://[hostname]/ if hostname field of request isn't * already that hostname. Use this in combination with a DNS server that redirects everything to the * ESP in order to load a HTML page as soon as a phone, tablet etc connects to the ESP. Watch out: * this will also redirect connections when the ESP is in STA mode, potentially to a hostname that is not * in the 'official' DNS and so will fail. * * @param conn - connection */ httpd_cgi_state cgiRedirectToHostname(HttpdConnData *connData); /** * Redirect to the given URL. * * Sets the status code to 302, adds the Location header and a simple redirect text body. * * @param conn - connection * @param newUrl - URL to redirect to */ void httpdRedirect(HttpdConnData *conn, const char *newUrl); /** * Start the HTTP server * * @param fixedUrls - array of defined URLs * @param options - server options * @return server thread handle or NULL on error */ httpd_thread_handle_t *httpdStart(const HttpdBuiltInUrl *fixedUrls, struct httpd_options *options); /** * Shutdown the server & wait for the thread to end. * * @param handle */ void httpdShutdown(httpd_thread_handle_t *handle); /** * Join the server thread. * This is mainly useful in the posix build to block while the server runs. * * @param handle */ void httpdJoin(httpd_thread_handle_t *handle); /** * Set transfer mode for the current connection * * @param conn * @param mode - transfer mode */ void httdSetTransferMode(HttpdConnData *conn, httpd_transfer_opt mode); /** * Start a HTTP response. Sends the HTTP line and common headers. * More headers can be added before starting the message body. * * @param conn * @param code - HTTP status code */ void httpdStartResponse(HttpdConnData *conn, int code); /** * Add a HTTP header * * @param conn * @param field - name * @param val - value */ void httpdHeader(HttpdConnData *conn, const char *field, const char *val); /** * End headers, start sending body * * @param conn */ void httpdEndHeaders(HttpdConnData *conn); /** * Read value of a request header * * @param conn * @param header - name * @param[out] buff - buffer for the header value, will be zero terminated * @param buffLen - capacity of the buffer * @return 1 = OK */ int httpdGetHeader(HttpdConnData *conn, const char *header, char *buff, size_t buffLen); /** * Send binary data * * @param conn * @param data - data to send * @param len - num bytes. -1 to use strlen. * @return 1 = OK */ int httpdSend(HttpdConnData *conn, const uint8_t *data, size_t len); /** * Send a string. The length is measured using strlen. * * @param conn * @param data - string * @return 1 = OK */ static inline int httpdSendStr(HttpdConnData *conn, const char *data) { return httpdSend(conn, (const uint8_t *) data, strlen(data)); } /** * Send a string with custom length. This is a slight optimization over httpdSendStr when the length is known. * * @param conn * @param data - string * @param len - num bytes * @return 1 = OK */ static inline int httpdSendStrN(HttpdConnData *conn, const char *data, size_t len) { return httpdSend(conn, (const uint8_t *) data, len); } // TODO convert to a general escaped send function /** * Send text with JSON escaping * * @param conn * @param data - string * @param len - string length, -1 to use strlen() * @return 1 = OK */ int httpdSend_js(HttpdConnData *conn, const char *data, ssize_t len); /** * Send text with HTML escaping. Escapes quotes and angle brackets. * * @param conn * @param data - string * @param len - string length, -1 to use strlen() * @return 1 = OK */ int httpdSend_html(HttpdConnData *conn, const char *data, ssize_t len); /** * Function to send any data in conn->priv->sendBuff. Do not use in CGIs unless you know what you * are doing! Also, if you do set conn->cgi to NULL to indicate the connection is closed, do it BEFORE * calling this. * Returns false if data could not be sent nor put in backlog. * * @param conn * @return 1 = OK */ bool httpdFlushSendBuffer(HttpdConnData *conn); /** * Can be called after a CGI function has returned HTTPD_CGI_MORE to * resume handling an open connection asynchronously * * @param conn */ void httpdContinue(HttpdConnData *conn); /** * Make a connection 'live' so we can do all the things a cgi can do to it. * * @param conn */ void httpdConnSendStart(HttpdConnData *conn); /** * Finish the live-ness of a connection. Always call this after httpdConnStart * * @param conn */ void httpdConnSendFinish(HttpdConnData *conn); /** * Add sensible cache control headers to avoid needless asset reloading. * * @param connData * @param mime - mime type string */ void httpdAddCacheHeaders(HttpdConnData *connData, const char *mime); /** * Get current HTTP backlog size * * @param connData * @return bytes */ size_t httpGetBacklogSize(const HttpdConnData *connData); /** * Set HTTP response options * * @param conn * @param cors 0 = don't add CORS header */ void httdResponseOptions(HttpdConnData *conn, int cors); //Platform dependent code should call these. /** * Callback called when the data on a socket has been successfully sent. * * @param conn * @param remIp - remote IP (4 bytes) * @param remPort - remote port */ void httpdSentCb(ConnTypePtr conn, const char *remIp, int remPort); /** * Callback called when there's data available on a socket. * * @param conn * @param remIp - remote IP (4 bytes) * @param remPort - remote port * @param data - data received. This is a mutable buffer * @param len - data len */ void httpdRecvCb(ConnTypePtr conn, const char *remIp, int remPort, uint8_t *data, unsigned short len); /** * The platform layer should ALWAYS call this function, regardless if the connection is closed by the server * or by the client. * * @param conn * @param remIp - remote IP (4 bytes) * @param remPort - remote port */ void httpdDisconCb(ConnTypePtr conn, const char *remIp, int remPort); /** * Connect callback - a client connected * * @param conn * @param remIp - remote IP (4 bytes) * @param remPort - remote port * @return 1 = OK, 0 = client couldn't be served */ int httpdConnectCb(ConnTypePtr conn, const char *remIp, int remPort); /** * Set server name (Should not be on stack - the pointer must live as long as the server! Const is preferable.) * * @param name - new server name */ void httpdSetName(const char *name); /** * Low level function to close & release a connection * * @param conn */ void httpdConnRelease(ConnTypePtr conn); /** * Close and retire all sockets. * Called during httpd shutdown. */ void httpdInternalCloseAllSockets();