#1 Re: mORMot 2 » does mOrMot work with http/3 ? » 2025-09-10 14:26:13

Thanks @AB, so i will definitively stay with http.sys

#2 mORMot 2 » does mOrMot work with http/3 ? » 2025-09-10 14:18:58

loki
Replies: 2

hi,

does mOrMot work with http/3 ? i know that http.sys support http/3 from windows 2022, but without http.sys does mOrMot work with http/3 ?
Http/3 is really a big jump as it's not use anymore traditional TCP

#4 Re: mORMot 2 » how many worker threads does mOrMot + http.sys use ? » 2025-09-09 11:22:22

Thanks @AB. Do you think it would be hard for me to update your code so that your http.sys implementation works with IOCP? Honestly, I can’t imagine any API server that won’t at least make a TCP request (most often a database request), so updating your implementation to IOCP could be a great improvement (I think). Do you see any problems I might run into, or any good reason not to do this?

#5 Re: mORMot 2 » how many worker threads does mOrMot + http.sys use ? » 2025-09-09 07:54:48

I get the point about 32 processing threads and thousands of idle connections being fine when the workload is truly CPU-bound. In my case, though, most endpoints perform I/O-bound work (e.g., calling external HTTP APIs or a DB over TCP). The latency is primarily waiting on upstream, not burning CPU. So a fixed cap of 32 worker threads means that, with 42 in-flight requests waiting on upstream, 10 will indeed queue up even though the machine is mostly idle.

I have a few questions:

* Handling I/O-bound work: How do you recommend handling these cases? Can the thread pool auto-scale when many handlers are waiting on external I/O? And can mORMot use IOCP when running with HTTP.SYS?

* Default thread count: Why is the default 32 threads? If the workload were purely CPU-bound (no blocking I/O—which is uncommon since there’s almost always at least a DB call), wouldn’t it make more sense to default to number-of-processors instead?

Thanks!

#6 Re: mORMot 2 » how many worker threads does mOrMot + http.sys use ? » 2025-09-08 21:41:26

Thanks @AB. I see ServerThreadPoolCount is set to 32. Does that mean 32 threads are created by default? If there are, say, 42 concurrent requests, will the extra 10 wait for a free thread, or am I misunderstanding?

#7 mORMot 2 » how many worker threads does mOrMot + http.sys use ? » 2025-09-08 20:18:23

loki
Replies: 8

hello,

how many worker threads does mOrMot + http.sys use ? Globally how the threads are managed with mOrMot + http.sys ?

thanks by advance

#8 Re: mORMot 2 » Serve multiple hostnames on one IP with separate mORMot binaries » 2025-08-19 18:34:14

pvn0 wrote:

Another thumbs up for nginx, also just this week they announced ACME support so it will be even easier then ever to auto renew ssl certificates (such as LetsEncrypt).

koraycayiroglu wrote:

Another thumbs up, nginx is the way to go

Yes, but NGINX isn’t really designed for Windows, and even its own developers do not recommend running it there.
(see: https://nginx.org/en/docs/windows.html
: “high performance and scalability should not be expected”).

That’s why I’m still wondering: is it really a good idea to replace IIS + ISAPI with NGINX (limited on Windows) + mORMot?

#9 Re: mORMot 2 » Serve multiple hostnames on one IP with separate mORMot binaries » 2025-08-19 12:41:04

Thanks @AB, yes i do not use any php. I will study http.sys with mORMot thanks a lot !

#10 Re: mORMot 2 » Serve multiple hostnames on one IP with separate mORMot binaries » 2025-08-19 06:26:28

Thanks @ab. I need to think about it, because that means in the end I’d be replacing my current IIS + ISAPI setup with an NGINX + mORMot setup. I’m not sure it would really be less complex. sad The goal was to have a single binary for each of my website that I could just deploy to get the website running (plus configuring the firewall, of course).

#11 mORMot 2 » Serve multiple hostnames on one IP with separate mORMot binaries » 2025-08-18 11:55:13

loki
Replies: 11

I need to host several sites on the same server/IP, for example:

* api.mydomain.com → API service
* www.mydomain.com → website

Each must run in its own mORMot binary/process (not in one app).

Questions:

* Is it possible for two mORMot processes to both listen on port 80/443 and be split by hostname?
* On Windows/http.sys (THttpApiServer): can I register different hostnames so each process handles its own domain?

If reverse proxy is the only option:

Any mORMot-specific notes for X-Forwarded-For, TLS offload, HTTP/2, or WebSockets?

Goal:

* One IP address
* Separate binaries per site
* Clean HTTPS setup (Let’s Encrypt etc.)

