allow a request to be processed in a job

Now we allow a request to be passed into a job queue,
and after the job finishes the request is passed into
a controller again. In order to achieve this we have
a requests queue in System, when we put a request
to the job this Request structure is preserved in the
queue and for a new request a new Request is added to
the queue.

while here:
- remove App::Lock()/Unlock(), use scoped locking
- fix: Plugin now has a Call method which takes ModelConnector
  and a logger (used in multithreaded environment)
- BaseThread has a main_model_connector pointer
  to the main (from the main thread) model connector
- the FastCGI structure fcgi_request moved from App to Request
- some methods for handling requests moved from App to Request
- small refactoring in main.cpp
- add Http class (a http client)
This commit is contained in:
2022-07-25 14:21:21 +02:00
parent b2d92b85a0
commit 979ef907fe
65 changed files with 7018 additions and 4437 deletions

View File

@@ -5,7 +5,7 @@
*/
/*
* Copyright (c) 2008-2021, Tomasz Sowa
* Copyright (c) 2008-2022, Tomasz Sowa
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -34,6 +34,7 @@
#include "cat.h"
namespace Winix
{

View File

@@ -167,6 +167,24 @@ void FunctionBase::Clear()
void FunctionBase::ContinueMakePost()
{
// do nothing by default
}
void FunctionBase::ContinueMakeGet()
{
// do nothing by default
}
void FunctionBase::ContinueMakeDelete()
{
// do nothing by default
}
} // namespace Winix

View File

@@ -40,7 +40,6 @@
#include "db/db.h"
#include "core/request.h"
#include "core/config.h"
#include "core/system.h"
#include "core/synchro.h"
#include "notify/notify.h"
#include "core/winixrequest.h"
@@ -116,6 +115,14 @@ public:
virtual void MakeDelete();
virtual void Clear();
/*
* called from the jobs thread
* objects are locked
*/
virtual void ContinueMakePost();
virtual void ContinueMakeGet();
virtual void ContinueMakeDelete();
//void SetConfig(Config * pconfig);
//void SetCur(Cur * pcur);
@@ -130,7 +137,6 @@ public:
protected:
//Config * config;
//Cur * cur;
Db * db; // depracated
//System * system;
Functions * functions;

View File

