[Tutorial] Basic fpWeb Tutorial Article lazarus / 38-Networking and Web Programming ---------------------------------------------------------------------- Leledumbo · 2015-07-14 11:13 I proudly present my latest writing: Basic fpWeb Tutorial. This article covers basic usage of fpWeb such as request flow & handling, modules, actions, cookies and sessions. Feel free to comment for improvement, but it's better to send patches here ---------------------------------------------------------------------- bee · 2015-07-15 03:17 Great job, bro. Thank you. With just one suggestion... provide example(s). ---------------------------------------------------------------------- motaz · 2015-07-15 08:07 This is a well written document about fpWeb. I always prefer default packages, and without this document we couldn’t know about it's fpWeb features ---------------------------------------------------------------------- exdatis · 2015-07-15 08:12 Thank you very much! ---------------------------------------------------------------------- nomorelogic · 2015-09-04 17:26 I translated the tutorial in Italian. There is still a bit 'of work to do (translate images) but there we are. I'm not a professional translator, criticism is welcome  Edit: ops... https://bitbucket.org/nomorelogic/traduzioni ---------------------------------------------------------------------- Trenatos · 2015-09-04 21:15 I've only had a chance to speed-read through it, but this looks great! Instead of skimming and not explaining important details, it seems that you cover the basics properly, how to use sessions, cookie, scope, post/get, modules, etc. I will definitely be spending some time checking this out. ---------------------------------------------------------------------- Trenatos · 2015-09-04 21:31 Hm, actually, I ran into a problem. After creating a new application, and trying to start it as described, I get an error when I visit the page:  TCustomHTTPModule not found ---------------------------------------------------------------------- Leledumbo · 2015-09-05 08:26 Quote from: Trenatos on September 04, 2015, 11:31:44 pmHm, actually, I ran into a problem. After creating a new application, and trying to start it as described, I get an error when I visit the page:  TCustomHTTPModule not found Please be specific, I'm not an oracle. I can't see what you code, how you run it, etc. ---------------------------------------------------------------------- eny · 2015-09-05 09:32 Great introduction! Would be nice if it would be integrated in the Wiki though (http://wiki.lazarus.freepascal.org/fcl-web). ---------------------------------------------------------------------- Trenatos · 2015-09-05 17:09 Quote from: Leledumbo on September 05, 2015, 10:26:56 amQuote from: Trenatos on September 04, 2015, 11:31:44 pmHm, actually, I ran into a problem. After creating a new application, and trying to start it as described, I get an error when I visit the page:  TCustomHTTPModule not found Please be specific, I'm not an oracle. I can't see what you code, how you run it, etc. Sorry about that. It seems I missed the part about ignoring all the exceptions. When I do that, it works and I see the text in browser. ---------------------------------------------------------------------- cappe · 2015-11-19 16:55 Thank you ---------------------------------------------------------------------- tigerA15 · 2015-11-30 04:12 that's great. ---------------------------------------------------------------------- kveroneau · 2016-02-01 23:26 Great tutorial, the example code provided is very helpful at explaining how to use fpWeb, especially for someone who is new to FP/Lazarus. I would like to point out that I did reference the source code for some additional help, such as DefaultModuleName, which is useful if you have multiple modules, but want "/" to still do something. Some stuff I'd love covered in a future fpWeb tutorial would be:  * What are the exceptions we are seeing in Lazarus when we run our app?  Are we suppose to trap these exceptions, where/how do we trap them?  * How does the serving of static files work?  For dev, it's nice to have the dev server serve JavaScript/CSS/images, but in a production environment, Nginx/Apache/CDN should really serve these.  * How could you override the default request handler?  Currently the URI system is /module/action, with no mentioning of any customization.  * How can you send out another HTTP response code?  Such as 403, or a 302 to the browser?  * An example of how to override Application.OnGetModule would be great!  * How to handle exceptions in production, such as sending out an email to the admin with the exception text.  * Can the exceptions during development be set to be more human to read?  Currently, the stack trace reads like machine code.  * More example code on using sessions, and how the browser cookie is set for these sessions.  * Examples on how to use the other lazweb module types: Web DataProvider, Web JSON-RPC, Web Ext.Direct, HTML Web I'll see about researching into these myself in the meantime.  I am currently debating on using Pascal for future web projects, especially where performance might be needed.  When comparing how fast a page loads in Pascal to dynamic languages like Python, it really shows a speed boast, as there's no more bytecode VM in the middle.  I'd personally like to do a basic benchmark to say compare fpWeb with a Python microframework like Bottle.py. ---------------------------------------------------------------------- Leledumbo · 2016-02-02 00:11 Quote from: kveroneau on February 02, 2016, 12:26:44 am * What are the exceptions we are seeing in Lazarus when we run our app?  Are we suppose to trap these exceptions, where/how do we trap them? None, unless it's from user own code. The tips and tricks section mentions how to trap this and displays appropriate error page instead of the default stack trace. Quote from: kveroneau on February 02, 2016, 12:26:44 am * How does the serving of static files work?  For dev, it's nice to have the dev server serve JavaScript/CSS/images, but in a production environment, Nginx/Apache/CDN should really serve these. Hmm... I did mention the dialog but doesn't go deep enough of how it works. Noted. Quote from: kveroneau on February 02, 2016, 12:26:44 am * How could you override the default request handler?  Currently the URI system is /module/action, with no mentioning of any customization. Application.OnGetModule should be exploited. Quote from: kveroneau on February 02, 2016, 12:26:44 am * How can you send out another HTTP response code?  Such as 403, or a 302 to the browser? I missed that one. Noted. In the meantime, try setting Response.Code. Quote from: kveroneau on February 02, 2016, 12:26:44 am * An example of how to override Application.OnGetModule would be great! I consider custom routing as not "basic", let me think about it. Quote from: kveroneau on February 02, 2016, 12:26:44 am * How to handle exceptions in production, such as sending out an email to the admin with the exception text. This should be out of the tutorial since the custom exception handling has been covered and email sending is not part of fpWeb feature. Quote from: kveroneau on February 02, 2016, 12:26:44 am * Can the exceptions during development be set to be more human to read?  Currently, the stack trace reads like machine code. Again, back to tips and tricks on custom exception handler. Quote from: kveroneau on February 02, 2016, 12:26:44 am * More example code on using sessions, and how the browser cookie is set for these sessions. More? What's missing? How the browser cookie is set could be added, it's just informational (see FPWebSession in your browser's cookie). Quote from: kveroneau on February 02, 2016, 12:26:44 am * Examples on how to use the other lazweb module types: Web DataProvider, Web JSON- RPC, Web Ext.Direct, HTML Web Definitely not basic. TBH, I'm not sure on how to use half of them and IMHO some of them are too complicated to use (I would prefer handcoding the HTML instead of using HTMLWriter). Quote from: kveroneau on February 02, 2016, 12:26:44 amI'll see about researching into these myself in the meantime.  I am currently debating on using Pascal for future web projects, especially where performance might be needed.  When comparing how fast a page loads in Pascal to dynamic languages like Python, it really shows a speed boast, as there's no more bytecode VM in the middle.  I'd personally like to do a basic benchmark to say compare fpWeb with a Python microframework like Bottle.py. Good luck. My company has one (I injected it when the others are unconscious), just a simple SQLite backed web services + front end pages. Actually I use it for benchmarking SQLite, since the Pascal part is already blazing fast while requiring only a small amount of RAM (the biggest use is SynMustache because it caches the templates). ---------------------------------------------------------------------- kveroneau · 2016-02-02 00:44 Thank you for your swift reply, that's good to know that the other module types can make things a bit more complicated, I'll hold off on looking at them for now.  I guess the session stuff is pretty much down packed, is there a way to customize the session cookie name?  Say, you have 2 fpWeb apps on a single domain, but want each to keep a separate session.  Where are the session INI files kept?  Are they placed in /tmp, or in the directory where your application was started?  Can the location of the session INIs be easily customized? As for the status codes, 302 is a redirect, and I believe I may have found out how to send one: AResponse.SendRedirect appears to get the job done.  In modern web apps, after say adding an object using a form, the page which was just POST'd to, usually performs a redirect back to either a form to edit the object just added, or redirects to the object list page. ---------------------------------------------------------------------- bee · 2016-02-02 04:31 If you know the basic mechanisms of how a web app works, actually you don't need fpWeb to write a web app using Pascal. I've been making many web apps using Pascal since about 10 years ago, long before fpWeb existed. HTTP is a pretty old technology, you know. IMHO, it's not about the future of Pascal for web because it has been able to do that since the beginning. I remember my first Pascal web app was written using Turbo Pascal 7.0. Basically it's just about how to read from stdin and to write to stdout using HTTP communication protocol. It's long before PHP even existed. It's more about how we use Pascal to compete with currently over-hype web tools/frameworks/languages. Object Pascal is an advance language since its inception. It's just born too early so most people don't understand its capability. ---------------------------------------------------------------------- edwinyzh · 2016-03-16 07:09 Well done and Thanks! Downloaded ---------------------------------------------------------------------- JD · 2016-03-24 09:22 Quote from: bee on February 02, 2016, 05:31:26 amIf you know the basic mechanisms of how a web app works, actually you don't need fpWeb to write a web app using Pascal. I've been making many web apps using Pascal since about 10 years ago, long before fpWeb existed. HTTP is a pretty old technology, you know. IMHO, it's not about the future of Pascal for web because it has been able to do that since the beginning. I remember my first Pascal web app was written using Turbo Pascal 7.0. Basically it's just about how to read from stdin and to write to stdout using HTTP communication protocol. It's long before PHP even existed. It's more about how we use Pascal to compete with currently over-hype web tools/frameworks/languages. Object Pascal is an advance language since its inception. It's just born too early so most people don't understand its capability. Well said & every encouraging. Thanks to Leledumbo for his excellent work. I never understood how fpWeb worked beforehand but I'll now give it a try. JD ---------------------------------------------------------------------- Leledumbo · 2016-03-24 18:02 Quote from: JD on March 24, 2016, 10:22:17 amWell said & every encouraging. Thanks to Leledumbo for his excellent work. I never understood how fpWeb worked beforehand but I'll now give it a try. Don't worry, I can guarantee 1 out of 10 web developers don't actually understand how browsers and servers communicate, HTTP protocol or even basic networking works So if you give it a try, at least you're already one step ahead. ---------------------------------------------------------------------- aradeonas · 2016-03-24 18:43 @Leledumbo, it seems you are active in web development and I saw some your activities about this like your posts in your blog (I like to read more but you didnt update it lately) so I want to ask is it good doing web stuff with fpc? what libraries do you used? did you tried Brook,didi you liked it? What fields in web you think fpc is more usefull? Beside this post what sources should I read for this subject? ---------------------------------------------------------------------- Leledumbo · 2016-03-25 08:33 Quote from: aradeonas on March 24, 2016, 07:43:28 pmso I want to ask is it good doing web stuff with fpc? You should've figured it out yourself. Why the hell do I keep posting it if it's not good? Quote from: aradeonas on March 24, 2016, 07:43:28 pmwhat libraries do you used? did you tried Brook,didi you liked it? Brook, exactly. fpWeb is secondary choice. Quote from: aradeonas on March 24, 2016, 07:43:28 pmWhat fields in web you think fpc is more usefull? Everything, no exception. Quote from: aradeonas on March 24, 2016, 07:43:28 pmBeside this post what sources should I read for this subject? General knowledge about networking, HTTP protocol, specific web server configuration, AJAX, JSON, etc. Too many to list if you have no clear goal. ---------------------------------------------------------------------- marcov · 2016-03-25 09:09 I actually ported FPC to FreeBSD in 1999-2000 because I wanted to run cgis on my FreeBSD account. It was my first major job as FPC devel. The CGIs were a kind of webcounters btw. ---------------------------------------------------------------------- aradeonas · 2016-03-25 11:10 Thanks @Leledumbo. Mostly I like to make some API for my programs to work with so avoid writing PHP for my API parts. I never saw a easy to learn demo for making an API system with authentication. ---------------------------------------------------------------------- Leledumbo · 2016-03-25 15:31 Quote from: aradeonas on March 25, 2016, 12:10:12 pmThanks @Leledumbo. Mostly I like to make some API for my programs to work with so avoid writing PHP for my API parts. I never saw a easy to learn demo for making an API system with authentication. Because it's no different from normal HTTP request/response flow, just specially dictated (what you have to send, what you will receive) in some parsable text (json, xml, whatever). It's a matter of knowledge combining, although in PHP world it's often overrated by being something special and thus require special libraries as well. ---------------------------------------------------------------------- aradeonas · 2016-03-25 15:39 QuoteBecause it's no different from normal HTTP request/response flow, just specially dictated (what you have to send, what you will receive) in some parsable text (json, xml, whatever). It's a matter of knowledge combining, although in PHP world it's often overrated by being something special and thus require special libraries as well.But it good to have one example for beginners anyway. ---------------------------------------------------------------------- Leledumbo · 2016-03-25 16:37 Quote from: aradeonas on March 25, 2016, 04:39:55 pmBut it good to have one example for beginners anyway. I don't consider web service API with authentication as a beginner task, which is why I don't write one for it. I always write basic tutorial and only advanced ones if they're not merely a knowledge combining, for instance: compiler construction. I assume knowledge combining to be basic requirement for intermediate programmers, in fact that's what makes them different from beginners. Below is a simple echo API with basic access authentication using Brook: Code: Pascal  [Select][+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i program SimpleAPIWithBasicAuthentication; {$mode objfpc}{$H+}{$define debug} uses  base64,  fpjson,  httpprotocol,  BrookUtils,  BrookLogger,  BrookAction,  BrookHttpDefs,  BrookFCLHTTPAppBroker,  BrookApplication; const  ValidUsername = 'root';  ValidPassword = 'admin'; type   { TAPIAction }   TAPIAction = class(TBrookAction)  protected    FJSONResponse: TJSONObject;  public    procedure DoRequest(ARequest: TBrookRequest; AResponse: TBrookResponse); override;  end;   { TAuthenticatedAction }   TAuthenticatedAction = class(TAPIAction)  private    function IsValidToken(const AToken: String): Boolean;  public    procedure Request(ARequest: TBrookRequest; AResponse: TBrookResponse); override;  end;   { TEchoAction }   TEchoAction = class(TAuthenticatedAction)    procedure Get; override;  end; { TAPIAction } procedure TAPIAction.DoRequest(ARequest: TBrookRequest;  AResponse: TBrookResponse);var  Log: String;begin  FJSONResponse := TJSONObject.Create;  try    inherited DoRequest(ARequest, AResponse);    // Every output is considered a log    Log := AResponse.Content;    if (Length(Log) > 0) and BrookSettings.LogActive then begin      TBrookLogger.Service.Info(Log);    end;    // Override content by JSON    AResponse.Content := FJSONResponse.{$ifndef debug}AsJSON{$else}FormatJSON{$endif};  finally    FJSONResponse.Free;  end;end; { TAuthenticatedAction } function TAuthenticatedAction.IsValidToken(const AToken: String): Boolean;begin  Result := EncodeStringBase64(ValidUsername + ':' + ValidPassword) = AToken;end; procedure TAuthenticatedAction.Request(ARequest: TBrookRequest; AResponse: TBrookResponse);var  AuthHeader, TokenPrefix, Token: String;  Authenticated: Boolean;begin  AuthHeader := ARequest.GetHeader(hhAuthorization);  // I love System.Copy's "no error" behavior :)  TokenPrefix := Copy(AuthHeader,1,6);  Token := Copy(AuthHeader,7,Length(AuthHeader));  Authenticated := (TokenPrefix = 'Basic ') and IsValidToken(Token);  if Authenticated then    inherited Request(ARequest, AResponse)  else begin    AResponse.Code := 401;    AResponse.CodeText := 'Unauthorized';    AResponse.SetHeader(hhWWWAuthenticate,'Basic realm="API"');    FJSONResponse.Add('status',AResponse.Code);    FJSONResponse.Add('message',AResponse.CodeText);  end;end; { TEchoAction } procedure TEchoAction.Get;var  Msg: String;begin  Msg := HttpRequest.QueryFields.Values['message'];  if Length(Msg) > 0 then begin    FJSONResponse.Add('status',200);    FJSONResponse.Add('message',Msg);  end else begin    FJSONResponse.Add('status',400);    FJSONResponse.Add('message','Please provide "message" field');  end;end; begin  TEchoAction.Register('/echo');  BrookSettings.Port := 4444;  BrookApp.Run;end. A beginner is likely to ask: How to compileHow to runHow to testHow to have username & password combo stored in files/database/whereverAnd many other non-essential things that may clutter a clean tutorial focusing on the web service itself. It's a self experience from teaching, and experiences don't lie ---------------------------------------------------------------------- aradeonas · 2016-03-25 20:02 Thanks @Leledumbo. It is more clear for me know how to make a simple API. ---------------------------------------------------------------------- garlar27 · 2016-12-16 15:51 Thanks Leledumbo! It's a good tutorial indeed!! But I've got a doubt: When building a module, is there a way to specify the for which Apache version (e.g. Apache 2.2 Apache 2.4) generate the module? ---------------------------------------------------------------------- Leledumbo · 2016-12-16 17:36 Quote from: garlar27 on December 16, 2016, 04:51:26 pmThanks Leledumbo! It's a good tutorial indeed!! But I've got a doubt: When building a module, is there a way to specify the for which Apache version (e.g. Apache 2.2 Apache 2.4) generate the module? The unit names differ for both versions, look in your units folder. ---------------------------------------------------------------------- garlar27 · 2016-12-19 13:33 Thank you!! Quote from: Leledumbo on December 16, 2016, 06:36:08 pmThe unit names differ for both versions, look in your units folder. I've changed the units "httpd" to "httpd24" and "fpapache" to "fpapache24" now the apache server starts well. But when the request reaches the server it doesn't responds. Checking the apache "error_log" file I read that the error that occurred is Quote    An unhandled exception occurred at $00007FF8F0760C66:     EHTTP: No REQUEST_METHOD passed from server.       $00007FF8F0760C66Googling the message "No REQUEST_METHOD passed from server" points to FPC repositories only. For that reason I added temporary logs everywhere to pin point if there is something wrong with my code (which works fine on Apache 2.2) and the only logs I have are the ones in the "begin ... end." of the ".lpr" file. It makes me think that the exception is raised before my code has a chance to read the request. Is there any other thing I need to change? Maybe the ".fpc.cfg" file or any other unit? ---------------------------------------------------------------------- Leledumbo · 2016-12-21 09:17 Quote from: garlar27 on December 19, 2016, 02:33:34 pmI've changed the units "httpd" to "httpd24" and "fpapache" to "fpapache24" now the apache server starts well. But when the request reaches the server it doesn't responds. Checking the apache "error_log" file I read that the error that occurred is Quote    An unhandled exception occurred at $00007FF8F0760C66:     EHTTP: No REQUEST_METHOD passed from server.       $00007FF8F0760C66Googling the message "No REQUEST_METHOD passed from server" points to FPC repositories only. For that reason I added temporary logs everywhere to pin point if there is something wrong with my code (which works fine on Apache 2.2) and the only logs I have are the ones in the "begin ... end." of the ".lpr" file. It makes me think that the exception is raised before my code has a chance to read the request. Something within apache virtual server config, I believe. I don't know how apache pass environment variables to its modules, but the core of fcl-web expects at least that environment variable to work. ---------------------------------------------------------------------- garlar27 · 2016-12-21 17:03 Well, things got more complicated than I anticipated. I will try to follow this problem in other thread. Resume: Changing the uses units "httpd" to "httpd24" and "fpapache" to "fpapache24" allow Apache server to start. The problem I still have: In case some one is interested will be explain in more detail in the following thread Problems with modules for APACHE 2.4 ---------------------------------------------------------------------- Ozz_Nixon · 2017-03-03 16:17 Kudos - Great Start! ---------------------------------------------------------------------- ahiggins · 2017-03-03 16:25 Thank you very much ---------------------------------------------------------------------- egsuh · 2017-03-24 06:03 I cannot see the tutorial.  It says something like:  "Dropbox - 404 cannot the file". ---------------------------------------------------------------------- nummer8 · 2017-03-24 07:54 Try this link https://bitbucket.org/leledumbo/books/downloads/ or use google fpweb tutorial Jos ---------------------------------------------------------------------- egsuh · 2017-03-24 09:11 Quote from: nummer8 on March 24, 2017, 08:54:18 amTry this link https://bitbucket.org/leledumbo/books/downloads/ or use google fpweb tutorial Jos Thank you. Really appreciate. ---------------------------------------------------------------------- egsuh · 2017-03-24 11:19 I did some tests myself, and I'd like to share what I have found with you, hoping that my experience help some guys at least. I tried to make my own web-server application in CGI way. The structure is rather similar with "WEBSNAP" in Delphi, which is deprecated now.  What I'd like to say is about action of event handlers.  I put one module, let's say "mod1", and one action, let's say "act1" and set it as default. If you call your app from browser, by typing in  "localhost/exec/mycgi.exe/act1" in the browser address windonw, it seems that event handlers run in following order: - module_oncreate - module_afterrequest - module_beforerequest - module_onrequest - module_ongetaction - action_beforerequest - action_onrequest - action_afterresponse - module_afterresponse - module_on destroy This means you can process your data on the server side at any position here, except you set "handled := true" in moudle_onrequest procedure. This will make your application skip to "module_afterresponse". Here, "processing" does not necessarily affect the HTML output, which client browser will actually see.  Basically you can change your output content directly, changing content of "AResponse.Contents" at module_onrequest, module_afterresponse, action_onrequest, action_afterresponse. Let's see an example: module_onrequest:     AResponse.Contents.Add ('Hello, world
');     Handled :=false; action_onrequest:    AResponse.Contents.Add('You called action
');    Handled := true;     // if you comment this out, default serems handled = falset action_afterresponse:    AResponse.Contents.Add('Actions done
'); module_afterresponset:     AResponse.Contents.Add ('I finished my response
'); Then you will see in our browser:   Hello, world   You called action   Actions done   I finished my response If you set handled:=true in module_onrequest, then you would see:   Hello, world Setting "handled:= ture" does not operate in the same way in module and action. If you set handled true, the process in the module_afterresponse IS processed, but response contents defined there are not. Another thing to mention is regarding defining "Contents" in action property --- you can directly type in the small editor box. Let's assume that you typed in "Contents from property Contents
" in Contents in act1's property.  If you set handled := true in the action_onrequest, you will get the same result above (assuming handled := false in module_onrequest). When you set handled to false in the action_onrequest, then you will get:   Hello, world   You called action   Contents from property Contents   Actions done   I finished my response With this, I think we can break down our application bit by bit, and process each part at different positions at our convenience. Hope you can include this content in your tutorial if you think helpful. I spend rather long time to figure out this structure in the past, and want others who start webprogramming do not have to spend time here. ---------------------------------------------------------------------- Leledumbo · 2017-03-25 06:19 Quote from: egsuh on March 24, 2017, 12:19:15 pmHope you can include this content in your tutorial if you think helpful. I spend rather long time to figure out this structure in the past, and want others who start webprogramming do not have to spend time here. Feel free to submit a pull request. Although I'm a bit unsure whether such a deep flow explanation is necessary for basic tutorial. Moreover, recently it gets new simpler and a lot more flexible routing mechanism. I have no idea where to insert it in the existing sections. ---------------------------------------------------------------------- egsuh · 2017-03-26 09:21 Quote from: Leledumbo on March 25, 2017, 07:19:39 amFeel free to submit a pull request. Although I'm a bit unsure whether such a deep flow explanation is necessary for basic tutorial. Moreover, recently it gets new simpler and a lot more flexible routing mechanism. I have no idea where to insert it in the existing sections. You are right. there are many other ways of routing. This may be useful only when setting "handled" is the most convenient way of controlling  flow. I just wanted to make it easier to understand the role of setting 'handled" true or false. ---------------------------------------------------------------------- juliano · 2017-05-26 01:06 Hello Leledumbo, do you have any brook framework tutorial? ---------------------------------------------------------------------- Leledumbo · 2017-05-26 05:00 Quote from: juliano on May 26, 2017, 03:06:50 amHello Leledumbo, do you have any brook framework tutorial? In my head, not yet dumped to books. ---------------------------------------------------------------------- valdir.marcos · 2017-05-26 09:21 Quote from: juliano on May 26, 2017, 03:06:50 amHello Leledumbo, do you have any brook framework tutorial? Have you already looked at these links? http://wiki.freepascal.org/Brook_Framework http://silvioprog.github.io/brookframework/ https://brookframework.org/ Brook,JSON,MySQL http://forum.lazarus.freepascal.org/index.php?topic=24668.0 [OT] Nice post about Brook framework http://forum.lazarus.freepascal.org/index.php?topic=19406.0 http://pascalgeek.blogspot.com.br/2012/12/brook-framework-new-web- application.html https://github.com/silvioprog [ANN] Travel Lazarus Brook | REST | JSON http://forum.lazarus- ide.org/index.php/topic,24018.msg144196.html#msg144196 ---------------------------------------------------------------------- Leledumbo · 2018-06-03 21:14 My tutorial has been updated tocover the new routing mechanism. The PDF has been generated from Typora instead of ReText and internal links are now working. To avoid confusion, old downloads have been removed. ---------------------------------------------------------------------- egsuh · 2018-06-08 03:18 Wow really great. Really appreciate your efforts. Downloading from dropbox does not work. So I downloaded from https://bitbucket.org/leledumbo/books/downloads/ ---------------------------------------------------------------------- af0815 · 2018-06-08 05:03 The tutorial is very inetresting. Thanks for sharing the information ---------------------------------------------------------------------- Leledumbo · 2018-06-08 17:01 The addition of new routing mechanism didn't take the whole article into considerations. Therefore, you might find the routing section a bit detached from the others. I'm thinking on better restructuring, supporting the two mechanism without duplicating the effort in other sections. Right now, other sections are written with the old mechanism in mind. Feel free to state any idea for this. ---------------------------------------------------------------------- nummer8 · 2018-06-08 17:09 Thank you for adding the routing part! Jos ---------------------------------------------------------------------- GAN · 2018-06-08 20:16 Hello Leledumbo, what is the license of the tutorial? Best regards. ---------------------------------------------------------------------- Leledumbo · 2018-06-09 08:58 Quote from: GAN on June 08, 2018, 10:16:42 pmHello Leledumbo, what is the license of the tutorial? Best regards. Damn right, I never state it. I'll probably make it CC BY-SA, as I want modifications to be contributed back. ---------------------------------------------------------------------- BSaidus · 2023-01-28 19:25 Hi @Leledumbo I can not find the pdf, Can you make it online back. Thanks. ---------------------------------------------------------------------- dseligo · 2023-01-28 21:29 Quote from: BSaidus on January 28, 2023, 08:25:42 pmHi @Leledumbo I can not find the pdf, Can you make it online back. Thanks. Not PDF, but wiki: https://wiki.lazarus.freepascal.org/fpWeb_Tutorial ---------------------------------------------------------------------- egsuh · 2023-01-28 22:20 Thank you for your hard working.  Following is an excerpt from the tutorial. Shouldn't parameters    AResponse   be defined as    AResponse:TResponse,   in TRouteCallback and TRouteEvent? QuoteRegistering a Route The 2nd, 3rd or 4th parameter (depending on whether you want to handle specific HTTP method and/or pass additional data to it) of HTTPRouter.RegisterRoute is overloaded with several possibilities:     Callback procedure TRouteCallback = Procedure(ARequest: TRequest; AResponse);     Callback event TRouteEvent = Procedure(ARequest: TRequest; AResponse) of object; ---------------------------------------------------------------------- Leledumbo · 2023-02-02 09:31 Quote from: BSaidus on January 28, 2023, 08:25:42 pmHi @Leledumbo I can not find the pdf, Can you make it online back. Thanks. Sorry, I quitted using dropbox. The book is now on github, feel free to clone and generate the PDF yourself. ---------------------------------------------------------------------- Roland57 · 2023-02-02 09:53 @leledumbo Thank you for sharing. For me, I have zero knowledge about web programming, and I don't have time nor need to learn it, but I am very interested in writing things in Markdown. Please could you share your method for generating HTML and PDF documents? Do you use pandoc, or another tool? Regards. Roland ---------------------------------------------------------------------- Leledumbo · 2023-02-02 20:45 Quote from: Roland57 on February 02, 2023, 10:53:59 amPlease could you share your method for generating HTML and PDF documents? Do you use pandoc, or another tool? The editor I use is Typora, it indeed depends on pandoc to generate its export formats, but I don't need to see that, it's a single menu item from the editor. ---------------------------------------------------------------------- dbannon · 2023-02-02 22:41 Wow, you have done a lot of work to get that on Github, well done ! If the content still the same as that on the Wiki or have you updated it as you go ? (just wondering if there should be a link to the github page from the wiki and visa versa) Davo ---------------------------------------------------------------------- Leledumbo · 2023-02-02 22:45 Quote from: dbannon on February 02, 2023, 11:41:28 pmIf the content still the same as that on the Wiki or have you updated it as you go ? Guess it's still the same, I don't really remember. Just diff it out yourself. Was a mistake putting it on bitbucket, I've lost all the history and left with latest available locally. ---------------------------------------------------------------------- Roland57 · 2023-02-03 04:45 Quote from: Leledumbo on February 02, 2023, 09:45:03 pmThe editor I use is Typora, it indeed depends on pandoc to generate its export formats, but I don't need to see that, it's a single menu item from the editor. Thanks for your answer. I will take a look to Typora. ---------------------------------------------------------------------- PierceNg · 2023-02-03 06:04 Quote from: Roland57 on February 03, 2023, 05:45:36 amThanks for your answer. I will take a look to Typora. You might be interested in https://github.com/grahamegrieve/delphi- markdown which works with FPC. Markdown processors usually generate HTML fragments, so Markdown is usually combined with a template system such as Mustache to generate complete HTML documents. FPC comes with a Mustache processor in package fcl-mustache in its main branch. ---------------------------------------------------------------------- Roland57 · 2023-02-03 06:43 @PierceNg Very interesting indeed. I will look at it. Thanks!