output buffers

This commit is contained in:
Udo 2021-12-09 03:01:10 +00:00
parent 8195154e4c
commit af29d51536
19 changed files with 169 additions and 62 deletions

Binary file not shown.

View File

@ -509,9 +509,30 @@ FastCGIServer::process_write_request(Connection& connection, RequestID id,
} }
if ((request.in_closed || request.status != 0) && if ((request.in_closed || request.status != 0) &&
!request.output_closed) { !request.output_closed) {
request.out =
var_dump(request.header, "", "\r\n") +
var_dump(request.set_cookies, "", "\r\n") +
"\r\n";
for(auto obs : request.ob_stack)
{
request.out += obs->str();
delete obs;
}
request.ob_stack.clear();
write_data(connection.output_buffer, id, request.out, FCGI_STDOUT); write_data(connection.output_buffer, id, request.out, FCGI_STDOUT);
write_data(connection.output_buffer, id, request.err, FCGI_STDERR); write_data(connection.output_buffer, id, request.err, FCGI_STDERR);
request.time_end = microtime();
printf("(r) pid:%i\t%s\t%0.6fs\t%0.1fkB\n",
my_pid,
request.params["REQUEST_URI"].c_str(),
request.time_end - request.time_start,
(f32)(request.out.length()/1024)
);
FCGI_EndRequestRecord complete; FCGI_EndRequestRecord complete;
bzero(&complete, sizeof(complete)); bzero(&complete, sizeof(complete));
complete.header.version = FCGI_VERSION_1; complete.header.version = FCGI_VERSION_1;

View File

@ -4,7 +4,7 @@
String process_html_literal(Request* context, SharedUnit* su, String content) String process_html_literal(Request* context, SharedUnit* su, String content)
{ {
String pc; String pc;
String HT_START = "context->print(R\"("; String HT_START = "print(R\"(";
String HT_END = ")\");"; String HT_END = ")\");";
u8 mode = 0; u8 mode = 0;
@ -63,7 +63,7 @@ String process_html_literal(Request* context, SharedUnit* su, String content)
{ {
pc.append( pc.append(
HT_END + HT_END +
"echo(html_escape( " + "print(html_escape( " +
code_buffer + code_buffer +
" )); " + " )); " +
HT_START HT_START
@ -299,17 +299,17 @@ void compiler_invoke(Request* context, String file_name, DTree& call_param)
if(!su) if(!su)
{ {
printf("Error loading unit %s\n", file_name.c_str()); printf("Error loading unit %s\n", file_name.c_str());
context->print("Error loading unit: "+file_name); print("Error loading unit: "+file_name);
} }
else if(!su->on_render) else if(!su->on_render)
{ {
context->header["Content-Type"] = "text/plain"; context->header["Content-Type"] = "text/plain";
context->print("Compiler error: "+su->compiler_messages); print("Compiler error: "+su->compiler_messages);
} }
else else
{ {
if(su->compiler_messages.length() > 0) if(su->compiler_messages.length() > 0)
context->print(su->compiler_messages); print(su->compiler_messages);
else else
{ {
String prev_wd = get_cwd(); String prev_wd = get_cwd();

View File

@ -184,14 +184,14 @@ String json_encode(DTree t)
String json_decode_String(String s, u32& i, char termination_char) String json_decode_String(String s, u32& i, char termination_char)
{ {
String result; String result;
//echo("json_decode_String " + s.substr(i) + "\n"); //print("json_decode_String " + s.substr(i) + "\n");
while(i < s.length()) while(i < s.length())
{ {
char c = s[i]; char c = s[i];
if(c == termination_char) if(c == termination_char)
{ {
i += 1; i += 1;
//echo("json_decode_String = " + result + "\n"); //print("json_decode_String = " + result + "\n");
return(result); return(result);
} }
else if(c == '\\') else if(c == '\\')
@ -289,7 +289,7 @@ DTree json_decode_value(String s, u32& i)
String value = ""; String value = "";
json_consume_space(s, i); json_consume_space(s, i);
char c = s[i]; char c = s[i];
//echo("json_decode_value " + s.substr(i) + "\n"); //print("json_decode_value " + s.substr(i) + "\n");
if(c == '"' || c == '\'') // String value if(c == '"' || c == '\'') // String value
{ {
result.type = 'S'; result.type = 'S';
@ -329,7 +329,7 @@ DTree json_decode_map(String s, u32& i)
result.type = 'M'; result.type = 'M';
String key = ""; String key = "";
json_consume_space(s, i); json_consume_space(s, i);
//echo("json_decode_map " + s.substr(i) + "\n"); //print("json_decode_map " + s.substr(i) + "\n");
while(i < s.length()) while(i < s.length())
{ {
char c = s[i]; char c = s[i];
@ -352,7 +352,7 @@ DTree json_decode_map(String s, u32& i)
i += 1; i += 1;
DTree v = json_decode_value(s, i); DTree v = json_decode_value(s, i);
//result._map[key] = json_decode_value(s, i); //result._map[key] = json_decode_value(s, i);
//echo("KV " + key + " = " + to_String(v) + "\n"); //print("KV " + key + " = " + to_String(v) + "\n");
//printf("map add %s (%c) \n", key.c_str(), s[i]); //printf("map add %s (%c) \n", key.c_str(), s[i]);
result._map[key] = v; result._map[key] = v;
} }
@ -372,4 +372,28 @@ DTree json_decode(String s)
return(json_decode_value(s, i)); return(json_decode_value(s, i));
} }
void ob_start()
{
context->ob_start();
}
void ob_close()
{
delete context->ob;
context->ob_stack.pop_back();
if(context->ob_stack.size() == 0)
ob_start();
}
String ob_get()
{
return(context->ob->str());
}
String ob_get_close()
{
String result = context->ob->str();
ob_close();
return(result);
}

View File

@ -24,3 +24,8 @@ DTree json_decode(String s);
String var_dump(StringMap map, String prefix = "", String postfix = "\n"); String var_dump(StringMap map, String prefix = "", String postfix = "\n");
String var_dump(StringList slist, String prefix = "", String postfix = "\n"); String var_dump(StringList slist, String prefix = "", String postfix = "\n");
void ob_start();
void ob_clear();
String ob_get_clear();
String ob_get();

View File

@ -247,7 +247,7 @@ u64 socket_connect(String host, short port)
auto sockfd = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); auto sockfd = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
if(sockfd < 0) if(sockfd < 0)
{ {
echo("SOCKET ERROR (could not open socket)\n"); print("SOCKET ERROR (could not open socket)\n");
perror("SOCKET ERROR "); perror("SOCKET ERROR ");
return(0); return(0);
} }
@ -259,7 +259,7 @@ u64 socket_connect(String host, short port)
if(connect(sockfd, (struct sockaddr*) &addr, sizeof(addr)) < 0) if(connect(sockfd, (struct sockaddr*) &addr, sizeof(addr)) < 0)
{ {
echo("SOCKET ERROR (could not connect to address " + String(host) + ":" + std::to_string(port) + ")\n"); print("SOCKET ERROR (could not connect to address " + String(host) + ":" + std::to_string(port) + ")\n");
perror("SOCKET ERROR "); perror("SOCKET ERROR ");
return(0); return(0);
} }
@ -438,3 +438,4 @@ void on_child_exit(int sig)
} }
} }

View File

@ -50,9 +50,10 @@ void Request::invoke(String file_name, DTree& call_param)
compiler_invoke(this, file_name, call_param); compiler_invoke(this, file_name, call_param);
} }
void Request::print(String s) void Request::ob_start()
{ {
out.append(s); ob_stack.push_back(new std::ostringstream());
ob = ob_stack.back();
} }
Request::~Request() Request::~Request()

View File

@ -3,6 +3,7 @@
#include <list> #include <list>
#include <vector> #include <vector>
#include <functional> #include <functional>
#include <sstream>
typedef unsigned char u8; typedef unsigned char u8;
typedef signed char s8; typedef signed char s8;
@ -17,6 +18,30 @@ typedef long long s64;
typedef std::string String; typedef std::string String;
String operator+(String lhs, u64 rhs) {
return(lhs + std::to_string(rhs));
}
String operator+(String lhs, u32 rhs) {
return(lhs + std::to_string(rhs));
}
String operator+(String lhs, s64 rhs) {
return(lhs + std::to_string(rhs));
}
String operator+(String lhs, s32 rhs) {
return(lhs + std::to_string(rhs));
}
String operator+(String lhs, f64 rhs) {
return(lhs + std::to_string(rhs));
}
String operator+(String lhs, f32 rhs) {
return(lhs + std::to_string(rhs));
}
#define DEBUG_MEMORY_OFF; #define DEBUG_MEMORY_OFF;
#define NO_GLOBAL_ARENA_ALLOCATOR; #define NO_GLOBAL_ARENA_ALLOCATOR;
@ -105,9 +130,6 @@ void operator delete(void * p) throw()
} }
#endif #endif
//#define to_String(a) std::to_String(a)
#define echo(s) context->print(s)
typedef std::map<String, String> StringMap; typedef std::map<String, String> StringMap;
typedef std::vector<String> StringList; typedef std::vector<String> StringList;
@ -217,13 +239,21 @@ struct Request {
MemoryArena* request_arena; MemoryArena* request_arena;
String in; String in;
std::vector<std::ostringstream*> ob_stack;
std::ostringstream* ob;
String out; String out;
String err; String err;
bool is_finished = false;
f64 time_init; f64 time_init;
f64 time_start; f64 time_start;
f64 time_end; f64 time_end;
struct Stats {
u32 bytes_written;
} stats;
struct Resources { struct Resources {
std::vector<u64> sockets; std::vector<u64> sockets;
std::vector<void*> mysql_connections; std::vector<void*> mysql_connections;
@ -231,7 +261,9 @@ struct Request {
void invoke(String file_name); void invoke(String file_name);
void invoke(String file_name, DTree& call_param); void invoke(String file_name, DTree& call_param);
void print(String s);
void ob_start();
~Request(); ~Request();
}; };
@ -239,3 +271,11 @@ struct Request {
typedef Request FastCGIRequest; typedef Request FastCGIRequest;
Request* context; Request* context;
#include <iostream>
template <typename... Ts>
void print(Ts... args)
{
((*context->ob << args), ...);
}

View File

@ -12,6 +12,8 @@ int handle_request(FastCGIRequest& request) {
// standard input stream. // standard input stream.
request.request_arena = request_arena; request.request_arena = request_arena;
request.time_init = microtime(); request.time_init = microtime();
request.ob_start(); // this one is for the headers
request.ob_start(); // this one is for the content
if (request.params.count("REQUEST_URI")) if (request.params.count("REQUEST_URI"))
return 0; // OK, continue processing return 0; // OK, continue processing
else else
@ -70,12 +72,6 @@ int handle_complete(FastCGIRequest& request) {
request.invoke(request.params["SCRIPT_FILENAME"]); request.invoke(request.params["SCRIPT_FILENAME"]);
switch_to_system_alloc(); switch_to_system_alloc();
String headers =
var_dump(request.header, "", "\r\n") +
var_dump(request.set_cookies, "", "\r\n") +
"\r\n";
request.out = headers + request.out;
for( auto &f : request.uploaded_files) for( auto &f : request.uploaded_files)
{ {
unlink(f.tmp_name); unlink(f.tmp_name);
@ -86,14 +82,6 @@ int handle_complete(FastCGIRequest& request) {
cleanup_mysql_connections(); cleanup_mysql_connections();
request.time_end = microtime();
printf("(r) pid:%i\t%s\t%0.6fs\t%0.1fkB\n",
my_pid,
request.params["REQUEST_URI"].c_str(),
request.time_end - request.time_start,
(f32)(request.out.length()/1024)
);
return 0; return 0;
} }

View File

@ -14,13 +14,13 @@ RENDER()
set_cookie("test-cookie-1", "test-value-1", time() + 30*60); set_cookie("test-cookie-1", "test-value-1", time() + 30*60);
set_cookie("test-cookie-2", "test-value-2", time() + 30*60*24); set_cookie("test-cookie-2", "test-value-2", time() + 30*60*24);
echo(var_dump(context->set_cookies)); print(var_dump(context->set_cookies));
?></pre> ?></pre>
Get Get
<pre><? <pre><?
echo(var_dump(context->cookies)); print(var_dump(context->cookies));
?></pre> ?></pre>
Params Params

View File

@ -16,16 +16,16 @@ RENDER()
<pre><? <pre><?
t.set("String test"); t.set("String test");
echo(String("String test: ") + t.to_string()+"\n"); print(String("String test: ") + t.to_string()+"\n");
t.set(true); t.set(true);
echo(String("bool test: ") + t.to_string()+"\n"); print(String("bool test: ") + t.to_string()+"\n");
t.set(1234.5678); t.set(1234.5678);
echo(String("float test: ") + t.to_string()+"\n"); print(String("float test: ") + t.to_string()+"\n");
t.set(&t); t.set(&t);
echo(String("pointer test: ") + t.to_string()+"\n"); print(String("pointer test: ") + t.to_string()+"\n");
?></pre> ?></pre>
@ -43,7 +43,7 @@ RENDER()
t["g"]["x"]["y2"] = &t; t["g"]["x"]["y2"] = &t;
t["g"]["x"]["y3"] = time(); t["g"]["x"]["y3"] = time();
t["g"]["x"]["y4"] = "Ünicödä"; t["g"]["x"]["y4"] = "Ünicödä";
echo(var_dump(t)); print(var_dump(t));
?></pre> ?></pre>

View File

@ -1,4 +1,4 @@
void test_output() void test_output()
{ {
echo("hello from include!"); print("hello from include!");
} }

View File

@ -26,8 +26,8 @@ RENDER()
<li><a href="fileio.uce">File I/O</a></li> <li><a href="fileio.uce">File I/O</a></li>
</ul> </ul>
<pre><? <pre><?
echo("Worker PID: "+std::to_string(my_pid)+"\n"); print("Worker PID: ", my_pid, "\n");
echo("Parent PID: "+std::to_string(parent_pid)+" \n"); print("Parent PID: ", parent_pid, " \n");
?></pre> ?></pre>
<pre><?= (var_dump(p)) ?></pre> <pre><?= (var_dump(p)) ?></pre>
</> </>

View File

@ -29,14 +29,14 @@ RENDER()
t["l"] = context->params; t["l"] = context->params;
String j; String j;
echo(j = json_encode(t)); print(j = json_encode(t));
?></pre> ?></pre>
Parsed: Parsed:
<pre><? <pre><?
echo(var_dump( print(var_dump(
json_decode(j) json_decode(j)
)); ));
?></pre> ?></pre>
@ -44,7 +44,7 @@ RENDER()
Compare: Compare:
<pre><? <pre><?
echo(var_dump( print(var_dump(
t t
)); ));
?></pre> ?></pre>

View File

@ -17,7 +17,7 @@ RENDER()
auto sfd = memcache_connect(); auto sfd = memcache_connect();
echo(memcache_command(sfd, "stats")); print(memcache_command(sfd, "stats"));
?></pre> ?></pre>
@ -27,9 +27,9 @@ RENDER()
memcache_set(sfd, "test_key", "test_value"); memcache_set(sfd, "test_key", "test_value");
memcache_set(sfd, "test_key2", "test_value2"); memcache_set(sfd, "test_key2", "test_value2");
echo("raw:: "+memcache_command(sfd, "get test_key")+"\n"); print("raw:: "+memcache_command(sfd, "get test_key")+"\n");
echo("get:: "+memcache_get(sfd, "test_key")+"\n"); print("get:: "+memcache_get(sfd, "test_key")+"\n");
echo("multiple::\n"+var_dump(memcache_get_multiple(sfd, {"test_key", "test_key2"}))+"\n"); print("multiple::\n"+var_dump(memcache_get_multiple(sfd, {"test_key", "test_key2"}))+"\n");
?></pre> ?></pre>

View File

@ -21,11 +21,11 @@ RENDER()
MySQL con; MySQL con;
if(con.connect("localhost", "root", "")) if(con.connect("localhost", "root", ""))
{ {
echo("connection established\n"); print("connection established\n");
echo("error: "+con.error()+"\n"); print("error: "+con.error()+"\n");
echo("quotation test: "+con.escape("\"' or 1=1;.")+"\n"); print("quotation test: "+con.escape("\"' or 1=1;.")+"\n");
echo("query parse: "+con.parse_query_parameters(query, params)+"\n"); print("query parse: "+con.parse_query_parameters(query, params)+"\n");
echo(var_dump(con.query("SHOW DATABASES"))); print(var_dump(con.query("SHOW DATABASES")));
con.query("USE mysql"); con.query("USE mysql");
?></pre> ?></pre>
@ -34,7 +34,7 @@ RENDER()
<pre><? <pre><?
echo(var_dump(con.query("SELECT * FROM user"))); print(var_dump(con.query("SELECT * FROM user")));
} }

View File

@ -18,17 +18,17 @@ RENDER()
if(action == "start") if(action == "start")
{ {
session_start(); session_start();
echo("action: starting session"); print("action: starting session");
} }
else if(action == "store") else if(action == "store")
{ {
context->session["stored-value"] = make_session_id(); context->session["stored-value"] = make_session_id();
echo("action: storing value "+context->session["stored-value"]); print("action: storing value "+context->session["stored-value"]);
} }
else if(action == "destroy") else if(action == "destroy")
{ {
session_destroy(); session_destroy();
echo("action: destroying session"); print("action: destroying session");
} }
<> <>
@ -40,9 +40,9 @@ RENDER()
Info Info
<pre><? <pre><?
echo(var_dump(context->cookies)); print(var_dump(context->cookies));
echo("SESSION:\n"); print("SESSION:\n");
echo(var_dump(context->session)); print(var_dump(context->session));
?></pre> ?></pre>
Params Params

27
test/string.uce Normal file
View File

@ -0,0 +1,27 @@
RENDER()
{
DTree t;
<>
<link rel="stylesheet" href='style.css'></link>
<h1>
<a href="index.uce">UCE Test</a>:
Strings
</h1>
<pre style="white-space: pre-wrap"><?
print(String("!") + 60*60*24);
?></pre>
Params
<pre><?= var_dump(context->params) ?></pre>
</>
}

View File

@ -10,7 +10,7 @@ RENDER()
Working Directory Working Directory
</h1> </h1>
<pre><? <pre><?
echo("Base WD: " + get_cwd() + "\n"); print("Base WD: " + get_cwd() + "\n");
context->invoke("test2/working-dir-test.uce"); context->invoke("test2/working-dir-test.uce");
?></pre> ?></pre>
<pre><?= var_dump(context->params) ?></pre> <pre><?= var_dump(context->params) ?></pre>