[SOLVED] how to debug a CGI from Lazarus
lazarus / 38-Networking and Web Programming
----------------------------------------------------------------------
nomorelogic · 2023-12-07 17:40
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
----------------------------------------------------------------------
Martin_fr · 2023-12-07 19:23
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 · 2023-12-07 21:56
what about ?
pgm "`cat cx.txt`"
deal with what is in file cx.txt in the pgm as paramstr 1
----------------------------------------------------------------------
Martin_fr · 2023-12-07 22:29
Quote from: toby on December 07, 2023, 10:56:02 pmwhat 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 · 2023-12-12 12:27
Quote from: Martin_fr on December 07, 2023, 11:29:31 pmQuote from:
toby on December 07, 2023, 10:56:02 pmwhat 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][+][-]window.onload = function(){var x1 =
document.getElementById("main_content_section"); if (x1) { var x =
document.getElementsByClassName("geshi");for (var i = 0; i
#!/usr/bin/instantfpcprogram TestCgi;{$mode objfpc}{$H+} uses
Classes, SysUtils, httpDefs, fpweb, custweb, custcgi,
webutil; type TMyCGIHandler = class(TCgiHandler) public procedure
HandleRequest(ARequest: Trequest; AResponse: TResponse); override;
end; TMyCGIApp = class(TCustomCGIApplication) protected
function InitializeWebHandler: TWebHandler; override; end;
procedure TMyCGIHandler.HandleRequest(ARequest: Trequest; AResponse:
TResponse); procedure AddNV(const N, V: string); begin
AResponse.Contents.Add('
| ' + N + ' | ' + V +
' |
'); end; var I, P: integer; N, V: string;
begin with AResponse.Contents do begin BeginUpdate;
try Add('FPC CGI Test page');
Add('Hello world
'); DumpRequest(ARequest,
AResponse.Contents); Add('CGI environment:
');
Add('');
Add('| Name | Value |
'); for I := 1 to
GetEnvironmentVariableCount do begin V :=
GetEnvironmentString(i); P := Pos('=', V); N :=
Copy(V, 1, P - 1); system.Delete(V, 1, P); AddNV(N,
V); end; Add('
'); Add('');
finally EndUpdate; end; end; end; function
TMyCGIApp.InitializeWebHandler: TWebHandler; begin Result :=
TMyCgiHandler.Create(self); end; begin with TMyCGIApp.Create(nil)
do try Initialize; Run; finally Free; end;end.
----------------------------------------------------------------------
Martin_fr · 2023-12-12 12:49
Quote from: nomorelogic on December 12, 2023, 01:27:17 pmQuote from:
Martin_fr on December 07, 2023, 11:29:31 pmThat 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][+][-]window.onload = function(){var x1 =
document.getElementById("main_content_section"); if (x1) { var x =
document.getElementsByClassName("geshi");for (var i = 0; i ./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.
Quotefollow example code
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
#!/usr/bin/instantfpcprogram TestCgi;
"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 " the normal gdb debugger
should be enough. (at least with the gdb version I tested on Windows.
----------------------------------------------------------------------
Martin_fr · 2023-12-13 10:11
As MarkMLI asked: What OS are you using?
Quote from: nomorelogic on December 13, 2023, 09:32:10 amregarding
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"): because ~ will
not work.
----------------------------------------------------------------------
nomorelogic · 2023-12-13 14:16
@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!