Recent

Author Topic: [SOLVED] how to debug a CGI from Lazarus  (Read 1288 times)

nomorelogic

  • Full Member
  • ***
  • Posts: 165
[SOLVED] how to debug a CGI from Lazarus
« on: December 07, 2023, 06:40:27 pm »
Hi all

I'd like to simulate the invocation of a cgi from Lazarus IDE
this to be able to use the integrated debugger

I already know that a cgi must read from environment variables
this is valid for GET method and here all goes fine
but the content of the POST request (parameter -d in curl) is passed to the cgi using standard input

in Lazarus IDE there is already the possibility to set environment variables (i am referring to the menu: run -> run parameters -> environment)

but I have no idea how to set in the run parameters something equivalent to:
mycgi.pas < input

is there any workaround?

thanks
nomorelogic



« Last Edit: December 13, 2023, 03:17:54 pm by nomorelogic »

Martin_fr

  • Administrator
  • Hero Member
  • *
  • Posts: 9691
  • Debugger - SynEdit - and more
    • wiki
Re: how to debug a CGI from Lazarus
« Reply #1 on: December 07, 2023, 08:23:43 pm »
Unfortunately that is currently not possible. There is already an issue about it: https://gitlab.com/freepascal.org/lazarus/lazarus/-/issues/40458

Well, you could probably us the "GDB Gnu remote debugger (gdbserver)" backend.
Then you have to start your exe outside the IDE, inside the gdbserver tool. And there you probably (not tested) can apply input redirection).
Then start the debugger and it should connect to the gdbserver. (gdbserver will pause your app on start, until the IDE connects)
I am not sure of the exact steps. It is ages ago since I even looked at that.


toby

  • Full Member
  • ***
  • Posts: 242
Re: how to debug a CGI from Lazarus
« Reply #2 on: December 07, 2023, 10:56:02 pm »
what about ?

pgm "`cat cx.txt`" 

deal with what is in file cx.txt in the pgm as paramstr 1

Martin_fr

  • Administrator
  • Hero Member
  • *
  • Posts: 9691
  • Debugger - SynEdit - and more
    • wiki
Re: how to debug a CGI from Lazarus
« Reply #3 on: December 07, 2023, 11:29:31 pm »
what about ?

pgm "`cat cx.txt`" 

deal with what is in file cx.txt in the pgm as paramstr 1

That will work in a shell. But if the IDE (the debugger) starts the exe, then shell stuff doesn't happen.

nomorelogic

  • Full Member
  • ***
  • Posts: 165
Re: how to debug a CGI from Lazarus
« Reply #4 on: December 12, 2023, 01:27:17 pm »
what about ?

pgm "`cat cx.txt`" 

deal with what is in file cx.txt in the pgm as paramstr 1

That will work in a shell. But if the IDE (the debugger) starts the exe, then shell stuff doesn't happen.

question:
is it for the same reason that if I use the REQUEST_METHOD environment variable set to GET, the debugger works correctly
whereas if I set it to POST it crashes on the Run statement?

follow example code

