Giter Club home page Giter Club logo

Comments (17)

silvioprog avatar silvioprog commented on July 19, 2024

Other day I tried to use static files. I had seen fpmimetypes and even tried to improve the brookhttpapp broker, but, unfortunately, fpmimetypes is coupled in fpweb. :(

His solution seems the best to use fpmimetypes. Can you to create a small example and provide it on the demos folder?

Thanks.

from brookframework.

leledumbo avatar leledumbo commented on July 19, 2024

This is as general as I can make:

unit Static;

{$mode objfpc}{$H+}

interface

uses
  Classes, SysUtils;

// This is the only thing that user may know from this unit
procedure RegisterDirectory(ARequestPath,ADirectory: String);

implementation

uses
  StrUtils, ghashmap, fpmimetypes, HTTPDefs, BrookAction;

resourcestring
  EmptyRequestPathErrMsg = 'Request path may not be empty';
  DirectoryNotExistErrMsg = 'Directory not exists: %s';

type

  { TStringHash }

  TStringHash = class
    class function hash(s: String; n: Integer): Integer;
  end;

  TRequestDirectoryMap = specialize THashmap<String,String,TStringHash>;

  { TStaticFileAction }

  TStaticFileAction = class(TBrookAction)
  public
    procedure Get; override;
  end;

var
  RequestDirectoryMap: TRequestDirectoryMap;

{ TStringHash }

class function TStringHash.hash(s: String; n: Integer): Integer;
var
  c: Char;
begin
  Result := 0;
  for c in LowerCase(s) do
    Inc(Result,Ord(c));
  Result := Result mod n;
end;

{ TStaticFileAction }

procedure TStaticFileAction.Get;
var
  LastSlashPos: Integer;
  PathInfo,FilePath,Buffer: String;
  ContentType: String;
begin
  PathInfo := GetRequest.PathInfo;
  LastSlashPos := RPos('/',PathInfo);
  System.Delete(PathInfo,LastSlashPos + 1,Length(PathInfo) - LastSlashPos);

  FilePath := RequestDirectoryMap[PathInfo] + Values['file'].AsString;
  if FileExists(FilePath) then begin
    ContentType := MimeTypes.GetMimeType(ExtractFileExt(FilePath));
    if ContentType = '' then
      ContentType := 'application/octet-stream';
    GetResponse.ContentType := ContentType;
    with TFileStream.Create(FilePath,fmOpenRead) do
      try
        SetLength(Buffer,Size);
        Read(Buffer[1],Size);
        Self.Write(Buffer);
      finally
        Free;
      end;
  end;
end;

procedure RegisterDirectory(ARequestPath,ADirectory: String);
begin
  if Length(ARequestPath) = 0 then raise Exception.Create(EmptyRequestPathErrMsg);
  if not DirectoryExists(ADirectory) then raise Exception.CreateFmt(DirectoryNotExistErrMsg,[ADirectory]);

  // add required slashes
  if ARequestPath[1] <> '/' then ARequestPath := '/' + ARequestPath;
  if ARequestPath[Length(ARequestPath)] <> '/' then ARequestPath := ARequestPath + '/';

  RequestDirectoryMap[ARequestPath] := IncludeTrailingPathDelimiter(ADirectory);
  TStaticFileAction.Register(ARequestPath + ':file');
end;

initialization
  RequestDirectoryMap := TRequestDirectoryMap.Create;

finalization
  RequestDirectoryMap.Free;

end.

The responsibility is now leveraged to the user of this unit to call:

MimeTypes.LoadFromFile('mime.types'); // for correct content-type
RegisterDirectory('css','/full/path/to/css');
RegisterDirectory('js','relative/path/may/work/js');
RegisterDirectory('img','/top/level/images');
RegisterDirectory('img/messages','/top/level/images/messages');

I'll make a simple demo, but I need to know where to put this unit and what better name it should have. Note that as the example RegisterDirectory shows, mapping works only for the given directory, excluding directories below it. For that to work, you must register each (sub)*directory #read-it-as-regex.

from brookframework.

silvioprog avatar silvioprog commented on July 19, 2024

Friend, I'll make a demo with this nice code and provides it on the demos folder. :)

It would be interesting implement a broker for use this together with BrookFCLHTTPAppBroker/BrookFCLHTTPDaemonBroker broker.

from brookframework.

leledumbo avatar leledumbo commented on July 19, 2024

It would be interesting implement a broker for use this together with BrookFCLHTTPAppBroker/BrookFCLHTTPDaemonBroker broker.

Do you mean to have 2 brokers active at the same time? Is that possible?

from brookframework.

silvioprog avatar silvioprog commented on July 19, 2024

Yep. Eg:

uses
  BrookFCLCGIBroker, BrookSQLdbBroker, ...

Or (pseudo code):

uses
  BrookFCLHTTPAppBroker, BrookFCLMIMETypesBroker, ...

Can you implement this idea? Feel free if yes! :)