What’s the recommended approach?

#12 Re: mORMot 2 » Migrating ISAPI App to Standalone HTTP Server with mORMot 2 » 2025-07-03 16:27:02

Thanks Arnaud smile If I'm not mistaken, there's actually more code in your IOCP server than in the http.sys wrapper, right? So theoretically, http.sys should be more stable and have fewer bugs than the IOCP implementation — even though you're an excellent programmer smile

Note: i ask the same to chatGPT, he know about mormot, and say : "IOCP Server (mORMot custom asynchronous server): More code to maintain (even if already well-written)"

#13 Re: mORMot 2 » Migrating ISAPI App to Standalone HTTP Server with mORMot 2 » 2025-07-03 15:14:53

Thanks, Arnaud! Do you have a sample showing how to use http.sys with mORMot?

Regarding your async socket server — and I may be wrong — I think http.sys might be more stable and efficient since it's built into Windows. For now, I'm not targeting Linux.

#14 mORMot 2 » Migrating ISAPI App to Standalone HTTP Server with mORMot 2 » 2025-07-02 20:11:33

loki
Replies: 5

Hello,

I have a large ISAPI application, and I’m looking to remove the dependency on IIS. Ideally, I’d like to switch to a standalone HTTP server to simplify deployment.

Is this possible with mORMot 2? Does it support HTTPS? And are there any example projects available to help get started?

Thank you very much for your help.
Best regards,
Stéphane

#15 Re: mORMot 1 » Base64Decode must raise exception if invalid characters are founded » 2018-01-21 17:27:11

great job Arnaud!
and again congratulation for you excellent work !!

#16 Re: mORMot 1 » Base64Decode must raise exception if invalid characters are founded » 2018-01-21 15:08:10

mvp, yes sorry about the code i post, it's even close to the same as the original but just with very little modification. I just added exception in case the input string is incorrect because as opposite to what Arnaud B. think, me i think it's a fundamental mistake to late a process to continue to work with false/random data, and it's can also open some breach in the security. But i will not argue about it, so forget my code i already did a fork of it for my own need.

the pascal implementation of base64 work very fast and it's a very great job !

#18 Re: mORMot 1 » Base64Decode must raise exception if invalid characters are founded » 2018-01-21 07:56:59

Base64ToBinSafe is not good to detect error!

function Base64ToBinSafe(sp: PAnsiChar; len: PtrInt; var data: RawByteString): boolean;
begin
  Base64ToBin(sp,len,data);
  result := data<>'';
end;

It's just check if the data <> '' but if the length of the sp look correct and you have invalid char in the middle of the SP then it's will NOT return you an empty data sad

about "The first rule is that raising exception should be exceptional - as its name states: exceptional. "

yes, sure but if Base64ToBin is not a function to return a result (success or not) then it's must return an exception else nothing will stop your program to work with invalid data!

as an example, it's like if strToint can not convert the str to an integer but instead of raising an exception it's return a random integer ....

#19 Re: mORMot 1 » Base64Decode must raise exception if invalid characters are founded » 2018-01-20 20:06:56

NOTE: to found that the pascal implementation is 2x more faster than the ASM implementation, i run in RELEASE mode

#20 Re: mORMot 1 » Base64Decode must raise exception if invalid characters are founded » 2018-01-20 20:04:49

this is the modification i did to have the best performance and the exception is invalid char founded in the input :

type
  TBase64Enc = array[0..63] of AnsiChar;
  TBase64Dec = array[AnsiChar] of shortint;
const
  b64enc: TBase64Enc =
    'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/';

var
  /// a conversion table from Base64 text into binary data
  // - used by Base64ToBin/IsBase64 functions
  // - contains -1 for invalid char, -2 for '=', 0..63 for b64enc[] chars
  ConvertBase64ToBin: TBase64Dec;

const
  sInvalidbase64String = 'Invalid base64 string';