Code: Pascal  [Select][+][-]
  1. #!/usr/bin/instantfpc
  2. program TestCgi;
  3. {$mode objfpc}{$H+}
  4.  
  5. uses
  6.   Classes,
  7.   SysUtils,
  8.   httpDefs,
  9.   fpweb,
  10.   custweb,
  11.   custcgi,
  12.   webutil;
  13.  
  14. type
  15.   TMyCGIHandler = class(TCgiHandler)
  16.   public
  17.     procedure HandleRequest(ARequest: Trequest; AResponse: TResponse); override;
  18.   end;
  19.  
  20.  
  21.   TMyCGIApp = class(TCustomCGIApplication)
  22.   protected
  23.     function InitializeWebHandler: TWebHandler; override;
  24.   end;
  25.  
  26.  
  27.   procedure TMyCGIHandler.HandleRequest(ARequest: Trequest; AResponse: TResponse);
  28.  
  29.     procedure AddNV(const N, V: string);
  30.     begin
  31.       AResponse.Contents.Add('<TR><TD>' + N + '</TD><TD>' + V + '</TD></TR>');
  32.     end;
  33.  
  34.   var
  35.     I, P: integer;
  36.     N, V: string;
  37.   begin
  38.     with AResponse.Contents do
  39.     begin
  40.       BeginUpdate;
  41.       try
  42.         Add('<HTML><TITLE>FPC CGI Test page</TITLE><BODY>');
  43.         Add('<H1>Hello world</H1>');
  44.         DumpRequest(ARequest, AResponse.Contents);
  45.         Add('<H1>CGI environment:</H1>');
  46.         Add('<TABLE BORDER="1">');
  47.         Add('<TR><TD>Name</TD><TD>Value</TD></TR>');
  48.         for I := 1 to GetEnvironmentVariableCount do
  49.         begin
  50.           V := GetEnvironmentString(i);
  51.           P := Pos('=', V);
  52.           N := Copy(V, 1, P - 1);
  53.           system.Delete(V, 1, P);
  54.           AddNV(N, V);
  55.         end;
  56.         Add('</TABLE>');
  57.         Add('</BODY></HTML>');
  58.       finally
  59.         EndUpdate;
  60.       end;
  61.     end;
  62.   end;
  63.  
  64.  
  65.   function TMyCGIApp.InitializeWebHandler: TWebHandler;
  66.   begin
  67.     Result := TMyCgiHandler.Create(self);
  68.   end;
  69.  
  70.  
  71. begin
  72.   with TMyCGIApp.Create(nil) do
  73.   try
  74.     Initialize;
  75.     Run;
  76.   finally
  77.     Free;
  78.   end;
  79. end.
  80.  




Martin_fr

  • Administrator
  • Hero Member
  • *
  • Posts: 9691
  • Debugger - SynEdit - and more
    • wiki
Re: how to debug a CGI from Lazarus
« Reply #5 on: December 12, 2023, 01:49:40 pm »
That will work in a shell. But if the IDE (the debugger) starts the exe, then shell stuff doesn't happen.

question:
is it for the same reason that if I use the REQUEST_METHOD environment variable set to GET, the debugger works correctly
whereas if I set it to POST it crashes on the Run statement?

Not sure about your question.
First of all, what crashes, the debugger or your app in the debugger?

But anyway, about the differences between running outside or inside the IDE (or inside an http server)

If you give a shell the command-line
Code: Text  [Select][+][-]
  1. ./myapp --data=~/data.txt >/tmp/log.txt

The shell will translate this. The shell will replace ~ with your home dir.
The shell will open the file /tmp/log.txt and set stdout to it.

Your app gets executed with the param "--data=/home/username/data.txt" and it gets a handle for stdout.

The http server also set stdout, and it does set additional environment.

---
The debugger does not translate "~".
And the debugger does not set stdout/stdin

The only thing the debugger currently does is set environment, if you specify it.


Quote
follow example code

Code: Pascal  [Select][+][-]
  1. #!/usr/bin/instantfpc
  2. program TestCgi;
  3.  

"instantfpc" doesn't matter to the debugger => you must have compiled the code, or set up the IDE to have it compiled before the debugger starts.

Another difference here.

A shell will look into the file, and recognize it starts with #!.
The shell will then call
  /usr/bin/instantfpc  the_file

The debugger will not do that. It expects an executable binary (with machine code in it).




Actually about stdin/stdout

Go to Tools > Options > Debugger > Backend
and choose "Gdb GNU debugger"
==> I think this should set up your stdin, if in "run parameters" you specify " <somefile "




What is planned....

* stdin/stdout
There is an open issue, and plans to implement stdin/stdout redirection to work with FpDebug.

That does not include piping between commands like "echo 123 | yourapp"


* ~  (and others)
Not planned (Though the ~ would be trivial)

* #!
Not planned
At least not from the debuggers perspective. If someone implements that on the IDE side, so it would be done before the debugger gets involved, .... But I have no knowledge that anyone is looking at it.


nomorelogic

  • Full Member
  • ***
  • Posts: 165
Re: how to debug a CGI from Lazarus
« Reply #6 on: December 13, 2023, 09:32:10 am »
thank you for your attention and answers
really appreciated

