The project Brook framework was moved to: risoflora/brookframework.
If you want Brook only for Free Pascal, it was moved to: risoflora/brookfreepascal.
Microframework which helps to develop web Pascal applications.
Home Page: https://github.com/risoflora/brookframework
License: GNU Lesser General Public License v3.0
The project Brook framework was moved to: risoflora/brookframework.
If you want Brook only for Free Pascal, it was moved to: risoflora/brookfreepascal.
boa tarde, a horas estou tentando fazer este simples código funcionar, mesmo o CHome.Content estar apenas sendo referenciado a variavel VPgInterna, e em nenhum lugar mais, ele aparece na saida, acredito que seja pelo .Content do CHome, se eu comento //VPgInterna := CHome.Content; ou faço assim VPgInterna := ''; tudo volta ao normal, por isso acredito que seja alguma problema com a palavra content, abaixo um exemplo de código.
Good afternoon, the hours I'm trying to make this simple code to work, even just being CHome.Content be referenced variable VPgInterna, and nowhere else, it appears in the output, I believe it is the . The Content CHome if I comment / / VPgInterna: = CHome.Content, or do so VPgInterna: =''; everything back
to normal, so I think it's some problem with the word content, below a sample code.
Templ := TJTemplate.Create;
Templ.HTMLSupports := False;
Templ.LoadFromFile(ANIVEL_ACIMA+AROOT_DIR_HTML+'index.html');
VPgInterna := CHome.Content;
Templ.Fields.Add('centro', '');
//Templ.Replace(False);
try
Write(Templ.Content);
finally
Templ.Free;
end;
Please create a plugin manager, like "Notepad ++ plugin manager":
http://brookframework.org/plgman.png
In Brook, it will download and install Brook plugins, like QTemplate, XMailer etc.
Upon install, the following error occurs.
fpweb has fpwebfile that defines default request for static files. I currently define my own action for this:
unit Static;
{$mode objfpc}{$H+}
interface
uses
Classes, SysUtils, HTTPDefs, BrookAction;
type
{ TStaticFileAction }
TStaticFileAction = class(TBrookAction)
private
FMimeType: String;
public
procedure Request(ARequest: TRequest; AResponse: TResponse); override;
procedure Get; override;
end;
implementation
uses
AppUtils, // for RelativeToAbsolute below
fpmimetypes;
{ TStaticFileAction }
procedure TStaticFileAction.Request(ARequest: TRequest; AResponse: TResponse);
begin
inherited Request(ARequest,AResponse);
AResponse.ContentType := FMimeType;
end;
procedure TStaticFileAction.Get;
var
FilePath: String;
begin
FilePath := RelativeToAbsolute(
IncludeTrailingPathDelimiter(Values['dir'].AsString) +
Values['file'].AsString
);
if FileExists(FilePath) then
with TStringList.Create do
try
LoadFromFile(FilePath);
FMimeType := MimeTypes.GetMimeType(ExtractFileExt(FilePath));
Write(Text);
finally
Free;
end;
end;
initialization
MimeTypes.LoadFromFile('mime.types');
TStaticFileAction.Register('/static/:dir/:file');
end.
Is there any better way?
Hello,
Please update all the experts to use the new leledumbo's broker (3471703). Below two pictures showing as would be:
1 - http://imagebin.org/241331
2 - http://imagebin.org/241332
So, these names chosen (Embedded HTTP etc.) are good?
Thank you!
Hi,
I want to intercept before each request and if the session is expired show a session expired page, I sort of have this working by creating a new class where I override the DoBeforeRequest and then my new actions are created from the "base" session class.
This works and the DoBeforeRequest fires and I can check if the session is expired, the problem is when I do a redirect in DoBeforeRequest the actual dorequest still fires and it never redirects to the session expired page.
procedure TSessionAction.DoBeforeRequest(ARequest: TRequest;
AResponse: TResponse);
var
path:string;
begin
path:=ARequest.PathInfo;
if path = '/logon' then
exit;
fsession.Start(GetRequest);
//if the session is expired redirect to session timeout page
if (FSession.IsExpired) then
Redirect(UrlFor(TSessionExpired, []),301);
end;
In current implementation when error page is hit, the framework first checks presence of template file, and only after that fall back to literal string, see brookfclhttpappbroker.pas#L152-L165
There are two problems with it:
Now BrookSettings.Page404
and BrookSettings.Page500
are empty if programmer not define them. I think framework should provide some meaningful defaults to them, like in demo projects: <html>[...]<h1>500 - Internal server error</h1>[...]</html>
.
Also separate settings could be used for naming template files, for example
BrookSettings.Page404File
and BrookSettings.Page500File
with default to empty string.
It would be much better this way. If programmer define Page500File
, but the file is not found, framework will have a chance to respond with meaningful text to visitors using Page500
string. And FileExists()
check could be easily skipped if Page500File
is not defined.
The demo website allows inserting unsafe code into the demo database.
I entered a obviously bogus script attack <script>alert('hi');</script>
and it executes at least on these urls:
http://brookframework.org/demos/db/jeasyui/grid.html
http://brookframework.org/demos/db/crud/cgi1.bf/person
(i removed this bugus item after testing and reporting bug)
Complete Newbie to Web Apps!
First I installed IIS on (Win7Pro virtual on PowerMac)
Then installed lazarus 1.08 (fpc2.6.2) and followed your Getting Started Guide
Compiled cgi1 demo and copied cgi1.o to a cgi-bin folder which I added to
C:\inetpub\wwwroot\cgi-bin\cgi.o
In IE I called http://localhost/cgi-bin/cgi1 but get an error
HTTP Error 404.0 - Not Found
The resource you are looking for has been removed, had its name changed, or is temporarily unavailable.
Can someone please tell me my stupid mistake?
Thanks
In delphi to create a webserver was the ability to use templates with labels {mytag} that helped replace them with values or objects.
Brookframework does the hard work, but to generate a beautiful web, it takes much work to code. You can do that using php generate templates or to improve the appearance?
En delphi al crear un webserver se tenia la posibilidad de usar plantillas con etiquetas {mytag} que ayudaban a reemplazarlas por valores u objetos.
Brookframework hace el trabajo duro pero para generar una pagina bella lleva mucho trabajo por codigo. Se puede hacer que el uso de plantillas o generar php para mejorar el aspecto?
When adding to input html/xml code (such as ), it does not escape the code, and embed it inside as it was a javascript code.
I expect any input to have been escaped to the literal representer with HTML, unless it was configured to that specific location to keep it "as-is".
This the idea I would always to have since fpweb times, and now I want to bring it to Brook. So in this scenario, the actions have the following inheritance:
OuterAction <|-- InnerAction <|-- RealAction
where RealAction is the only action that gets registered in the route. When the action is executed, OuterAction draws OuterFrame, followed by InnerAction that draws InnerFrame, and finally RealAction draws the content. This way, the number of code to write the outer and inner frame can be reduced to just one instead of having them in all actions, even if they're just a line or two. It's also more maintainable, single change in the outer/inner action would affect the other real actions.
Both OuterAction and InnerAction may have variable values that can be assigned from RealAction, with those values displayed in respective frames. For instance, OuterAction may have Location property that will be shown on other frame to show where the user is at the moment. So is InnerAction, for instance it has ActiveMenu property that will be drawn with different colors.
I'm working on a unit that I'm using in my project. Soon I'll make it part of Brook. The unit will be called BrookDBConstraints (may be used by BrookDBActions or BrookRESTActions), with the following features:
- TBrookDBConstraintDefault
- TBrookDBConstraintCheck
- TBrookDBConstraintNotNull
- TBrookDBConstraintUnique
- TBrookDBConstraintForeignKey
I have this unit and it is already in testing, and is working perfectly fine. But I need some time to check if it need to make changes in the modeling.
Two nice examples showing the usage:
unit statementactns;
{$i webcontas.inc}
interface
uses
BrookJSONHelper, authrestactns, dbconstraints;
type
{ TStatementDBConstraintCheck }
TStatementDBConstraintCheck = class(TDBConstraintCheck)
public
procedure Execute; override;
end;
{ TStatementDBConstraintNotNull }
TStatementDBConstraintNotNull = class(TDBConstraintNotNull)
public
procedure Execute; override;
end;
{ TStatementDBConstraintUnique }
TStatementDBConstraintUnique = class(TDBConstraintUnique)
public
procedure Execute; override;
end;
{ TStatementBankDBConstraintForeignKey }
TStatementBankDBConstraintForeignKey = class(TDBConstraintForeignKey)
public
class function GetDetails: TForeignKeyDetails; override;
procedure Execute; override;
end;
{ TStatementFinCategoryDBConstraintForeignKey }
TStatementFinCategoryDBConstraintForeignKey = class(TDBConstraintForeignKey)
public
class function GetDetails: TForeignKeyDetails; override;
procedure Execute; override;
end;
{ TStatementParticipantDBConstraintForeignKey }
TStatementParticipantDBConstraintForeignKey = class(TDBConstraintForeignKey)
public
class function GetDetails: TForeignKeyDetails; override;
procedure Execute; override;
end;
{ TStatementCostCentreDBConstraintForeignKey }
TStatementCostCentreDBConstraintForeignKey = class(TDBConstraintForeignKey)
public
class function GetDetails: TForeignKeyDetails; override;
procedure Execute; override;
end;
{ TStatementBusinessDBConstraintForeignKey }
TStatementBusinessDBConstraintForeignKey = class(TDBConstraintForeignKey)
public
class function GetDetails: TForeignKeyDetails; override;
procedure Execute; override;
end;
{ TStatementOptionsAction }
TStatementOptionsAction = class(TAuthOptionsAction)
end;
{ TStatementRetrieveAction }
TStatementRetrieveAction = class(TAuthRetrieveAction)
end;
{ TStatementShowAction }
TStatementShowAction = class(TAuthShowAction)
end;
{ TStatementCreateAction }
TStatementCreateAction = class(TAuthCreateAction)
end;
{ TStatementUpdateAction }
TStatementUpdateAction = class(TAuthUpdateAction)
end;
{ TStatementDestroyAction }
TStatementDestroyAction = class(TAuthDestroyAction)
end;
implementation
{ TStatementDBConstraintCheck }
procedure TStatementDBConstraintCheck.Execute;
begin
Assert(Action.Fields.Exists('repeatingCycle') and
(Action.Fields['repeatingCycle'].AsChar in ['N', 'D', 'W', 'M', 'B', 'Y']),
'Ciclo de recorrencia não pode ser diferente de N, D, W, M, B ou Y.');
Assert(Action.Fields.Exists('type') and
(Action.Fields['type'].AsChar in ['E', 'R']),
'Tipo não pode ser diferente de E ou R.');
end;
{ TStatementDBConstraintNotNull }
procedure TStatementDBConstraintNotNull.Execute;
begin
Assert('memo', 'Memo não pode ser nulo ou vazio.', True);
Assert('value', 'Valor não pode ser nulo.', True);
Assert('date', 'Data não pode ser nula.', True);
Assert('repeat', 'Recorrencia não pode ser nula.', True);
Assert('done', 'Pago não pode ser nulo.', True);
end;
{ TStatementDBConstraintUnique }
procedure TStatementDBConstraintUnique.Execute;
begin
Assert(['bankAccountId', 'financeCategoryId', 'participantId', 'costCentreId',
'businessId'], 'Lançamento já registrado.');
end;
{ TStatementBankDBConstraintForeignKey }
class function TStatementBankDBConstraintForeignKey.GetDetails: TForeignKeyDetails;
begin
with Result do
begin
TableDescription := 'Lançamento financeiro';
ReferencedTableName := 'bankAccount';
end;
end;
procedure TStatementBankDBConstraintForeignKey.Execute;
begin
Assert('statement', 'bankAccountId', 'id', 'Conta bancária não registrada.');
end;
{ TStatementFinCategoryDBConstraintForeignKey }
class function TStatementFinCategoryDBConstraintForeignKey.GetDetails: TForeignKeyDetails;
begin
with Result do
begin
TableDescription := 'Lançamento financeiro';
ReferencedTableName := 'financeCategory';
end;
end;
procedure TStatementFinCategoryDBConstraintForeignKey.Execute;
begin
Assert('statement', 'financeCategoryId', 'id',
'Categoria financeira não registrada.');
end;
{ TStatementParticipantDBConstraintForeignKey }
class function TStatementParticipantDBConstraintForeignKey.GetDetails: TForeignKeyDetails;
begin
with Result do
begin
TableDescription := 'Lançamento financeiro';
ReferencedTableName := 'participant';
end;
end;
procedure TStatementParticipantDBConstraintForeignKey.Execute;
begin
Assert('statement', 'participantId', 'id', 'Participante não registrado.');
end;
{ TStatementCostCentreDBConstraintForeignKey }
class function TStatementCostCentreDBConstraintForeignKey.GetDetails: TForeignKeyDetails;
begin
with Result do
begin
TableDescription := 'Lançamento financeiro';
ReferencedTableName := 'costcentre';
end;
end;
procedure TStatementCostCentreDBConstraintForeignKey.Execute;
begin
Assert('statement', 'costCentreId', 'id', 'Centro de custo não registrado.');
end;
{ TStatementBusinessDBConstraintForeignKey }
class function TStatementBusinessDBConstraintForeignKey.GetDetails: TForeignKeyDetails;
begin
with Result do
begin
TableDescription := 'Lançamento financeiro';
ReferencedTableName := 'business';
end;
end;
procedure TStatementBusinessDBConstraintForeignKey.Execute;
begin
Assert('statement', 'businessId', 'id', 'Negócio não registrado.');
end;
initialization
TStatementOptionsAction.Register('statement', '/statement');
TStatementRetrieveAction.Register('statement', '/statement');
TStatementShowAction.Register('statement', '/statement/:id');
TStatementCreateAction.Register('statement', '/statement');
TStatementUpdateAction.Register('statement', '/statement/:id');
TStatementDestroyAction.Register('statement', '/statement/:id');
TStatementCreateAction.RegisterDBConstraint(TStatementDBConstraintNotNull);
TStatementCreateAction.RegisterDBConstraint(TStatementDBConstraintUnique);
TStatementCreateAction.RegisterDBConstraint(TStatementBankDBConstraintForeignKey);
TStatementCreateAction.RegisterDBConstraint(TStatementFinCategoryDBConstraintForeignKey);
TStatementCreateAction.RegisterDBConstraint(TStatementParticipantDBConstraintForeignKey);
TStatementCreateAction.RegisterDBConstraint(TStatementCostCentreDBConstraintForeignKey);
TStatementCreateAction.RegisterDBConstraint(TStatementBusinessDBConstraintForeignKey);
TStatementUpdateAction.RegisterDBConstraint(TStatementDBConstraintNotNull);
TStatementUpdateAction.RegisterDBConstraint(TStatementDBConstraintUnique);
TStatementUpdateAction.RegisterDBConstraint(TStatementBankDBConstraintForeignKey);
TStatementUpdateAction.RegisterDBConstraint(TStatementFinCategoryDBConstraintForeignKey);
TStatementUpdateAction.RegisterDBConstraint(TStatementParticipantDBConstraintForeignKey);
TStatementUpdateAction.RegisterDBConstraint(TStatementCostCentreDBConstraintForeignKey);
TStatementUpdateAction.RegisterDBConstraint(TStatementBusinessDBConstraintForeignKey);
end.
unit participantactns;
{$i webcontas.inc}
interface
uses
BrookJSONHelper, authrestactns, dbconstraints;
type
{ TParticipantDBConstraintCheck }
TParticipantDBConstraintCheck = class(TDBConstraintCheck)
public
procedure Execute; override;
end;
{ TParticipantDBConstraintNotNull }
TParticipantDBConstraintNotNull = class(TDBConstraintNotNull)
public
procedure Execute; override;
end;
{ TParticipantDBConstraintUnique }
TParticipantDBConstraintUnique = class(TDBConstraintUnique)
public
procedure Execute; override;
end;
{ TParticipantDBConstraintForeignKey }
TParticipantDBConstraintForeignKey = class(TDBConstraintForeignKey)
public
class function GetDetails: TForeignKeyDetails; override;
procedure Execute; override;
end;
{ TParticipantOptionsAction }
TParticipantOptionsAction = class(TAuthOptionsAction)
end;
{ TParticipantRetrieveAction }
TParticipantRetrieveAction = class(TAuthRetrieveAction)
end;
{ TParticipantShowAction }
TParticipantShowAction = class(TAuthShowAction)
end;
{ TParticipantCreateAction }
TParticipantCreateAction = class(TAuthCreateAction)
end;
{ TParticipantUpdateAction }
TParticipantUpdateAction = class(TAuthUpdateAction)
end;
{ TParticipantDestroyAction }
TParticipantDestroyAction = class(TAuthDestroyAction)
end;
implementation
{ TParticipantDBConstraintCheck }
procedure TParticipantDBConstraintCheck.Execute;
begin
Assert(Action.Fields.Exists('type') and
(Action.Fields['type'].AsChar in ['C', 'V', 'S', 'P']),
'Tipo não pode ser diferente de C, V, S ou P.');
end;
{ TParticipantDBConstraintNotNull }
procedure TParticipantDBConstraintNotNull.Execute;
begin
Assert('name', 'Nome não pode ser nulo ou vazio.', True);
Assert('documentNumber', 'CPF/CNPJ não pode ser nulo ou vazio.', True);
Assert('type', 'Tipo não pode ser nulo ou vazio.', True);
end;
{ TParticipantDBConstraintUnique }
procedure TParticipantDBConstraintUnique.Execute;
begin
Assert('email', 'E-mail já registrado.');
Assert(['documentNumber', 'stateRegistration'],
'CPF/CNPJ e inscrição estadual já registrados.');
Assert('address', 'Endereço já registrado.');
end;
{ TParticipantDBConstraintForeignKey }
class function TParticipantDBConstraintForeignKey.GetDetails: TForeignKeyDetails;
begin
with Result do
begin
TableDescription := 'Participante';
ReferencedTableName := 'city';
end;
end;
procedure TParticipantDBConstraintForeignKey.Execute;
begin
Assert('participant', 'cityId', 'id', 'Cidade não registrada.');
end;
initialization
TParticipantOptionsAction.Register('participant', '/city/participant');
TParticipantRetrieveAction.Register('participant', '/city/:cityid/participant');
TParticipantShowAction.Register('participant', '/city/:cityid/participant/:id');
TParticipantCreateAction.Register('participant', '/city/:cityid/participant');
TParticipantUpdateAction.Register('participant', '/city/:cityid/participant/:id');
TParticipantDestroyAction.Register('participant', '/city/:cityid/participant/:id');
TParticipantOptionsAction.Register('participant', '/participant');
TParticipantRetrieveAction.Register('participant', '/participant');
TParticipantShowAction.Register('participant', '/participant/:id');
TParticipantCreateAction.Register('participant', '/participant');
TParticipantUpdateAction.Register('participant', '/participant/:id');
TParticipantDestroyAction.Register('participant', '/participant/:id');
TParticipantCreateAction.RegisterDBConstraint(TParticipantDBConstraintCheck);
TParticipantCreateAction.RegisterDBConstraint(TParticipantDBConstraintNotNull);
TParticipantCreateAction.RegisterDBConstraint(TParticipantDBConstraintUnique);
TParticipantCreateAction.RegisterDBConstraint(TParticipantDBConstraintForeignKey);
TParticipantUpdateAction.RegisterDBConstraint(TParticipantDBConstraintCheck);
TParticipantUpdateAction.RegisterDBConstraint(TParticipantDBConstraintNotNull);
TParticipantUpdateAction.RegisterDBConstraint(TParticipantDBConstraintUnique);
TParticipantUpdateAction.RegisterDBConstraint(TParticipantDBConstraintForeignKey);
end.
I tried to install it on my Ubuntu 12.10/Lazarus 1.04 but it fails to install.
Here is the message
/home/spottymickey/lazarusprj/brookfrm/brookframework-master/brokers/brookfclcgibroker.pas(57,15) Error: There is no method in an ancestor class to be overridden: "TBrookCGIRequest.DeleteTempUploadedFiles;"
/home/spottymickey/lazarusprj/brookfrm/brookframework-master/brokers/brookfclcgibroker.pas(58,14) Error: There is no method in an ancestor class to be overridden: "TBrookCGIRequest.GetTempUploadFileName(const AnsiString,const AnsiString,Int64):AnsiString;"
/home/spottymickey/lazarusprj/brookfrm/brookframework-master/brokers/brookfclcgibroker.pas(60,14) Error: There is no method in an ancestor class to be overridden: "TBrookCGIRequest.RequestUploadDir:AnsiString;"
/home/spottymickey/lazarusprj/brookfrm/brookframework-master/brokers/brookfclcgibroker.pas(62,15) Error: There is no method in an ancestor class to be overridden: "TBrookCGIRequest.HandleUnknownEncoding(const AnsiString,TStream);"
/home/spottymickey/lazarusprj/brookfrm/brookframework-master/brokers/brookfclcgibroker.pas(85,1) Fatal: There were 4 errors compiling module, stopping
Hi,
with Lazarus 1.0.7 r40538 FPC 2.6.1 x86_64-linux-gtk 2
if I open the BrookEK package an compile, I get
../ideintf/frmbrooktable2htmlform.pas(29,19) Fatal: Can not find unit ListFilterEdit used by frmBrookTable2HTMLForm. Check if package LazControls is in the dependencies.
It would be interesting to Brook have a broker or plugin implementing the Amazon's S3 service.
I added support for fcl-web's embedded HTTP server here:
https://github.com/leledumbo/brookframework/commit/20ac331d090c47264c88b2852d022db63f3f78e4
It somewhat works, but I still face an exception on request completion:
#0 fpc_raiseexception at :0
#1 TBROOKROUTER__ROUTE(0xb7d8f020, 0xb7d87020, <error reading variable>) at /media/Sources/lazarus-fpc/git/brookframework/core/brookrouter.pas:602
#2 TBROOKHTTPSERVERHANDLER__HANDLEREQUEST(0xb7d8f020, 0xb7d87020, <error reading variable>) at /media/Sources/lazarus-fpc/git/brookframework/brokers/brookfclhttpappbroker.pas:112
#3 DOHANDLEREQUEST(0xb7daf020, 0xb7d8f020, 0xb7d87020) at custweb.pp:470
#4 HTTPHANDLEREQUEST(0xb7daf020, 0xb7da7020, 0xb7d8f020, 0xb7d87020) at custhttpapp.pp:202
#5 HANDLEREQUEST(0xb7da7020, 0xb7d8f020, 0xb7d87020) at fphttpserver.pp:734
#6 HANDLEREQUEST(0xb7fd33c0) at fphttpserver.pp:539
#7 DOCONNECT(0xb7da7020, 0xb7db7080, 0xb7e0f110) at fphttpserver.pp:694
#8 SSOCKETS$_$TSOCKETSERVER_$__$$_DOCONNECT$TSOCKETSTREAM at :0
#9 ?? at :0
#10 STARTSERVERSOCKET(0xb7da7020) at fphttpserver.pp:721
#11 SETACTIVE(0xb7da7020, true) at fphttpserver.pp:608
#12 RUN(0xb7daf020) at custhttpapp.pp:276
#13 DORUN(0xb7db7020) at custweb.pp:635
#14 CUSTAPP$_$TCUSTOMAPPLICATION_$__$$_RUN at :0
#15 TBROOKAPPLICATION__RUN(<error reading variable>) at /media/Sources/lazarus-fpc/git/brookframework/brokers/brookfclhttpappbroker.pas:86
#16 main at test.lpr:9
The exception can be skipped and the application still runs, thanks to latest update from Michael Van Canneyt on the embedded HTTP server. Could you take a look?
Update brookgreyhoundrt.lpk using the new Greyhound package name.
Please add the Port property in TBrookSettings.
I convert the blog demo into fastcgi project, replacing hardcoded link in the form action of newpost.html template into /post/. The problem is after I press the post button, I got empty page. The data does get in to the database though. Quick investigation shows that this piece of code:
procedure TPost.Post;
begin
Table.Insert(Fields).Apply;
Redirect(UrlFor(THome), BROOK_HTTP_STATUS_CODE_FOUND);
end;
cause the problem because UrlFor(THome) returns empty string.
It would be nice if the Brook actions had the Files
property, to be able to use something like:
procedure TMyAction.Post;
begin
Files.First.Save('doc.pdf');
end;
or:
procedure TMyAction.Post;
begin
Write(Files.First.AsBase64)
end;
Etc. etc. etc.
Would be nice if you could configure the project port in TBrookSettings, e.g:
unit Brokers;
{$mode objfpc}{$H+}
interface
uses
BrookFCLHTTPAppBroker, BrookUtils;
implementation
initialization
BrookSettings.Port := 8080;
end.
Exception at 080AAAFA: Exception:
Failed to open input-handle passed from server. Socket Error: 88.
Lazarus 1.1 r38762 FPC 2.7.1 rXXXX (about 1 month old)
Perhaps I've missed it in the docs, getting started, README.markdown, but I cannot seem to understand how to install this framework. I'd prefer to use it with Lazarus, if that matters.
clear enough? XD
It would be nice if you could choose which table fields it would ignored in the operations as open, insert, edit and delete.
I am trying to make simple HTTP server with brook framework and use helloworld\embeddedserver
example.
When I enable threads support in brokers.pas
,
initialization
TBrookHTTPApplication(BrookApp.Instance).Threaded := true;
the server constantly fails down with exception if concurrent request is run simultaneously.
This bug is obviously caused by TBrookRouter
implementation, where FCurrentAction
is saved as object field. Instead it should be local to the thread, so procedure TBrookRouter.Route
should reads something like
procedure TBrookRouter.Route(ARequest: TRequest; AResponse: TResponse);
var
{...}
AAction:TBrookAction;
begin
{...}
try
AAction := DoCreateAction(VActClass);
DoExecuteAction(AAction, ARequest, AResponse, VNames, VValues);
finally
DoFreeAction(AAction);
end;
end;
FCurrentRoute
variable is also meaningless under threaded environment, but at least its value is never used anywhere.
Currently action routing supports such syntax:
Single-part asterisk seems redundant to me, because you can always replace it with
/more/*/all → /more/:dummy/all and do not use value of dummy parameter.
Multi-part asterisk implementation is buggy, because it doesn't check suffix,
so /file/x-files/top-secret.pdf/denyaccess will also match /file//download** pattern. Besides being buggy, it is nearly useless, because action should parse whole URL to extract pathname of file. It would be great if the action somehow received x-files/top-secret.pdf as a parameter.
I propose slightly adjust router syntax:
(this is much like http://backbonetutorials.com/what-is-a-router/)
With such modification asterisk will match anything after /file/
and place substring to parameter named path
. So Action could easily use path
and open needed file.
I could push some modifications right now, but we already have a lot of commits in working branch so I better hold down before current changes will be merged to master branch.
In the ADS databases, the deleted records are not physically deleted but are marked for subsequent deletion or recovery. There are settings for these marked records are not displayed to the user. This problem occurs in the ADS Broker that did not provide this situation. I performed a adjust in file brookadsbroker.pas (link bellow) to fix this issue. The tests were performed using Lazarus 1.1/FPC 2.71 running on Windows 32 bits.
link: https://www.dropbox.com/s/mdqfassr40e354u/adsbroker_fix.zip
Would be nice if the embedded server was started with the operating system.
Thank you!
Please see:
I don't know if it's bug in Brook or FCL, we need to test it.
Lazarus 1.0.8 r40573 FPC 2.6.2 i386-win32-win32/win64
A simple project generated by wizard Embedded daemon server.
I'm studing for understand...
Only start, make Get and stop service.
C:\Projetos\testes\brook\project1.exe --run
Heap dump by heaptrc unit
153 memory blocks allocated : 5120/5544
139 memory blocks freed : 4448/4856
14 unfreed memory blocks : 672
True heap size : 655360
True free heap : 653600
Should be : 653776
Call trace for block $018C9A90 size 40
$004308AA TBROOKHTTPDAEMON__START, line 112 of C:/lazarus/components/brook/brokers/brookfclhttpdaemonbroker.pas
$00435C56
Call trace for block $002D8618 size 68
$004360CC
$00434853
$004351DC
$0044C794 of C:/lazarus/components/brook/core/brookhttputils.pas
$00430808 TBROOKDAEMONAPPLICATION__RUN, line 97 of C:/lazarus/components/brook/brokers/brookfclhttpdaemonbroker.pas
$00401A5C main, line 11 of project1.lpr
$0040F0E1
Call trace for block $002D8588 size 72
$00434853
$004351DC
$0044C794 of C:/lazarus/components/brook/core/brookhttputils.pas
$00430808 TBROOKDAEMONAPPLICATION__RUN, line 97 of C:/lazarus/components/brook/brokers/brookfclhttpdaemonbroker.pas
$00401A5C main, line 11 of project1.lpr
$0040F0E1
Call trace for block $00348838 size 108
$00435375
$0043539F
$004351DC
$0044C794 of C:/lazarus/components/brook/core/brookhttputils.pas
$00430808 TBROOKDAEMONAPPLICATION__RUN, line 97 of C:/lazarus/components/brook/brokers/brookfclhttpdaemonbroker.pas
$00401A5C main, line 11 of project1.lpr
$0040F0E1
Call trace for block $002C1B58 size 16
$0041FF2D
$00436530
$0043623B
$004357DC
$0042003B
$004347FB
$0044C794 of C:/lazarus/components/brook/core/brookhttputils.pas
$00430808 TBROOKDAEMONAPPLICATION__RUN, line 97 of C:/lazarus/components/brook/brokers/brookfclhttpdaemonbroker.pas
Call trace for block $002C8848 size 36
$0043623B
$004357DC
$0042003B
$004347FB
$0044C794 of C:/lazarus/components/brook/core/brookhttputils.pas
$00430808 TBROOKDAEMONAPPLICATION__RUN, line 97 of C:/lazarus/components/brook/brokers/brookfclhttpdaemonbroker.pas
$00401A5C main, line 11 of project1.lpr
$0040F0E1
Call trace for block $002E05F0 size 56
$004357DC
$0042003B
$004347FB
$0044C794 of C:/lazarus/components/brook/core/brookhttputils.pas
$00430808 TBROOKDAEMONAPPLICATION__RUN, line 97 of C:/lazarus/components/brook/brokers/brookfclhttpdaemonbroker.pas
$00401A5C main, line 11 of project1.lpr
$0040F0E1
Call trace for block $002C1AF8 size 16
$0040B9D8
$004357CD
$0042003B
$004347FB
$0044C794 of C:/lazarus/components/brook/core/brookhttputils.pas
$00430808 TBROOKDAEMONAPPLICATION__RUN, line 97 of C:/lazarus/components/brook/brokers/brookfclhttpdaemonbroker.pas
$00401A5C main, line 11 of project1.lpr
$0040F0E1
Call trace for block $00330760 size 80
$0042003B
$004347FB
$0044C794 of C:/lazarus/components/brook/core/brookhttputils.pas
$00430808 TBROOKDAEMONAPPLICATION__RUN, line 97 of C:/lazarus/components/brook/brokers/brookfclhttpdaemonbroker.pas
$00401A5C main, line 11 of project1.lpr
$0040F0E1
Call trace for block $002C1A98 size 16
$0040B9D8
$00425363
$00435A37
$00430C40 TBROOKHTTPDAEMONMAPPER__CREATE, line 179 of C:/lazarus/components/brook/brokers/brookfclhttpdaemonbroker.pas
$004347FB
$0044C794 of C:/lazarus/components/brook/core/brookhttputils.pas
$00430808 TBROOKDAEMONAPPLICATION__RUN, line 97 of C:/lazarus/components/brook/brokers/brookfclhttpdaemonbroker.pas
$00401A5C main, line 11 of project1.lpr
Call trace for block $002C1A38 size 16
$00424CF3
$00425363
$00435A37
$00430C40 TBROOKHTTPDAEMONMAPPER__CREATE, line 179 of C:/lazarus/components/brook/brokers/brookfclhttpdaemonbroker.pas
$004347FB
$0044C794 of C:/lazarus/components/brook/core/brookhttputils.pas
$00430808 TBROOKDAEMONAPPLICATION__RUN, line 97 of C:/lazarus/components/brook/brokers/brookfclhttpdaemonbroker.pas
$00401A5C main, line 11 of project1.lpr
Call trace for block $002C19D8 size 16
$0041FF2D
$00435536
$00435912
$00435A29
$00430C40 TBROOKHTTPDAEMONMAPPER__CREATE, line 179 of C:/lazarus/components/brook/brokers/brookfclhttpdaemonbroker.pas
$004347FB
$0044C794 of C:/lazarus/components/brook/core/brookhttputils.pas
$00430808 TBROOKDAEMONAPPLICATION__RUN, line 97 of C:/lazarus/components/brook/brokers/brookfclhttpdaemonbroker.pas
Call trace for block $002C87D8 size 36
$00435912
$00435A29
$00430C40 TBROOKHTTPDAEMONMAPPER__CREATE, line 179 of C:/lazarus/components/brook/brokers/brookfclhttpdaemonbroker.pas
$004347FB
$0044C794 of C:/lazarus/components/brook/core/brookhttputils.pas
$00430808 TBROOKDAEMONAPPLICATION__RUN, line 97 of C:/lazarus/components/brook/brokers/brookfclhttpdaemonbroker.pas
$00401A5C main, line 11 of project1.lpr
$0040F0E1
Call trace for block $00340770 size 96
$004347FB
$0044C794 of C:/lazarus/components/brook/core/brookhttputils.pas
$00430808 TBROOKDAEMONAPPLICATION__RUN, line 97 of C:/lazarus/components/brook/brokers/brookfclhttpdaemonbroker.pas
$00401A5C main, line 11 of project1.lpr
$0040F0E1
$0040B134
$0040F0E1
Setting BrookSettings.AcceptsJSONContent := True;
doesn't work for BrookFCLHTTPAppBroker.
+ Memory leak in HandleUnknownEncoding()
procedure in other brokers.
Is there any method to detect whether a request is ajax request or not?
Would it be possible to use pascal script in a template similar to how mako templates
work in python: http://www.makotemplates.org/
Just wondering.
Hello,
I'm thinking of implementing the following feature in Brook (a pseudo code):
type
TFoo = class(TObject)
published
procedure Validate;
property Any: string read GetAny;
(...)
end;
(...)
procedure TMyDBAction.Post;
var
Foo: TFoo;
begin
Foo := TFoo.Create;
try
Foo.Validade;
Table.Insert(Foo).Apply;
finally
Foo.Free;
end;
end;
I'm a bit biased whether this is fcl's fastcgi fault or brook, but I'll report here first to ensure (and you can forward to fpc mantis then). Basically I want to test the reliability of the application. So I create a simple fastcgi application that only outputs a single hello world message (just make an action with get method containing write('hello, world');). With httest, I then create 5000 (sometimes it passes, and fails at higher number like 8000) concurrent connection to request the server at once and here's what I got from debugger:
Exception class "HTTPError" at $080CDCA7 with message "Failed to write data to socket. Error: -1"
#0 fpc_raiseexception at :0
#1 CUSTFCGI$$TFCGIRESPONSE$$$WRITE_FCGIRECORD$PFCGI_HEADER at :0
#2 CUSTFCGI$
#3 HTTPDEFS$
#4 .Ld17 at :0
#5 CUSTWEB$
#6 ?? at :0
#7 TBROOKAPPLICATION__RUN() at /media/Sources/lazarus-fpc/git/brookframework/brokers/brookfclfcgibroker.pas:108
#8 main at test.lpr:9
I want to try FCL HTTP Daemon Broker on Linux. After following steps here, the service runs, but the application doesn't seem to work correctly. Requesting from browser behaves as if the application doesn't run. I tried running the service manually by passing -r directly to the executable and indeed it doesn't work. Removing the daemon broker and returning to purely embedded web server works.
In case of unhandled exception occurs, a brook app will crash and causes HTTP 502, while in fpweb, it will generate a backtrace similar as in desktop application, only converted as html and sent as response. The application is still alive after that. Please add this functionality. You can take a look at custweb unit as an implementation reference. I tried making it as pluggable module but apparently I can't do any output from the exception handler and I think the better way is to make it integrated in the framework.
How can i use Embedded Daemon Server on Linux (Ubuntu) ?
On my first test i get access violation:
user1@movotcf:/Documentos/Desenvolvimento/pascal/testewserv$ sudo ./tws/Documentos/Desenvolvimento/pascal/testewserv$ sudo ./tws -r
Usage: /home/user1/Documentos/Desenvolvimento/pascal/testewserv/tws [command]
Where command is one of the following:
-i --install To install the program as a service
-u --uninstall To uninstall the service
-r --run To run the service
user1@movotcf:
^Cexception at 000000000041C69B:
Access violation.
user1@movotcf:~/Documentos/Desenvolvimento/pascal/testewserv$
Hello,
I'm planning to create a middleware support.
Imagine it:
TUserAction.RegisterMiddleware('/user/:id', TMyMiddlewareClass);
...
procedure TMyMiddlewareClass.Execute;
var
Vid: Integer;
begin
Vid := Action.Fields['id'].AsInteger;
if not VId in [0..9] then
Error('Invalid ID: %d', [VId]);
end;
And reuse TMyMiddlewareClass
in other class:
initialization
TDownloadAction.Register('/download/:id');
TDownloadAction.RegisterMiddleware(TMyMiddlewareClass);
What do you think?
Hello,
I'm planning to create the BSP -- Brook Server Pages.
BSP is similar to JSP, ASP etc., however will use Object Pascal.
Tale with the help of those who are interested by this feature. 👍
Hi,
When using the embedded http broker how can I set a public html directory for Javascript libraries, images etc
How would I approach setting up a brook app that also uses graphical forms in Windows?
I'd like most of the UI to be via a web browser, accessing the Brook backend via http://localhost/. However, the big empty console box that is created when a Brook embedded web server app is run is rather ugly.
I'd rather generate a simple form that can be minimized to the system tray when the Brook app is running.
I am using the git master zip from a few days ago.
When I run my project user the embedded http broker it dies with a unhandled exception in
procedure TBrookApplication.Run;
begin
FApp.Run; <---exception raised here and app terminates.
end;
After I load the first action and refresh the page it does this every time and returns this exception: Missing http protocol version in request
The app terminates after this exception is raised.
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.