mirror of
https://github.com/Relintai/pandemonium_engine.git
synced 2024-12-23 04:16:50 +01:00
Added httpio ( https://github.com/fetisov/httpio ).
This commit is contained in:
parent
617d3e6321
commit
be5f77c874
3
modules/web/http_server_simple/httpio.md
Normal file
3
modules/web/http_server_simple/httpio.md
Normal file
@ -0,0 +1,3 @@
|
||||
https://github.com/fetisov/httpio
|
||||
|
||||
8c56b550316e064842360eeddf2abb626df9123f
|
1
modules/web/http_server_simple/httpio/.gitignore
vendored
Normal file
1
modules/web/http_server_simple/httpio/.gitignore
vendored
Normal file
@ -0,0 +1 @@
|
||||
/tests/*
|
21
modules/web/http_server_simple/httpio/LICENSE
Normal file
21
modules/web/http_server_simple/httpio/LICENSE
Normal file
@ -0,0 +1,21 @@
|
||||
MIT License
|
||||
|
||||
Copyright (c) 2016 Fetisov Sergey
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
120
modules/web/http_server_simple/httpio/README.md
Normal file
120
modules/web/http_server_simple/httpio/README.md
Normal file
@ -0,0 +1,120 @@
|
||||
# httpio
|
||||
Cross Platform parser and response generator for the HTTP protocol.
|
||||
|
||||
Library has the simple API to embed to the custom systems.
|
||||
|
||||
Parser functions:
|
||||
- Parses the HTTP stream on the fly
|
||||
- Does not use the dynamic allocation (uses predefined connection buffer as the simple pool)
|
||||
- Not used space of the connection buffer can be used as the network receiving buffer
|
||||
- Supports the keep-alive multiple requests and various types of POST request
|
||||
|
||||
Generator functions:
|
||||
- As well as the parser it does not use the dynamic allocation
|
||||
- Organized by a ring buffer
|
||||
- Supports the chunked transfer encoding
|
||||
|
||||
# Parser example (stdin instead the socket)
|
||||
```c
|
||||
#include <stdio.h>
|
||||
#include "httpio.h"
|
||||
|
||||
static char in_pool[1024];
|
||||
|
||||
int main(int argc, const char **argv)
|
||||
{
|
||||
FILE *f;
|
||||
httpi_t *in;
|
||||
f = argc == 2 ? fopen(argv[1], "rb") : stdin;
|
||||
in = httpi_init(in_pool, 1024);
|
||||
while (1)
|
||||
{
|
||||
int size;
|
||||
char *data;
|
||||
int status = httpi_pull(in);
|
||||
switch (status)
|
||||
{
|
||||
case HTTP_IN_NODATA:
|
||||
/* data input */
|
||||
httpi_get_state(in, &data, &size);
|
||||
size = fread(data, 1, size, f);
|
||||
httpi_push(in, data, size);
|
||||
if (size == 0) return 0;
|
||||
continue;
|
||||
case HTTP_IN_REQUEST:
|
||||
printf("page %s requested\n", httpi_request(in)->uri);
|
||||
continue;
|
||||
case HTTP_IN_POSTDATA:
|
||||
printf("new chunk of POST data \"%s\"\n", httpi_posted(in)->name);
|
||||
continue;
|
||||
case HTTP_IN_FINISHED:
|
||||
printf("request finished\n");
|
||||
continue;
|
||||
default:
|
||||
printf("invalid request!\n");
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
Example input:
|
||||
```http
|
||||
POST /cgi-bin/login.cgi HTTP/1.1
|
||||
Host: www.tutorialspoint.com
|
||||
Content-Type: application/x-www-form-urlencoded
|
||||
Content-Length: 35
|
||||
Accept-Language: en-us
|
||||
Accept-Encoding: gzip, deflate
|
||||
Connection: Keep-Alive
|
||||
|
||||
login=Petya%20Vasechkin&password=qq
|
||||
```
|
||||
Example output:
|
||||
```
|
||||
page /cgi-bin/login.cgi requested
|
||||
new chunk of POST data "login"
|
||||
new chunk of POST data "password"
|
||||
request finished
|
||||
```
|
||||
|
||||
# Response generator example (stdout instead the socket)
|
||||
```c
|
||||
#include <stdio.h>
|
||||
#include "httpio.h"
|
||||
|
||||
static char out_pool[1024];
|
||||
|
||||
int main(int argc, const char **argv)
|
||||
{
|
||||
FILE *f;
|
||||
httpo_t *out;
|
||||
http_resp_t resp;
|
||||
char *data;
|
||||
int size;
|
||||
out = httpo_init(out_pool, 1024);
|
||||
http_resp_init(&resp, 200, MIME_TEXT_HTML, RESPF_KEEPALIVE | RESPF_CHUNKED | RESPF_NOCACH);
|
||||
httpo_write_resp(out, &resp);
|
||||
httpo_write_data(out, "first data chunk", 16);
|
||||
httpo_write_data(out, "the second data chunk", 21);
|
||||
httpo_finished(out);
|
||||
httpo_state(out, &data, &size);
|
||||
fwrite(data, 1, size, stdout);
|
||||
return 0;
|
||||
}
|
||||
```
|
||||
|
||||
Example output:
|
||||
```http
|
||||
HTTP/1.1 200 OK
|
||||
Content-Language: en
|
||||
Content-Type: text/html
|
||||
Connection: keep-alive
|
||||
Cache-Control: no-store, no-cache
|
||||
Transfer-Encoding: chunked
|
||||
|
||||
10
|
||||
first data chunk
|
||||
15
|
||||
the second data chunk
|
||||
0
|
||||
```
|
298
modules/web/http_server_simple/httpio/http.c
Normal file
298
modules/web/http_server_simple/httpio/http.c
Normal file
@ -0,0 +1,298 @@
|
||||
/*
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* Copyright (c) 2015 by Sergey Fetisov <fsenok@gmail.com>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
#include "http.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
const char MIME_APP_ATOM[] = "application/atom+xml";
|
||||
const char MIME_APP_JSON[] = "application/json";
|
||||
const char MIME_APP_JS[] = "application/javascript";
|
||||
const char MIME_APP_OCTSTR[] = "application/octet-stream";
|
||||
const char MIME_APP_PDF[] = "application/pdf";
|
||||
const char MIME_APP_PS[] = "application/postscript";
|
||||
const char MIME_APP_XHTML[] = "application/xhtml+xml";
|
||||
const char MIME_APP_XML[] = "application/xml-dtd";
|
||||
const char MIME_APP_ZIP[] = "application/zip";
|
||||
const char MIME_APP_GZIP[] = "application/x-gzip";
|
||||
const char MIME_APP_BTOR[] = "application/x-bittorrent";
|
||||
const char MIME_APP_TEX[] = "application/x-tex";
|
||||
const char MIME_URLENCODED[] = "application/x-www-form-urlencoded";
|
||||
const char MIME_TEXT_HTML[] = "text/html";
|
||||
const char MIME_TEXT_JS[] = "text/javascript";
|
||||
const char MIME_TEXT_PLAIN[] = "text/plain";
|
||||
const char MIME_TEXT_XML[] = "text/xml";
|
||||
const char MIME_TEXT_CSS[] = "text/css";
|
||||
const char MIME_IMAGE_GIF[] = "image/gif";
|
||||
const char MIME_IMAGE_JPEG[] = "image/jpeg";
|
||||
const char MIME_IMAGE_PJPEG[] = "image/pjpeg";
|
||||
const char MIME_IMAGE_PNG[] = "image/png";
|
||||
const char MIME_IMAGE_SVG[] = "image/svg+xml";
|
||||
const char MIME_IMAGE_TIFF[] = "image/tiff";
|
||||
const char MIME_IMAGE_ICON[] = "image/vnd.microsoft.icon";
|
||||
const char MIME_IMAGE_WBMP[] = "image/vnd.wap.wbmp";
|
||||
const char MIME_MPART_MIXED[] = "multipart/mixed";
|
||||
const char MIME_MPART_ALT[] = "multipart/alternative";
|
||||
const char MIME_MPART_REL[] = "multipart/related";
|
||||
const char MIME_MPART_FORM[] = "multipart/form-data";
|
||||
const char MIME_MPART_SIGN[] = "multipart/signed";
|
||||
const char MIME_MPART_ENCR[] = "multipart/encrypted";
|
||||
|
||||
const char *mime_list[] =
|
||||
{
|
||||
MIME_TEXT_HTML,
|
||||
MIME_TEXT_PLAIN,
|
||||
MIME_URLENCODED,
|
||||
MIME_APP_XHTML,
|
||||
MIME_APP_XML,
|
||||
MIME_TEXT_CSS,
|
||||
MIME_TEXT_JS,
|
||||
MIME_TEXT_XML,
|
||||
MIME_IMAGE_JPEG,
|
||||
MIME_IMAGE_PNG,
|
||||
MIME_IMAGE_GIF,
|
||||
MIME_IMAGE_SVG,
|
||||
MIME_MPART_FORM,
|
||||
MIME_MPART_MIXED,
|
||||
MIME_APP_JS,
|
||||
MIME_APP_JSON,
|
||||
MIME_APP_ATOM,
|
||||
MIME_APP_OCTSTR,
|
||||
MIME_APP_PDF,
|
||||
MIME_APP_PS,
|
||||
MIME_APP_ZIP,
|
||||
MIME_APP_GZIP,
|
||||
MIME_APP_BTOR,
|
||||
MIME_APP_TEX,
|
||||
MIME_IMAGE_PJPEG,
|
||||
MIME_IMAGE_TIFF,
|
||||
MIME_IMAGE_ICON,
|
||||
MIME_IMAGE_WBMP,
|
||||
MIME_MPART_ALT,
|
||||
MIME_MPART_REL,
|
||||
MIME_MPART_SIGN,
|
||||
MIME_MPART_ENCR,
|
||||
NULL
|
||||
};
|
||||
|
||||
struct http_code
|
||||
{
|
||||
int code;
|
||||
const char *str;
|
||||
};
|
||||
|
||||
static struct http_code http_code_list[] =
|
||||
{
|
||||
{ 100, "Continue" },
|
||||
{ 101, "Switching Protocols" },
|
||||
{ 102, "Processing" },
|
||||
{ 200, "OK" },
|
||||
{ 201, "Created" },
|
||||
{ 202, "Accepted" },
|
||||
{ 203, "Non-Authoritative Information" },
|
||||
{ 204, "No Content" },
|
||||
{ 205, "Reset Content" },
|
||||
{ 206, "Partial Content" },
|
||||
{ 207, "Multi Status" },
|
||||
{ 300, "Multiple Choices" },
|
||||
{ 301, "Moved Permanently" },
|
||||
{ 302, "Moved Temporarily" },
|
||||
{ 303, "See Other" },
|
||||
{ 304, "Not Modified" },
|
||||
{ 305, "Use Proxy" },
|
||||
{ 306, "Switch Proxy" },
|
||||
{ 307, "Temporary Redirect" },
|
||||
{ 400, "Bad Request" },
|
||||
{ 401, "Unauthorized" },
|
||||
{ 402, "Payment Required" },
|
||||
{ 403, "Forbidden" },
|
||||
{ 404, "Not Found" },
|
||||
{ 405, "Method Not Allowed" },
|
||||
{ 406, "Not Acceptable" },
|
||||
{ 407, "Proxy Authentication Required" },
|
||||
{ 408, "Request Time-out" },
|
||||
{ 409, "Conflict" },
|
||||
{ 410, "Gone" },
|
||||
{ 411, "Length Required" },
|
||||
{ 412, "Precondition Failed" },
|
||||
{ 413, "Request Entity Too Large" },
|
||||
{ 414, "Request-URI Too Large" },
|
||||
{ 415, "Unsupported Media Type" },
|
||||
{ 416, "Requested Range Not Satisfiable" },
|
||||
{ 417, "Expectation Failed" },
|
||||
{ 422, "Unprocessable Entity" },
|
||||
{ 423, "Locked" },
|
||||
{ 424, "Failed Dependency" },
|
||||
{ 425, "Unordered Collection" },
|
||||
{ 426, "Upgrade Required" },
|
||||
{ 444, "No Response" },
|
||||
{ 449, "Retry With" },
|
||||
{ 450, "Blocked by Windows Parental Controls" },
|
||||
{ 451, "Unavailable For Legal Reasons" },
|
||||
{ 500, "Internal Server Error" },
|
||||
{ 501, "Not Implemented" },
|
||||
{ 502, "Bad Gateway" },
|
||||
{ 503, "Service Unavailable" },
|
||||
{ 504, "Gateway Time-out" },
|
||||
{ 505, "HTTP Version not supported" },
|
||||
{ 506, "Variant Also Negotiates" },
|
||||
{ 507, "Insufficient Storage" },
|
||||
{ 508, "Unknown" },
|
||||
{ 509, "Bandwidth Limit Exceeded" },
|
||||
{ 510, "Not Extended" }
|
||||
};
|
||||
|
||||
static const char *CONN_TYPE_STR[] =
|
||||
{
|
||||
"", "close", "keep-alive"
|
||||
};
|
||||
|
||||
const char *http_req_val(const http_req_t *req, const char *param, const char *def)
|
||||
{
|
||||
int i;
|
||||
for (i = 0; i < req->nparams; i++)
|
||||
if (strcmp(req->params[i], param) == 0)
|
||||
return req->values[i];
|
||||
return def;
|
||||
}
|
||||
|
||||
void http_resp_init(http_resp_t *resp, int code, const char *mime, int flags)
|
||||
{
|
||||
memset(resp, 0, sizeof(http_resp_t));
|
||||
resp->code = code;
|
||||
resp->connection = flags & RESPF_KEEPALIVE ? CT_KEEP_ALIVE : CT_CLOSE;
|
||||
resp->content.type = mime;
|
||||
resp->content.length = -1;
|
||||
resp->content.language = "en";
|
||||
resp->cache_control = flags & RESPF_NOCACH ? "no-store, no-cache" : NULL;
|
||||
if (flags & RESPF_DEFLATE) resp->content.encoding = "deflate"; else
|
||||
if (flags & RESPF_GZIP) resp->content.encoding = "gzip";
|
||||
resp->transfer_encoding = flags & RESPF_CHUNKED ? TENC_CHUNKED : TENC_NONE;
|
||||
}
|
||||
|
||||
const char *http_dict_mime(const char *mime)
|
||||
{
|
||||
int i;
|
||||
if (mime == NULL) return NULL;
|
||||
for (i = 0; mime_list[i] != NULL; i++)
|
||||
if (strcmp(mime_list[i], mime) == 0)
|
||||
return mime_list[i];
|
||||
return NULL;
|
||||
}
|
||||
|
||||
int http_resp_len(const http_resp_t *resp)
|
||||
{
|
||||
int tmp;
|
||||
return http_resp_str(resp, (char *)&tmp, sizeof(tmp));
|
||||
}
|
||||
|
||||
#if defined(__WINNT__) || defined(_WIN32) || defined(_WIN64)
|
||||
int correct_snprintf(char *buff, int buff_size, const char *fmt, ...)
|
||||
{
|
||||
int res;
|
||||
va_list args;
|
||||
va_start(args, fmt);
|
||||
res = vsnprintf(buff, buff_size, fmt, args);
|
||||
if (res < 0) res = _vscprintf(fmt, args);
|
||||
va_end(args);
|
||||
return res;
|
||||
}
|
||||
#else
|
||||
#define correct_snprintf snprintf
|
||||
#endif
|
||||
|
||||
int http_resp_str(const http_resp_t *resp, char *str, int size)
|
||||
{
|
||||
#define PRN(fmt, arg) \
|
||||
{ \
|
||||
n = correct_snprintf(str, size, fmt, arg); \
|
||||
str += n; \
|
||||
size -= n; \
|
||||
res += n; \
|
||||
if (size < 0) size = 0; \
|
||||
}
|
||||
|
||||
#define PRNSTR(prop, field) if (field != NULL) PRN(prop ": %s\r\n", field)
|
||||
|
||||
int res, n;
|
||||
res = 0;
|
||||
|
||||
PRN("HTTP/1.1 %d ", resp->code);
|
||||
PRN("%s\r\n", http_code_str(resp->code));
|
||||
if (resp->content.disp.disp != NULL)
|
||||
{
|
||||
PRN("Content-Disposition %s", resp->content.disp.disp);
|
||||
if (resp->content.disp.disp_name != NULL)
|
||||
PRN(" name=\"%s\"", resp->content.disp.disp_name);
|
||||
if (resp->content.disp.disp_file != NULL)
|
||||
PRN(" filename=\"%s\"", resp->content.disp.disp_file);
|
||||
PRN("%s", "\r\n");
|
||||
}
|
||||
PRNSTR("Content-Encoding", resp->content.encoding);
|
||||
PRNSTR("Content-Language", resp->content.language);
|
||||
if (resp->content.length > 0)
|
||||
PRN("Content-Length: %d\r\n", resp->content.length);
|
||||
PRNSTR("Content-Location", resp->content.location);
|
||||
PRNSTR("Content-MD5", resp->content.md5);
|
||||
/* TODO: http_rng_t range; */
|
||||
PRNSTR("Content-Type", resp->content.type);
|
||||
PRNSTR("Content-Version", resp->content.ver);
|
||||
PRNSTR("Expires", resp->content.expires);
|
||||
PRNSTR("Last-Modified", resp->content.modified);
|
||||
PRNSTR("Link", resp->content.link);
|
||||
PRNSTR("Title", resp->content.title);
|
||||
PRN("Connection: %s\r\n", CONN_TYPE_STR[resp->connection]);
|
||||
PRNSTR("Cache-Control", resp->cache_control);
|
||||
PRNSTR("ETag", resp->etag);
|
||||
PRNSTR("Location", resp->location);
|
||||
PRNSTR("Proxy-Authenticate", resp->proxy_authenticate);
|
||||
PRNSTR("Public", resp->Public);
|
||||
if (resp->retry_after > 0)
|
||||
PRN("Retry-After: %d\r\n", resp->retry_after);
|
||||
PRNSTR("Server", resp->server);
|
||||
if (resp->transfer_encoding == TENC_CHUNKED)
|
||||
PRN("Transfer-Encoding: %s\r\n", "chunked");
|
||||
PRNSTR("Vary", resp->vary);
|
||||
PRNSTR("WWW-Authenticate", resp->www_authenticate);
|
||||
if (resp->exthdr != NULL)
|
||||
PRN("%s", resp->exthdr);
|
||||
PRN("%s", "\r\n");
|
||||
return res;
|
||||
}
|
||||
|
||||
const char *http_code_str(int code)
|
||||
{
|
||||
int i, n;
|
||||
n = sizeof(http_code_list) / sizeof(struct http_code);
|
||||
for (i = 0; i < n; i++)
|
||||
if (http_code_list[i].code == code)
|
||||
return http_code_list[i].str;
|
||||
return "";
|
||||
}
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
237
modules/web/http_server_simple/httpio/http.h
Normal file
237
modules/web/http_server_simple/httpio/http.h
Normal file
@ -0,0 +1,237 @@
|
||||
/*
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* Copyright (c) 2015 by Sergey Fetisov <fsenok@gmail.com>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
#ifndef HTTP_H
|
||||
#define HTTP_H
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdbool.h>
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdarg.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#ifndef HTTP_REQ_MAX_PARAMS
|
||||
#define HTTP_REQ_MAX_PARAMS 16
|
||||
#endif
|
||||
|
||||
#ifndef HTTP_REQ_MAX_ACCEPT
|
||||
#define HTTP_REQ_MAX_ACCEPT 8
|
||||
#endif
|
||||
|
||||
extern const char MIME_APP_ATOM[]; /* application/atom+xml */
|
||||
extern const char MIME_APP_JSON[]; /* application/json */
|
||||
extern const char MIME_APP_JS[]; /* application/javascript */
|
||||
extern const char MIME_APP_OCTSTR[]; /* application/octet-stream */
|
||||
extern const char MIME_APP_PDF[]; /* application/pdf */
|
||||
extern const char MIME_APP_PS[]; /* application/postscript */
|
||||
extern const char MIME_APP_XHTML[]; /* application/xhtml+xml */
|
||||
extern const char MIME_APP_XML[]; /* application/xml-dtd */
|
||||
extern const char MIME_APP_ZIP[]; /* application/zip */
|
||||
extern const char MIME_APP_GZIP[]; /* application/x-gzip */
|
||||
extern const char MIME_APP_BTOR[]; /* application/x-bittorrent */
|
||||
extern const char MIME_APP_TEX[]; /* application/x-tex */
|
||||
extern const char MIME_URLENCODED[]; /* application/x-www-form-urlencoded */
|
||||
extern const char MIME_TEXT_HTML[]; /* text/html */
|
||||
extern const char MIME_TEXT_JS[]; /* text/javascript */
|
||||
extern const char MIME_TEXT_PLAIN[]; /* text/plain */
|
||||
extern const char MIME_TEXT_XML[]; /* text/xml */
|
||||
extern const char MIME_TEXT_CSS[]; /* text/css */
|
||||
extern const char MIME_IMAGE_GIF[]; /* image/gif */
|
||||
extern const char MIME_IMAGE_JPEG[]; /* image/jpeg */
|
||||
extern const char MIME_IMAGE_PJPEG[]; /* image/pjpeg */
|
||||
extern const char MIME_IMAGE_PNG[]; /* image/png */
|
||||
extern const char MIME_IMAGE_SVG[]; /* image/svg+xml */
|
||||
extern const char MIME_IMAGE_TIFF[]; /* image/tiff */
|
||||
extern const char MIME_IMAGE_ICON[]; /* image/vnd.microsoft.icon */
|
||||
extern const char MIME_IMAGE_WBMP[]; /* image/vnd.wap.wbmp */
|
||||
extern const char MIME_MPART_MIXED[]; /* multipart/mixed */
|
||||
extern const char MIME_MPART_ALT[]; /* multipart/alternative */
|
||||
extern const char MIME_MPART_REL[]; /* multipart/related */
|
||||
extern const char MIME_MPART_FORM[]; /* multipart/form-data */
|
||||
extern const char MIME_MPART_SIGN[]; /* multipart/signed */
|
||||
extern const char MIME_MPART_ENCR[]; /* multipart/encrypted */
|
||||
|
||||
typedef enum http_method
|
||||
{
|
||||
METHOD_NONE,
|
||||
METHOD_GET,
|
||||
METHOD_POST,
|
||||
METHOD_HEAD,
|
||||
METHOD_PUT,
|
||||
METHOD_CONNECT,
|
||||
METHOD_OPTIONS,
|
||||
METHOD_DELETE,
|
||||
METHOD_TRACE,
|
||||
METHOD_PATCH
|
||||
} http_mt_t;
|
||||
|
||||
typedef enum http_conn_type
|
||||
{
|
||||
CT_NONE,
|
||||
CT_CLOSE,
|
||||
CT_KEEP_ALIVE
|
||||
} http_ct_t;
|
||||
|
||||
/* http content disposition */
|
||||
typedef struct http_cdh
|
||||
{
|
||||
const char *disp; /* Content-Disposition: [form-data]; name="File1"; filename="photo.jpg" */
|
||||
const char *disp_name; /* Content-Disposition: form-data; name="[File1]"; filename="photo.jpg" */
|
||||
const char *disp_file; /* Content-Disposition: form-data; name="File1"; filename="[photo.jpg]" */
|
||||
} http_cdh_t;
|
||||
|
||||
typedef struct http_range
|
||||
{
|
||||
uint32_t range_size;
|
||||
uint32_t range_from;
|
||||
uint32_t range_to;
|
||||
} http_rng_t;
|
||||
|
||||
/* http response/request entity */
|
||||
|
||||
typedef struct http_cont
|
||||
{
|
||||
http_cdh_t disp; /* Content-Disposition: [form-data; name="File1"; filename="photo.jpg"] */
|
||||
const char *encoding; /* Content-Encoding: [...] */
|
||||
const char *language; /* Content-Language: [en, ase, ru] */
|
||||
int length; /* Content-Length: [123] */
|
||||
const char *location; /* Content-Location: [...] */
|
||||
const char *md5; /* Content-MD5: [Q2hlY2sgSW50ZWdyaXR5IQ==] */
|
||||
http_rng_t range; /* Content-Range: [64397516-80496894/160993792] */
|
||||
const char *type; /* Content-Type: [multipart/form-data] */
|
||||
const char *boundary; /* Content-Type: multipart/form-data; boundary="[Asrf456BGe4h]" */
|
||||
const char *charset; /* Content-Type: Content-Type: text/html; charset=[UTF-8] */
|
||||
const char *ver; /* Content-Version: [...] */
|
||||
const char *expires; /* Expires: [Tue, 31 Jan 2012 15:02:53 GMT] */
|
||||
const char *modified; /* Last-Modified: [...] */
|
||||
const char *link; /* link: [...] */
|
||||
const char *title; /* Title: [...] */
|
||||
} http_cont_t;
|
||||
|
||||
/* http transfer encoding */
|
||||
typedef enum http_tenc
|
||||
{
|
||||
TENC_NONE, /* - */
|
||||
TENC_CHUNKED /* Transfer-Encoding: chunked */
|
||||
} http_tenc_t;
|
||||
|
||||
/* http transfer encoding */
|
||||
typedef struct httpaccept
|
||||
{
|
||||
int count;
|
||||
const char *type[HTTP_REQ_MAX_ACCEPT]; /* text/html */
|
||||
int level[HTTP_REQ_MAX_ACCEPT]; /* level=[1] */
|
||||
float q[HTTP_REQ_MAX_ACCEPT]; /* q=[0.8] */
|
||||
} httpaccept_t;
|
||||
|
||||
typedef struct http_req
|
||||
{
|
||||
/* request line */
|
||||
http_mt_t method; /* GET */
|
||||
const char *uri; /* /path */
|
||||
int nparams; /* */
|
||||
const char *params[HTTP_REQ_MAX_PARAMS]; /* param1, param2 */
|
||||
const char *values[HTTP_REQ_MAX_PARAMS]; /* value1, value2 */
|
||||
const char *ver; /* HTTP/1.1 */
|
||||
|
||||
/* general header */
|
||||
http_ct_t connection; /* Connection: [keep-alive] */
|
||||
char *via; /* Via: [1.0 fred, 1.1 example.com] */
|
||||
|
||||
/* request header */
|
||||
httpaccept_t accept;
|
||||
const char *accept_charset; /* Accept-Charset: [utf-8] */
|
||||
const char *accept_encoding; /* Accept-Encoding: [gzip, deflate] */
|
||||
const char *accept_language; /* Accept-Language: [en-US;q=0.5,en;q=0.3] */
|
||||
const char *authorization; /* Authorization: [Basic QWxhZGRpbjpvcGVuIHNlc2FtZQ==] */
|
||||
const char *expect; /* Expect: [100-continue] */
|
||||
const char *from; /* From: [user@example.com] */
|
||||
const char *host; /* Host: [wikipedia.org] */
|
||||
const char *if_match; /* If-Match: "[737060cd8c284d8af7ad3082f209582d]" */
|
||||
const char *if_modified_since; /* If-Modified-Since: [Sat, 29 Oct 1994 19:43:31 GMT] */
|
||||
const char *if_none_match; /* If-None-Match: "[737060cd8c284d8af7ad3082f209582d]" */
|
||||
const char *if_range; /* If-Range: "[737060cd8c284d8af7ad3082f209582d]" */
|
||||
const char *if_unmodified_since; /* If-Unmodified-Since: [Sat, 29 Oct 1994 19:43:31 GMT] */
|
||||
int keep_alive; /* Keep-Alive: [300] */
|
||||
int max_forwards; /* Max-Forwards: [10] */
|
||||
const char *proxy_authorization; /* Proxy-Authorization: [Basic QWxhZGRpbjpvcGVuIHNlc2FtZQ==] */
|
||||
http_rng_t range; /* Range: bytes=[50000-99999],250000-399999,500000- */
|
||||
const char *referer; /* Referer: [http://en.wikipedia.org/wiki/Main_Page] */
|
||||
const char *te; /* TE: [trailers, deflate] */
|
||||
const char *user_agent; /* User-Agent: [Mozilla/5.0] */
|
||||
|
||||
/* content and cookies */
|
||||
http_cont_t content; /**/
|
||||
const char *cookie; /* Cookie: [Cookie data] */
|
||||
} http_req_t;
|
||||
|
||||
typedef enum http_resp_flag
|
||||
{
|
||||
RESPF_NONE = 0,
|
||||
RESPF_KEEPALIVE = 1,
|
||||
RESPF_CHUNKED = 2,
|
||||
RESPF_NOCACH = 4,
|
||||
RESPF_DEFLATE = 8,
|
||||
RESPF_GZIP = 16
|
||||
} http_respf_t;
|
||||
|
||||
typedef struct http_resp
|
||||
{
|
||||
|
||||
char *mime_ver; /* MIME-Version: 1.0 */
|
||||
char *pragma; /* Pragma: [no-cache] */
|
||||
int code; /* HTTP/1.1 [200] OK */
|
||||
http_cont_t content; /**/
|
||||
http_ct_t connection; /* Connection: [keep-alive] */
|
||||
const char *cache_control; /* Cache-Control: [no-cache] */
|
||||
const char *etag; /* ETag: "[56d-9989200-1132c580]" */
|
||||
const char *location; /* Location: [http://example.com/about.html#contacts] */
|
||||
const char *proxy_authenticate; /* Proxy-Authenticate: [...] */
|
||||
const char *Public; /* Public: [...] */
|
||||
int retry_after; /* Retry-After: [123] */
|
||||
const char *server; /* Server: [Name] */
|
||||
http_tenc_t transfer_encoding; /* Transfer-Encoding: [chunked] */
|
||||
const char *vary; /* Vary: [...] */
|
||||
const char *www_authenticate; /* WWW-Authenticate: [...] */
|
||||
char *upgrade; /* Upgrade: [HTTP/2.0, SHTTP/1.3, IRC/6.9, RTA/x11] */
|
||||
const char *exthdr; /* extended header options */
|
||||
} http_resp_t;
|
||||
|
||||
const char *http_req_val(const http_req_t *req, const char *param, const char *def);
|
||||
void http_resp_init(http_resp_t *resp, int code, const char *mime, int flags);
|
||||
const char *http_dict_mime(const char *mime);
|
||||
const char *http_code_str(int code);
|
||||
int http_resp_len(const http_resp_t *resp);
|
||||
int http_resp_str(const http_resp_t *resp, char *str, int size);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
1330
modules/web/http_server_simple/httpio/httpio.c
Normal file
1330
modules/web/http_server_simple/httpio/httpio.c
Normal file
File diff suppressed because it is too large
Load Diff
185
modules/web/http_server_simple/httpio/httpio.h
Normal file
185
modules/web/http_server_simple/httpio/httpio.h
Normal file
@ -0,0 +1,185 @@
|
||||
/*
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* Copyright (c) 2015 by Sergey Fetisov <fsenok@gmail.com>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
#ifndef HTTPIO_H
|
||||
#define HTTPIO_H
|
||||
|
||||
#include <stdbool.h>
|
||||
#include <stdint.h>
|
||||
#include <stddef.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include "http.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
typedef struct http_output httpo_t;
|
||||
typedef struct http_input httpi_t;
|
||||
typedef struct http_post_info http_post_t;
|
||||
|
||||
struct http_post_info
|
||||
{
|
||||
const char *name;
|
||||
const char *file;
|
||||
const char *disp_type;
|
||||
const char *content_type;
|
||||
const char *data; /**< pointer to current post data chunk */
|
||||
int size; /**< size of current post data chunk */
|
||||
int first; /**< is it first post data chunk */
|
||||
int last; /**< is it last post data chunk */
|
||||
};
|
||||
|
||||
/* next codes returns httpi_pull function: */
|
||||
#define HTTP_IN_NODATA 0 /* have no more input data */
|
||||
#define HTTP_IN_REQUEST 2 /* http request parsed */
|
||||
#define HTTP_IN_POSTDATA 32 /* has POST-request data */
|
||||
#define HTTP_IN_FINISHED 64 /* request parsing is finished */
|
||||
#define HTTP_IN_ERR_SYNT 256 /* request syntax error */
|
||||
#define HTTP_IN_ERR_NOMEM 512 /* have no memory in pool */
|
||||
#define HTTP_IN_ERR_UMETH 1024 /* unknown request method */
|
||||
#define HTTP_IN_ERR_PARLIM 2048 /* too many request parameters */
|
||||
|
||||
/**
|
||||
* @brief Initialize new http-input driver
|
||||
* @param pool Memory pool buffer
|
||||
* @param size Memory pool buffer size
|
||||
* @return Http-input driver instance or NULL if \a size value is too small
|
||||
* @warning You shouldn't change any data in pool after this call
|
||||
*
|
||||
* Instance structure will be allocated from a pool.
|
||||
* Library has no any dynamic allocation call.
|
||||
*/
|
||||
httpi_t *httpi_init(const void *pool, int size);
|
||||
|
||||
/**
|
||||
* @brief Get the next parsed element
|
||||
* @param httpi Http-input driver instance
|
||||
* @return One of HTTP_IN_xxx value
|
||||
*/
|
||||
int httpi_pull(httpi_t *httpi);
|
||||
|
||||
/**
|
||||
* @brief Push the received data to a driver instance for it parsing
|
||||
* @param httpi Http-input driver instance
|
||||
* @param data Pointer to a data
|
||||
* @param size Data size
|
||||
* @warning You shouldn't change data until the httpi_pull() call not returns HTTP_IN_NODATA value
|
||||
*/
|
||||
void httpi_push(httpi_t *httpi, const void *data, int size);
|
||||
|
||||
/**
|
||||
* @brief Allows to know the pool buffer state
|
||||
* @param httpi Http-input driver instance
|
||||
* @param pool Output pointer to unused pool space
|
||||
* @param avail Output value of unused pool space
|
||||
*
|
||||
* You can use the unused space to receive the data from a network
|
||||
* before the httpi_push() call like this:
|
||||
* int size;
|
||||
* char *data;
|
||||
* httpi_get_state(httpi, &pool, &size);
|
||||
* size = recv(client, data, size, 0);
|
||||
* httpi_push(httpi, data, size);
|
||||
*/
|
||||
void httpi_get_state(httpi_t *httpi, char **pool, int *avail);
|
||||
|
||||
/**
|
||||
* @brief Get the HTTP-request structure
|
||||
* @param httpi Http-input driver instance
|
||||
* @return Pointer to the request structure
|
||||
*
|
||||
* You can do this call if httpi_pull() returned HTTP_IN_REQUEST
|
||||
*/
|
||||
const http_req_t *httpi_request(httpi_t *httpi);
|
||||
|
||||
/**
|
||||
* @brief Get the next HTTP POST data
|
||||
* @param httpi Http-input driver instance
|
||||
* @return Pointer to the http_post_t structure
|
||||
*
|
||||
* You can do this call if httpi_pull() returned HTTP_IN_POSTDATA
|
||||
*/
|
||||
const http_post_t *httpi_posted(httpi_t *httpi);
|
||||
|
||||
/**
|
||||
* @brief Initialize the HTTP-output driver instance
|
||||
* @param pool Memory pool buffer
|
||||
* @param poolsz Memory pool buffer size
|
||||
* @return HTTP-output driver instance
|
||||
*/
|
||||
httpo_t *httpo_init(void *pool, int poolsz);
|
||||
|
||||
/**
|
||||
* @brief Returns the prepared HTTP output data
|
||||
* @param out HTTP-output driver instance
|
||||
* @param data Output pointer to prepared data
|
||||
* @param size Output value of prepared data size
|
||||
*/
|
||||
void httpo_state(httpo_t *out, char **data, int *size);
|
||||
|
||||
/**
|
||||
* @brief Increments the tail pointer of output buffer
|
||||
* @param out HTTP-output driver instance
|
||||
* @param count The amount of data that has been sent
|
||||
*/
|
||||
void httpo_sended(httpo_t *out, int count);
|
||||
|
||||
/**
|
||||
* @brief Writes the HTTP response to the output buffer
|
||||
* @param out HTTP-output driver instance
|
||||
* @param resp Responce structure
|
||||
* @return 1 if successful, or 0 if not enough memory in the output buffer
|
||||
*/
|
||||
int httpo_write_resp(httpo_t *out, const http_resp_t *resp);
|
||||
|
||||
/**
|
||||
* @brief Writes the response data to the output buffer
|
||||
* @param out HTTP-output driver instance
|
||||
* @param data Response data
|
||||
* @param size Response data size
|
||||
* @return 1 if successful, or 0 if not enough memory in the output buffer
|
||||
*/
|
||||
int httpo_write_data(httpo_t *out, const void *data, int size);
|
||||
|
||||
/**
|
||||
* @brief Returns the size of the data available for writing by httpo_write_data
|
||||
* @param out HTTP-output driver instance
|
||||
* @return Size of the data available for writing
|
||||
*/
|
||||
int httpo_write_avail(httpo_t *out);
|
||||
|
||||
/**
|
||||
* @brief Correctly ends the output stream
|
||||
* @param out HTTP-output driver instance
|
||||
*/
|
||||
void httpo_finished(httpo_t *out);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
Loading…
Reference in New Issue
Block a user