regarding what I called "crash" above:
Lazarus debugging works fine with InstantFpc projects: it simply ignores the initial shebang and then treats the project like any pascal project.
However, when I set REQUEST_METHOD = POST (or PUT) in the environment variables and proceed with debugging, when execution is paused on the 'Run' instruction (line 75 of the code above) and I then proceed with 'Step Into' or 'Step Over', the debugger and the IDE freeze and control will not return until the debugger is stopped manually.
I get the idea that at that moment the debugger waits for input that will never arrive. Of course, I do not know if this impression is correct.

On the other hand, when I start the debugger with REQUEST_METHOD = GET, I don't encounter any problems: everything works perfectly.

As soon as possible I will try "Gdb GNU debugger" as suggested.

Thanks again.

MarkMLl

  • Hero Member
  • *****
  • Posts: 6576
Re: how to debug a CGI from Lazarus
« Reply #7 on: December 13, 2023, 10:37:40 am »
As soon as possible I will try "Gdb GNU debugger" as suggested.

Note that Martin specifically suggested the *Remote* debugger. I've used this in the past for various things, but there's a bit of a question mark over it now that the IDE is moving to fpDebug.

Alternatively, have you tried starting your program as normal and then getting the IDE to attach the debugger to it?

What OS etc. are you running? To what extent does the web server require elevated privilege?

MarkMLl
MT+86 & Turbo Pascal v1 on CCP/M-86, multitasking with LAN & graphics in 128Kb.
Pet hate: people who boast about the size and sophistication of their computer.
GitHub repositories: https://github.com/MarkMLl?tab=repositories

Martin_fr

  • Administrator
  • Hero Member
  • *
  • Posts: 9691
  • Debugger - SynEdit - and more
    • wiki
Re: how to debug a CGI from Lazarus
« Reply #8 on: December 13, 2023, 10:44:39 am »
As soon as possible I will try "Gdb GNU debugger" as suggested.

Note that Martin specifically suggested the *Remote* debugger. I've used this in the past for various things, but there's a bit of a question mark over it now that the IDE is moving to fpDebug.

With regards to setting a redirected stdin => the normal gdb debugger should be enough. (at least with the gdb version I tested on Windows.

Martin_fr

  • Administrator
  • Hero Member
  • *
  • Posts: 9691
  • Debugger - SynEdit - and more
    • wiki
Re: how to debug a CGI from Lazarus
« Reply #9 on: December 13, 2023, 11:11:10 am »
As MarkMLI asked: What OS are you using?

regarding what I called "crash" above:
Lazarus debugging works fine with InstantFpc projects: it simply ignores the initial shebang and then treats the project like any pascal project.
However, when I set REQUEST_METHOD = POST (or PUT) in the environment variables and proceed with debugging, when execution is paused on the 'Run' instruction (line 75 of the code above) and I then proceed with 'Step Into' or 'Step Over', the debugger and the IDE freeze and control will not return until the debugger is stopped manually.
I get the idea that at that moment the debugger waits for input that will never arrive. Of course, I do not know if this impression is correct.

To me "the IDE freeze" would mean that you can't even move the caret in the source editor anymore. You can't use any menus, and do nothing with the IDE?

Because I just tested your project, and my IDE kept working (then again, I am using the latest version 3.99 / but 3.0 RC should be the same)

As for the app, yes it waits forever. The CGI will want to read the STDIN until EOF. But its connected to the "View > Debug Windows > Console in/output", which delivers keystrokes from the keyboard (if focused). And which never gets to EOL.
Hence yes, your CGI app will wait forever.

But I also checked: Using "gdb" I could supply a command line ("run parameters"):  </home/name/somefile.txt
And then your app would process it, and print some html.

Mind that I entered </home/name  and not <~/somefile => because ~ will not work.

nomorelogic

  • Full Member
  • ***
  • Posts: 165
Re: how to debug a CGI from Lazarus
« Reply #10 on: December 13, 2023, 03:16:41 pm »
@MarkMLl
I am working under Linux Devuan and use Apache as my web server.


@Martin_fr
I expressed myself wrongly, the ide works as you described, it is the debugging that freezes
in the sense that it is perpetually waiting.

I tried with gdb and putting in the "run parameters" an input file like: /home/user/testdata.dat
the debugger works even with POST!

I thank everyone!


 

TinyPortal © 2005-2018