Git Product home page Git Product logo

brookframework's Introduction

brookframework's People

Contributors

atihonovs avatar leledumbo avatar mdbs99 avatar mfernstrom avatar michaelvanham avatar silvioprog avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

brookframework's Issues

html template, ccs or PHP for decoration is posible?

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?

Compile using FPC release stable or FPC fixes was failed

I thought, by default FPC 2.6.2 was not compiled FCL-STL as their compiled packages.

Fact, FCL-STL was not default compiled package. So, there is not possible to use any units from FCL-STL using current FPC release (2.6.2) nor their fixes.

regards,
Takeda

1 error

Feature: router middleware

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?

BrookFCLHTTPAppBroker lacks JSON support

Setting BrookSettings.AcceptsJSONContent := True; doesn't work for BrookFCLHTTPAppBroker.

+ Memory leak in HandleUnknownEncoding() procedure in other brokers.

Embedded http broker dies with unhandled exception

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.

Unhandled exception handler is missing, causing application to crash when happened

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.

Can't handle a lot of requests

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$
$TFCGIRESPONSE_$
$$DOSENDCONTENT at :0
#3 HTTPDEFS$
$TRESPONSE_$$$SENDCONTENT at :0
#4 .Ld17 at :0
#5 CUSTWEB$
$TWEBHANDLER_$
$$_DOHANDLEREQUEST$TREQUEST$TRESPONSE at :0
#6 ?? at :0
#7 TBROOKAPPLICATION__RUN() at /media/Sources/lazarus-fpc/git/brookframework/brokers/brookfclfcgibroker.pas:108
#8 main at test.lpr:9

Embedded Daemon Server is only for Windows service?

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
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:
/Documentos/Desenvolvimento/pascal/testewserv$ sudo ./tws -r
^Cexception at 000000000041C69B:
Access violation.

user1@movotcf:~/Documentos/Desenvolvimento/pascal/testewserv$

newbie question

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.

Embedded http brooker memory leaks

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

Installation problem Ubuntu12.10/Lazarus 1.04

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

Error package installation

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.

DoBeforeRequest question

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;

Daemon on Linux doesn't seem to work

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.

TBrookRouter is not thread-safe

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.

Page404 and Page500 should not check file system each time

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:

  • First one is performance - file system is checked each time, which is not desired if error page template is hardcoded in the source.
  • The second one is security - if file for some reason become unavailable (e.g. file system failure), framework will expose path to that file directly to user. Production server should never leak such information to the visitors in any circumstances.

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.

Brook forum.

Hello,

It would be interesting to have a Brook forum? If yes, it would be maked with Kendo+Brook or phpbb?

Blog demo redirect problem, UrlFor(THome) returns empty string

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.

Support for fcl-web's embedded HTTP server

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?

TBrookSettings.Port;

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.

Table: Persist a TObject

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;

Deleted records are still displayed using the ADS databases

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

content different than expected output in CGI

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;

Some issues in the wizard generated project (Lazarus)

  • Action editor problem: cannot edit action. Whenever I press OK on action being edited, it always says: The action "" already exists. Steps:
    • Project->New Project->Full CGI / FastCGI application
    • Fill the form (whatever)
    • Actions form appear, click add
    • Give a name and OK
    • Back to actions form, select the newly created action and press edit
    • Simply press OK
  • HTTP_CHARSET_UTF_8 identifier in generated Brokers unit, should be BROOK_HTTP_CHARSET_UTF_8 (causes identifier not found)
  • Can't execute the resulting binary. Executing from IDE shows nothing, executing from terminal gives

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)

demos contain cross site scripting

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".

Brook Server Pages

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. 👍

Add support for hierarchical rendering

test
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.

Static file request support

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?

Feature: BrookDBConstraints

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.

Brook embedded web server and forms in windows?

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.

ugly

I'd rather generate a simple form that can be minimized to the system tray when the Brook app is running.

better

New property: TBrookAction.Files;

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.

Improvements to Router syntax

Currently action routing supports such syntax:

  • /page – static page
  • /get/:id/ – parameterized page
  • /more/*/all – single-part asterisk
  • /file//download** – multi-part asterisk (would match /file/a/.../z/download)

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/)

  • /page – static page
  • /get/:id/ – parameterized page
  • */file/path

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.

Getting Started Question

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

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.