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) &&
!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.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;
bzero(&complete, sizeof(complete));
complete.header.version = FCGI_VERSION_1;

View File

@ -4,7 +4,7 @@
String process_html_literal(Request* context, SharedUnit* su, String content)
{
String pc;
String HT_START = "context->print(R\"(";
String HT_START = "print(R\"(";
String HT_END = ")\");";
u8 mode = 0;
@ -63,7 +63,7 @@ String process_html_literal(Request* context, SharedUnit* su, String content)
{
pc.append(
HT_END +
"echo(html_escape( " +
"print(html_escape( " +
code_buffer +
" )); " +
HT_START
@ -299,17 +299,17 @@ void compiler_invoke(Request* context, String file_name, DTree& call_param)
if(!su)
{
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)
{
context->header["Content-Type"] = "text/plain";
context->print("Compiler error: "+su->compiler_messages);
print("Compiler error: "+su->compiler_messages);
}
else
{
if(su->compiler_messages.length() > 0)
context->print(su->compiler_messages);
print(su->compiler_messages);
else
{
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 result;
//echo("json_decode_String " + s.substr(i) + "\n");
//print("json_decode_String " + s.substr(i) + "\n");
while(i < s.length())
{
char c = s[i];
if(c == termination_char)
{
i += 1;
//echo("json_decode_String = " + result + "\n");
//print("json_decode_String = " + result + "\n");
return(result);
}
else if(c == '\\')
@ -289,7 +289,7 @@ DTree json_decode_value(String s, u32& i)
String value = "";
json_consume_space(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
{
result.type = 'S';
@ -329,7 +329,7 @@ DTree json_decode_map(String s, u32& i)
result.type = 'M';
String key = "";
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())
{
char c = s[i];
@ -352,7 +352,7 @@ DTree json_decode_map(String s, u32& i)
i += 1;
DTree v = 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]);
result._map[key] = v;
}
@ -372,4 +372,28 @@ DTree json_decode(String s)
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(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);
if(sockfd < 0)
{
echo("SOCKET ERROR (could not open socket)\n");
print("SOCKET ERROR (could not open socket)\n");
perror("SOCKET ERROR ");
return(0);
}
@ -259,7 +259,7 @@ u64 socket_connect(String host, short port)
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 ");
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);
}
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()

View File

@ -3,6 +3,7 @@
#include <list>
#include <vector>
#include <functional>
#include <sstream>
typedef unsigned char u8;
typedef signed char s8;
@ -17,6 +18,30 @@ typedef long long s64;
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 NO_GLOBAL_ARENA_ALLOCATOR;
@ -105,9 +130,6 @@ void operator delete(void * p) throw()
}
#endif
//#define to_String(a) std::to_String(a)
#define echo(s) context->print(s)
typedef std::map<String, String> StringMap;
typedef std::vector<String> StringList;
@ -217,13 +239,21 @@ struct Request {
MemoryArena* request_arena;
String in;
std::vector<std::ostringstream*> ob_stack;
std::ostringstream* ob;
String out;
String err;
bool is_finished = false;
f64 time_init;
f64 time_start;
f64 time_end;
struct Stats {
u32 bytes_written;
} stats;
struct Resources {
std::vector<u64> sockets;
std::vector<void*> mysql_connections;
@ -231,7 +261,9 @@ struct Request {
void invoke(String file_name);
void invoke(String file_name, DTree& call_param);
void print(String s);
void ob_start();
~Request();
};
@ -239,3 +271,11 @@ struct Request {
typedef Request FastCGIRequest;
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.
request.request_arena = request_arena;
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"))
return 0; // OK, continue processing
else
@ -70,12 +72,6 @@ int handle_complete(FastCGIRequest& request) {
request.invoke(request.params["SCRIPT_FILENAME"]);
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)
{
unlink(f.tmp_name);
@ -86,14 +82,6 @@ int handle_complete(FastCGIRequest& request) {
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;
}

View File

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

View File

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

View File

@ -1,4 +1,4 @@
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>
</ul>
<pre><?
echo("Worker PID: "+std::to_string(my_pid)+"\n");
echo("Parent PID: "+std::to_string(parent_pid)+" \n");
print("Worker PID: ", my_pid, "\n");
print("Parent PID: ", parent_pid, " \n");
?></pre>
<pre><?= (var_dump(p)) ?></pre>
</>

View File

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

View File

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

View File

@ -21,11 +21,11 @@ RENDER()
MySQL con;
if(con.connect("localhost", "root", ""))
{
echo("connection established\n");
echo("error: "+con.error()+"\n");
echo("quotation test: "+con.escape("\"' or 1=1;.")+"\n");
echo("query parse: "+con.parse_query_parameters(query, params)+"\n");
echo(var_dump(con.query("SHOW DATABASES")));
print("connection established\n");
print("error: "+con.error()+"\n");
print("quotation test: "+con.escape("\"' or 1=1;.")+"\n");
print("query parse: "+con.parse_query_parameters(query, params)+"\n");
print(var_dump(con.query("SHOW DATABASES")));
con.query("USE mysql");
?></pre>
@ -34,7 +34,7 @@ RENDER()
<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")
{
session_start();
echo("action: starting session");
print("action: starting session");
}
else if(action == "store")
{
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")
{
session_destroy();
echo("action: destroying session");
print("action: destroying session");
}
<>
@ -40,9 +40,9 @@ RENDER()
Info
<pre><?
echo(var_dump(context->cookies));
echo("SESSION:\n");
echo(var_dump(context->session));
print(var_dump(context->cookies));
print("SESSION:\n");
print(var_dump(context->session));
?></pre>
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
</h1>
<pre><?
echo("Base WD: " + get_cwd() + "\n");
print("Base WD: " + get_cwd() + "\n");
context->invoke("test2/working-dir-test.uce");
?></pre>
<pre><?= var_dump(context->params) ?></pre>