how to do a HTTP POST with sockets lazarus / 38-Networking and Web Programming ---------------------------------------------------------------------- Key-Real · 2023-06-03 02:36 Hi, I'm trying to send a SOAPAction to my Router. It looks like this: 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 {$MODE OBJFPC} {$H+}uses    sockets, SysUtils; procedure SocketError(s:string);begin    writeln('Socket Error: ', s);    halt(1);end; const        MS : string =                  'POST /upnp/control/WANIPConnection0 HTTP/1.1' + #$0d + #$0a +              'SOAPAction: "urn:schemas-upnp- org:service:WANIPConnection:1#AddPortMapping"' + #$0d + #$0a +              'Host: 192.168.0.4:49153' + #$0d + #$0a +                'Content-Type: text/xml' + #$0d + #$0a +                'Content- Length: '; var        socket : longint;        addr : sockaddr_in;      f : text;        post : string;        s : string;begin        assignfile(f, 'add.xml');        reset(f);        post:= '';        repeat                readln(f, s);                post:= post + s + #$0a + #$0d;        until eof(f);        close(f);         ms:=ms + intToStr(length(post)) + #$0d + #$0a + #$0d + #$0a + post + #$0d +#$0a;         writeln(ms);         socket:= fpsocket(AF_INET, SOCK_STREAM, IPPROTO_TCP);        if socket = -1 then SocketError('Init Socket');         fillchar(addr, 0, sizeof(addr));      addr.sin_family:= AF_INET;        addr.sin_addr:= StrToNetAddr('192.168.0.1');        addr.sin_port:= htons(49153);       if fpconnect(socket, @addr, sizeof(addr)) < 0 then SocketError('unable to connect');         //if fpsendto(socket, pchar(MS), length(MS), 0, @addr, sizeof(addr)) = -1 then SocketError('send MS message');          if fpsend(socket, @ms, sizeof(ms), 0) < 0 then SocketError('unable to send');     closeSocket(socket);end. my add.xml: 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             It is my uPnP test        0        192.168.0.4        True        3333                UDP        3333      so my question: Do I do the HTTP POST request right? ---------------------------------------------------------------------- dbannon · 2023-06-03 04:00 Have you considered  fcl-web ? https://wiki.freepascal.org/fpWeb_Tutorial In use, about line 1321 of https://github.com/tomboy-notes/tomboy- ng/blob/master/source/transgithub.pas where I talk to github with POST. Davo ---------------------------------------------------------------------- Warfley · 2023-06-03 10:02 I don't know why you would want to implement HTTP yourself, but if you really want to do, to use HTTPS you must use TLS. You can either directly use the openssl unit and use the functions like "sslConnect" instead of "fpConnect" (of course requires to setup an ssl context first, but thats just a bit of boilerplate code), as described here (for C): https://stackoverflow.com/questions/7698488/turn-a-simple-socket-into- an-ssl-socket Or you can use the ssockets (+opensslsocket) units instead: 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 uses  ssockets, opensslsockets; var  Sock: TInetSocket;begin  Sock := TInetSocket.Create('127.0.0.1', 1337, TOpenSSLSocketHandler.create);  try    Sock.Connect;    Sock.Write('Hello World'[0], Length('Hello WOrld'));  finally    Sock.Free;  end;end. ---------------------------------------------------------------------- edap · 2023-06-03 11:19 Consider using mORMot2 unit https://github.com/synopse/mORMot2/blob/ma ster/src/net/mormot.net.client.pas in folder https://github.com/synopse/mORMot2/tree/master/src ---------------------------------------------------------------------- rvk · 2023-06-03 13:51 Quote from: Warfley on June 03, 2023, 12:02:52 pmI don't know why you would want to implement HTTP yourself, but if you really want to do, to use HTTPS you must use TLS. Seeing the code this is not https. It's for UPnP to a router which is simple HTTP. So just using THttpSend from Synapse or fcl-web is enough. (I've done UPnP with THttpSend) ---------------------------------------------------------------------- Key-Real · 2023-06-15 19:11 I'm writing a bigger program and I do not wanna use 3rd Party Libraries like Synapse etc. I'm working with the socket unit. So I'm trying to do a HTTP Post only with Raw Sockets. Can you please provide an example? ---------------------------------------------------------------------- rvk · 2023-06-15 20:01 Quote from: Key-Real on June 15, 2023, 09:11:33 pmI'm writing a bigger program and I do not wanna use 3rd Party Libraries like Synapse etc. I'm working with the socket unit. So I'm trying to do a HTTP Post only with Raw Sockets. Can you please provide an example? I can't provide an example for raw sockets. I could adjust the example from earlier with the standard fcl-web package (which should be installed as default) but with using raw sockets it would become much more complex. Why are you against using fcl-web? Or can you provide simple raw socket code (with the emphasis on simple)? ---------------------------------------------------------------------- Key-Real · 2023-06-16 06:34 I'm not using Lazarus, the Project is in pure FPC ---------------------------------------------------------------------- rvk · 2023-06-16 06:39 Quote from: Key-Real on June 16, 2023, 08:34:33 amI'm not using Lazarus, the Project is in pure FPC Fcl-web is pure FPC. Nothing to do with Lazarus. Don't you have a $(fpcdirectory)\packages\fcl-web directory? ---------------------------------------------------------------------- rvk · 2023-06-16 12:02 I changed my example with just using fcl-web and socket. It works out of the box on Windows and Linux with only FPC. https://github.com/rvk01/upnp ---------------------------------------------------------------------- TRon · 2023-06-16 12:44 Quote from: rvk on June 16, 2023, 02:02:08 pmI changed my example with just using fcl-web and socket. Thank you for your class. Tested on my machine (Linux x86_64 with upnp disabled on my router). At creation of the class: The broadcast option seems to do as suggested as it returns a zero then setting the timeout returns a -1 for me (edit: should that not be a ttimeval struct = 2x 64 bit on 64-bit Linux ?). The following bind also returns a -1 for me. Strangely enough the sendto then returns a 101 to finally "hang" indefinitely at the call to fprecvfrom. Not knowing how serious you wish the class to be(come) I thought to mention it. ---------------------------------------------------------------------- rvk · 2023-06-16 13:33 Quote from: TRon on June 16, 2023, 02:44:57 pmNot knowing how serious you wish the class to be(come) I thought to mention it. It should at least work on Windows and Linux with Router UPnP enabled and disabled. I've just switched to socket (from Synapse) so it could contain some bugs. But I've just tested it here and even when disabling the UPnP, it timeout correctly for me. Quote from: TRon on June 16, 2023, 02:44:57 pmThe broadcast option seems to do as suggested as it returns a zero then setting the timeout returns a -1 for me (edit: should that not be a ttimeval struct = 2x 64 bit on 64-bit Linux ?). Yes, Thank you. I fixed that one. Quote from: TRon on June 16, 2023, 02:44:57 pmThe following bind also returns a -1 for me. Strangely enough the sendto then returns a 101 to finally "hang" indefinitely at the call to fprecvfrom. I'm not entirely sure the fpbind() is needed. I can comment it out and it still works for me (I receive several other M-SEARCH results). I'm new to the whole raw sockets so there might be an easier way to do this in fpc (maybe with fcl-net). It works now for me when UPnP is disabled (it searches and waits about 6 seconds before giving up). If it still hangs for you I need to look at the timeouts again. ---------------------------------------------------------------------- TRon · 2023-06-16 13:42 @rvk: switching to struct ttimeval lets the setsocket option succeed and also will now correctly "stop" the call to receive when the timeout occurs. Thank you ! The raw sockets themselves is not that difficult (I take my queue from examples written with/for bsdsockets) but I have never searched for how upnp works with bsdsockets (nor was I able to find something useful when key-real asked for it). ---------------------------------------------------------------------- Key-Real · 2023-06-17 17:24 @rvk: I tested Your lib under windows, it doesn't work It tells me: "UPnP is not available." under Linux it works perfect, I tested it. under Mac it looks good, it does the job but I can't verify if it succeed. ---------------------------------------------------------------------- rvk · 2023-06-17 17:36 Quote from: Key-Real on June 17, 2023, 07:24:42 pmI tested Your lib under windows, it doesn't work It tells me: "UPnP is not available."Not sure why. I just tested it here one last time and it works. You could put a writeln(S) in the Create() (just below the SetLength() on line 140). Just to see if you receive some M-SEARCH discover packets. Maybe it can fail with multiple network interfaces. But here it worked on Windows and Linux. In that case you can try to do UPnP := TUPnP.Create('192.168.0.1'); in your upnptest.lpr. QuoteUPnP device is available at http://192.168.2.1:35608/ctl/IPConn Internal IP: 192.168.2.11 External IP: x.x.x.x Status: Connected Last error: ERROR_NONE Uptime router: 26 days 12 hours 20 minutes and 17 seconds SetPortMapping OK Portmappings: 0 TCP 8000->192.168.2.11:8081  0 s Check port. Press Enter to delete and terminate DeletePortMapping OK No portmappings We are done, press enter Quote from: Key-Real on June 17, 2023, 07:24:42 pmunder Mac it looks good, it does the job but I can't verify if it succeed. If the output is as above then it should work fine. If, after that, the port doesn't seem open, then it must be something in the program or the mac itself blocking the port. This code can only deal with the UPnP part of the router. BTW. There also seems to be something like NAT-PMP and PCP. But I'm not familiar with that. ---------------------------------------------------------------------- Key-Real · 2023-06-17 17:39 I will try to debug it later. Under Mac it looks good