@@ -50,22 +50,21 @@ FunctionParser::FunctionParser()
}
bool FunctionParser::Parse(Cur * pcur, Db * pdb, Functions * pfunctions, System * psystem)
bool FunctionParser::Parse(Request * request, Dirs * dirs, Functions * functions)
{
db = pdb;
cur = pcur;
system = psystem;
functions = pfunctions;
this->request = request;
this->dirs = dirs;
this->functions = functions;
last_dir = nullptr;
path = cur->request->env_request_uri.c_str();
path = request->env_request_uri.c_str();
status = true;
// IMPROVEME put WINIX_URL_MAX_SIZE to the config
if( cur->request->env_request_uri.size() <= WINIX_URL_MAX_SIZE )
if( request->env_request_uri.size() <= WINIX_URL_MAX_SIZE )
{
if( !cur->request->dir_tab.empty() )
if( !request->dir_tab.empty() )
{
last_dir = cur->request->dir_tab.back();
last_dir = request->dir_tab.back();
PrintCurrentDirs();
if( ParseDirsItemFunction() )
@@ -77,36 +76,74 @@ bool FunctionParser::Parse(Cur * pcur, Db * pdb, Functions * pfunctions, System
else
{
status = false;
cur->request->http_status = Header::status_500_internal_server_error;
request->http_status = Header::status_500_internal_server_error;
log << log1 << "FP: no root directory provided in the request dir_tab" << logend;
}
}
else
{
status = false;
cur->request->http_status = Header::status_414_uri_too_long;
log << log1 << "FP: the URL is too long: " << cur->request->env_request_uri.size() << logend;
request->http_status = Header::status_414_uri_too_long;
log << log1 << "FP: the URL is too long: " << request->env_request_uri.size() << logend;
}
return status;
}
bool FunctionParser::ParseDirs(Request * request, Dirs * dirs)
{
this->request = request;
this->dirs = dirs;
this->functions = nullptr;
last_dir = nullptr;
path = request->env_request_uri.c_str();
status = true;
// IMPROVEME put WINIX_URL_MAX_SIZE to the config
if( request->env_request_uri.size() <= WINIX_URL_MAX_SIZE )
{
if( !request->dir_tab.empty() )
{
last_dir = request->dir_tab.back();
PrintCurrentDirs();
ParseDirs();
}
else
{
status = false;
request->http_status = Header::status_500_internal_server_error;
log << log1 << "FP: no root directory provided in the request dir_tab" << logend;
}
}
else
{
status = false;
request->http_status = Header::status_414_uri_too_long;
log << log1 << "FP: the URL is too long: " << request->env_request_uri.size() << logend;
}
return status;
}
/*
* there should be at least the root directory
*/
void FunctionParser::PrintCurrentDirs()
{
std::vector<Item*>::iterator i = cur->request->dir_tab.begin();
std::vector<Item*>::iterator i = request->dir_tab.begin();
for( ; i != cur->request->dir_tab.end() ; ++i)
for( ; i != request->dir_tab.end() ; ++i)
{
LogDir(*i);
}
}
bool FunctionParser::ParseDirsItemFunction()
void FunctionParser::ParseDirs()
{
ReadName();
@@ -115,6 +152,12 @@ bool FunctionParser::ParseDirsItemFunction()
AddDir();
ReadName();
}
}
bool FunctionParser::ParseDirsItemFunction()
{
ParseDirs();
if( name.empty() )
{
@@ -150,7 +193,7 @@ bool FunctionParser::ParseDirsItemFunction()
if( !CheckAddFunction() )
{
log << log3 << "FP: unknown function: " << name << logend;
cur->request->http_status = Header::status_404_not_found;
request->http_status = Header::status_404_not_found;
status = false;
return false;
}
@@ -167,7 +210,7 @@ bool FunctionParser::IsDir()
if( name.empty() || !last_dir )
return false;
last_dir = system->dirs.GetDir(name, last_dir->id);
last_dir = dirs->GetDir(name, last_dir->id);
return last_dir != nullptr;
}
@@ -175,8 +218,8 @@ bool FunctionParser::IsDir()
bool FunctionParser::CheckAddItem()
{
// cur->request->dir_tab has at least one element
long parent_id = cur->request->dir_tab.back()->id;
// request->dir_tab has at least one element
long parent_id = request->dir_tab.back()->id;
morm::Finder<Item> finder(model_connector);
finder.
@@ -184,33 +227,36 @@ bool FunctionParser::CheckAddItem()
where().
eq(L"parent_id", parent_id).
eq(L"url", name).
get(cur->request->item);
get(request->item);
if( cur->request->item.found() )
if( request->item.found() )
{
log << log3 << "FP: Item: id: " << cur->request->item.id << ", url: " << cur->request->item.url << logend;
cur->request->last_item = &cur->request->item;
cur->request->is_item = true;
log << log3 << "FP: Item: id: " << request->item.id << ", url: " << request->item.url << logend;
request->last_item = &request->item;
request->is_item = true;
}
else
{
log << log3 << "FP: No Item: url: " << name << logend;
cur->request->http_status = Header::status_404_not_found;
request->http_status = Header::status_404_not_found;
status = false;
}
return cur->request->item.found();
return request->item.found();
}
bool FunctionParser::CheckAddFunction()
{
cur->request->function = functions->Find(name);
if( cur->request->function )
if( functions )
{
log << log3 << "FP: Function: " << cur->request->function->fun.url << logend;
request->function = functions->Find(name);
}
if( request->function )
{
log << log3 << "FP: Function: " << request->function->fun.url << logend;
return true;
}
@@ -231,9 +277,9 @@ void FunctionParser::LogDir(Item * dir)
void FunctionParser::AddDir()
{
cur->request->dir_tab.push_back(last_dir);
request->dir_tab.push_back(last_dir);
LogDir(last_dir);
cur->request->last_item = cur->request->dir_tab.back();
request->last_item = request->dir_tab.back();
}
@@ -302,7 +348,7 @@ void FunctionParser::AddParam()
{
param.name = name;
param.value = value;
cur->request->param_tab.push_back(param);
request->param_tab.push_back(param);
log << log3 << "FP: Param: name=" << param.name;
@@ -323,15 +369,15 @@ void FunctionParser::ParseAnchor()
while( *path )
name_ascii += GetChar();
pt::utf8_to_wide(name_ascii, cur->request->anchor);
pt::utf8_to_wide(name_ascii, request->anchor);
if( !cur->request->anchor.empty() )
log << log3 << "FP: anchor: " << cur->request->anchor << logend;
if( !request->anchor.empty() )
log << log3 << "FP: anchor: " << request->anchor << logend;
}
else
if( *path != 0 )
{
cur->request->http_status = Header::status_400_bad_request;
request->http_status = Header::status_400_bad_request;
status = false;
}
}
@@ -362,7 +408,7 @@ int FunctionParser::FromHex(int c)
}
else
{
cur->request->http_status = Header::status_400_bad_request;
request->http_status = Header::status_400_bad_request;
status = false;
}
@@ -383,7 +429,7 @@ int c;
if( c == 0 && status )
{
cur->request->http_status = Header::status_400_bad_request;
request->http_status = Header::status_400_bad_request;
status = false;
}

View File

@@ -5,7 +5,7 @@
*/
/*
* Copyright (c) 2008-2021, Tomasz Sowa
* Copyright (c) 2008-2022, Tomasz Sowa
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -40,7 +40,7 @@
#include "core/winixmodeldeprecated.h"
#include "db/db.h"
#include "core/cur.h"
#include "core/system.h"
#include "core/dirs.h"
namespace Winix
@@ -60,13 +60,15 @@ public:
/*
* if the method returns false then cur->request->http_status will be already set to a specific error
*/
bool Parse(Cur * pcur, Db * pdb, Functions * pfunctions, System * psystem);
bool Parse(Request * request, Dirs * dirs, Functions * functions);
bool ParseDirs(Request * request, Dirs * dirs);
private:
Db * db;
Cur * cur;
System * system;
Request * request;
Dirs * dirs;
Functions * functions;
const wchar_t * path;
@@ -79,6 +81,7 @@ private:
void SkipSlashes();
void PrintCurrentDirs();
void ParseDirs();
bool ParseDirsItemFunction();
void ParseParams();
void ParseAnchor();

View File

@@ -170,6 +170,7 @@ Error Functions::CheckSpecialFile(const Item & item)
cur->mount = system->mounts.GetEmptyMount();
system->mounts.ReadMounts(item.item_content.content_raw);
system->mounts.CalcCurMount(cur->request);
cur->mount = system->mounts.pmount;
templates->ReadNewIndexTemplates();
templates->ReadNewChangeTemplates();
@@ -275,7 +276,7 @@ void Functions::CreateFunctions()
Add(fun_who);
Add(fun_vim);
plugin->Call((Session*)0, WINIX_CREATE_FUNCTIONS);
plugin->Call(WINIX_CREATE_FUNCTIONS);
}
@@ -312,10 +313,15 @@ void Functions::Finish()
bool Functions::Parse()
{
return function_parser.Parse(cur, db, this, system);
return function_parser.Parse(cur->request, &system->dirs, this);
}
bool Functions::ParseOnlyDirs()
{
return function_parser.ParseDirs(cur->request, &system->dirs);
}
void Functions::SetDefaultFunctionForFile()
{
@@ -494,6 +500,56 @@ void Functions::MakeFunction()
}
void Functions::ContinueMakeFunction()
{
if( !cur->request->function )
{
cur->request->status = WINIX_ERR_NO_FUNCTION;
log << log1 << "Functions: no function (neither cat nor ls)" << logend;
return;
}
// if( !system->DirsHaveReadExecPerm() ||
// !system->HasReadExecAccess(cur->request->function->fun) ||
// !cur->request->function->HasAccess() )
// {
// cur->request->status = WINIX_ERR_PERMISSION_DENIED;
// return;
// }
if( cur->request->method == Request::get )
{
log << log4 << "Functions: continuing method get for request " << cur->request
<< " for function " << cur->request->function->fun.url << logend;
cur->request->function->ContinueMakeGet();
}
else
if( cur->request->method == Request::post )
{
log << log4 << "Functions: continuing method post for request " << cur->request
<< " for function " << cur->request->function->fun.url << logend;
cur->request->function->ContinueMakePost();
}
else
if( cur->request->method == Request::head )
{
// do nothing
// !! IMPROVE ME
// we should make a page similar like in a GET request but the content should not be returned only
}
else
if( cur->request->method == Request::delete_ )
{
log << log4 << "Functions: continuing method delete for request " << cur->request
<< " for function " << cur->request->function->fun.url << logend;
cur->request->function->ContinueMakeDelete();
}
else
{
log << log1 << "Functions: cannot continue a request, unknown request method (skipping)" << logend;
}
}

View File

@@ -5,7 +5,7 @@
*/
/*
* Copyright (c) 2010-2018, Tomasz Sowa
* Copyright (c) 2010-2022, Tomasz Sowa
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -151,6 +151,7 @@ public:
void Init();
void Finish();
bool Parse();
bool ParseOnlyDirs();
size_t FunctionsSize();
Iterator Begin();
@@ -159,6 +160,12 @@ public:
void CheckFunctionAndSymlink();
void MakeFunction();
/*
* this function is called from the jobs thread
* objects are locked
*/
void ContinueMakeFunction();
//void SetConfig(Config * pconfig);
void SetCur(Cur * pcur);