from brookframework.

leledumbo avatar leledumbo commented on July 19, 2024

Hmm... I'll have to dig in the code first, I'm not sure how 2 brokers can be active at the same time...

from brookframework.

jcmoraisjr avatar jcmoraisjr commented on July 19, 2024

you can use as much brokers as you want at the same time providing you dont implement the same service more than once, otherwise it'd lead to ambiguity or something like "service already registered" error.

from brookframework.

leledumbo avatar leledumbo commented on July 19, 2024

you can use as much brokers as you want at the same time providing you dont implement the same service more than once, otherwise it'd lead to ambiguity or something like "service already registered" error.

Yes, that's what I'm afraid of. For mimetypes broker, it should be easy as it doesn't deal with request handling. But static file request broker will do request handling in the same way as CGI/FCGI/HTTPApp/DaemonApp broker (actually, it's the sub of them as it depends on either of them). So could I simply use Static unit implementation above renamed as BrookStaticFileBroker?

from brookframework.

silvioprog avatar silvioprog commented on July 19, 2024

BrookStaticFileBroker (so, StaticFile or StaticFiles? :/ ) is a good name for this new broker.
But this need not necessarily be a broker. You can create a separate class to be used as (pseudo code):

mycustomactns.pas
TCustomAction = class(TBrookAction) // or TBrookDBAction, TBrookRetrieveAction etc etc etc.

procedure TCustomAction.Create;
begin
  inherited Create;
  FStaticFiles := TBrookStaticFiles.Create;
end;

procedure TCustomAction.Destroy;
begin
  FStaticFiles.Free;
  inherited Destroy;
end;

procedure TCustomAction.Request(ARequest: TRequest; AResponse: TResponse);
begin
  FStaticFiles.Execute(ARequest, AResponse);
  inherited;
end;
mycactns.pas
TMyAction = class(TCustomAction)

procedure TMyAction.Get;
begin
  something
end;

Interesting?

from brookframework.

leledumbo avatar leledumbo commented on July 19, 2024

Too much user code IMO, better just register directory and corresponding request path.

from brookframework.

tcaduto avatar tcaduto commented on July 19, 2024

Hi trying to get the static unit to work, but where do I find the mime.types file?

Nevermind, copied it from a linux box.

from brookframework.

leledumbo avatar leledumbo commented on July 19, 2024

In case anybody need one: https://dl.dropboxusercontent.com/u/22124591/mime.types

from brookframework.

silvioprog avatar silvioprog commented on July 19, 2024

Done. (1251c7c)

@leledumbo , can you upload to working branch a very small sample showing how to use the "brookstaticfilebroker.pas" unit please?

from brookframework.

leledumbo avatar leledumbo commented on July 19, 2024

Will do tonight if I'm not exhausted

EDIT: Done, but I think I did something wrong, please check

from brookframework.

silvioprog avatar silvioprog commented on July 19, 2024

I saw and it worked fine on my Win8 64. It is a nice demo. :)

I refactored some code and also updated the brokers unit for can compile the project. Please check if the current implementation in brookstaticfilebroker unit is the last implementation that you was implemented. I renamed the register method too.

from brookframework.

leledumbo avatar leledumbo commented on July 19, 2024

Please check if the current implementation in brookstaticfilebroker unit is the last implementation that you was implemented

Yep, that seems so.

from brookframework.

silvioprog avatar silvioprog commented on July 19, 2024

Thank you very much! :)

from brookframework.

Related Issues (20)

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.