{********************************************************************************************}
function Base64AnyDecode(const decode: TBase64Dec; sp,rp: PAnsiChar; len: NativeInt): boolean;
var c, ch: NativeInt;
begin
  result := false;
  while len>=4 do begin
    c := decode[sp[0]];
    if c<0 then
      exit;
    c := c shl 6;
    ch := decode[sp[1]];
    if ch<0 then
      exit;
    c := (c or ch) shl 6;
    ch := decode[sp[2]];
    if ch<0 then
      exit;
    c := (c or ch) shl 6;
    ch := decode[sp[3]];
    if ch<0 then
      exit;
    c := c or ch;
    rp[2] := AnsiChar(c);
    c := c shr 8;
    rp[1] := AnsiChar(c);
    c := c shr 8;
    rp[0] := AnsiChar(c);
    dec(len,4);
    inc(rp,3);
    inc(sp,4);
  end;
  if len>=2 then begin
    c := decode[sp[0]];
    if c<0 then
      exit;
    c := c shl 6;
    ch := decode[sp[1]];
    if ch<0 then
      exit;
    if len=2 then
      rp[0] := AnsiChar((c or ch) shr 4) else begin
      c := (c or ch) shl 6;
      ch := decode[sp[2]];
      if ch<0 then
        exit;
      c := (c or ch) shr 2;
      rp[1] := AnsiChar(c);
      rp[0] := AnsiChar(c shr 8);
    end;
  end;
  result := true;
end;

{*******************************************************************}
function Base64EncodeMain(rp, sp: PAnsiChar; len: cardinal): integer;
var i: integer;
    c: cardinal;
begin
  result := len div 3;
  for i := 1 to result do begin
    c := ord(sp[0]) shl 16 + ord(sp[1]) shl 8 + ord(sp[2]);
    rp[0] := b64enc[(c shr 18) and $3f];
    rp[1] := b64enc[(c shr 12) and $3f];
    rp[2] := b64enc[(c shr 6) and $3f];
    rp[3] := b64enc[c and $3f];
    inc(rp,4);
    inc(sp,3);
  end;
end;

{*******************************************************}
procedure Base64Decode(sp,rp: PAnsiChar; len: NativeInt);
begin
  len := len shl 2; // len was the number of 4 chars chunks in sp
  if (len>0) and (ConvertBase64ToBin[sp[len-2]]>=0) then
    if ConvertBase64ToBin[sp[len-1]]>=0 then else
      dec(len) else
      dec(len,2); // adjust for Base64AnyDecode() algorithm
  if not Base64AnyDecode(ConvertBase64ToBin,sp,rp,len) then
    raise Exception.Create(sInvalidbase64String);
end;

{***********************************************************************}
procedure Base64EncodeTrailing(rp, sp: PAnsiChar; len: cardinal); inline;
var c: cardinal;
begin
  case len of
    1: begin
      c := ord(sp[0]) shl 4;
      rp[0] := b64enc[(c shr 6) and $3f];
      rp[1] := b64enc[c and $3f];
      rp[2] := '=';
      rp[3] := '=';
    end;
    2: begin
      c := ord(sp[0]) shl 10 + ord(sp[1]) shl 2;
      rp[0] := b64enc[(c shr 12) and $3f];
      rp[1] := b64enc[(c shr 6) and $3f];
      rp[2] := b64enc[c and $3f];
      rp[3] := '=';
    end;
  end;
end;

{*******************************************************}
procedure Base64Encode(rp, sp: PAnsiChar; len: cardinal);
var main: cardinal;
begin
  main := Base64EncodeMain(rp,sp,len);
  Base64EncodeTrailing(rp+main*4,sp+main*3,len-main*3);
end;

{******************************************************}
function BinToBase64Length(len: NativeUInt): NativeUInt;
begin
  result := ((len+2)div 3)*4;
end;

{*******************************************************************}
function Base64ToBinLength(sp: PAnsiChar; len: NativeInt): NativeInt;
begin
  result := 0;
  if (len=0) then exit;
  if (len and 3<>0) then raise Exception.Create(sInvalidbase64String);
  if ConvertBase64ToBin[sp[len-2]]>=0 then
    if ConvertBase64ToBin[sp[len-1]]>=0 then
      result := 0 else
      result := 1 else
      result := 2;
  result := (len shr 2)*3-result;
end;

{***************************************************************************}
procedure Base64ToBin(sp: PAnsiChar; len: NativeInt; var result: AnsiString);
var resultLen: NativeInt;
begin
  resultLen := Base64ToBinLength(sp,len);
  if resultLen=0 then
    result := '' else begin
    SetString(result,nil,resultLen);
    Base64Decode(sp,pointer(result),len shr 2);
  end;
end;

#21 Re: mORMot 1 » Base64Decode must raise exception if invalid characters are founded » 2018-01-20 19:39:35

NOTE: also the purepascal implementation of Base64Encode is close to 2x more faster than the ASM implementation (I test it on tokyo)

#22 mORMot 1 » Base64Decode must raise exception if invalid characters are founded » 2018-01-20 19:25:59

loki
Replies: 11

Just one remark, i think that Base64Decode in syncommon.pas must raise an exception if invalid characters are founded in the input instead an returning random data

Board footer

Powered by FluxBB