Jump to content
omnibrain

Adding (CORS) Headers for simple fileserving THttpServer

Recommended Posts

I threw together a simple file serving THttpServer to host some local data (mainly static JSON to emulate some APIs). But now I need to add a "Access-Control-Allow-Origin: *" header. Where would I do this.

My server code is literally not more than:

  HttpServer1.DocDir:='C:\temp;
  HttpServer1.Port:='16010';
  HttpServer1.Addr:='127.0.0.1';
  HttpServer1.Start();

 I tried to add an "OnBeforeAnswer"-Handler, but I'm totally lost.

procedure Tffileserver.HttpServer1BeforeAnswer(Sender, Client: TObject);
begin
  var lclient:=THttpConnection(client);
  lclient.SendHeader('Access-Control-Allow-Origin: *');
end;

 

Share this post


Link to post

You can add it in OnCommang* event handler

 

  AResponseInfo.CustomHeaders.Add('Access-Control-Allow-Origin: *');
  AResponseInfo.CustomHeaders.Add('Access-Control-Allow-Methods: GET, POST, PUT, DELETE');
  AResponseInfo.CustomHeaders.Add('Access-Control-Allow-Headers: Origin, X-Requested-With, Content-Type, Accept');

 

Share this post


Link to post

There are various methods for sending web server responses, SendDocument has a CustomHeaders property where you put complete header lines, while AnswerPage, AnswerStream, AnswerString, etc have a Header property that does the same.  You don't need to use an event.

 

Angus

 

Share this post


Link to post
32 minutes ago, Angus Robertson said:

There are various methods for sending web server responses, SendDocument has a CustomHeaders property where you put complete header lines, while AnswerPage, AnswerStream, AnswerString, etc have a Header property that does the same.  You don't need to use an event.

I don't use any of them. I use the "automatic serving of the contents of the DocDir" method. So I think I would have to use the events, I guess. But where can I add a custom header to the automatic response?

 

Do I need to create my derived "myHttpConnection" class and override "ProcessGet"?

Edited by omnibrain

Share this post


Link to post

I found something I overlooked earlier: The PersistentHeader property might be useful.

But there might be a bug in THttpConnection.SendHeader. I looks like, that in adding the PersistentHeader the second #$d#$a at the end of the headers might gets omitted. That means, that the blank line between headers and body is missing.

Share this post


Link to post

SendHeader is really an internal function, it is called during most of the other Send/Answer methods, and will send any PersistentHeader property lines, together with headers specified by the Send/Answer functions, that may also add their own headers.  Only use SendHeader if you are using low level functions like Send and SendStream.

 

You can use the onRespHdr event to log the headers actually being sent, to check they are correct.

 

Angus

 

Share this post


Link to post

You might have misunderstood me. I did not use "SendHeader" by myself. I just initialised

PersistentHeader:='Access-Control-Allow-Origin: *'

before starting the server. Then I wondered why my browser hung accessing the served files and why Postman chocked on the headers. So I debugged into the "SendHeader" function and saw there, that it loses the second CRLF at the end of the header when adding the PersistentHeader.

I guess that leads to a missing blank line between header and body, but I did not go that low level while debugging.

 

My workaround is to add a CRLF to the end of the PersistentHeader when I set it in my Program. But I think (at least from an UX standpoint) that should not be necessary.

Edited by omnibrain

Share this post


Link to post

The SendHeader function does not add any line endings to PersisentHeaders, each header line requires a line ending, including the last header.  Changing that now would break all existing web servers.

 

Angus

  • Like 1

Share this post


Link to post
7 minutes ago, Angus Robertson said:

The SendHeader function does not add any line endings to PersisentHeaders, each header line requires a line ending, including the last header

How should I have known? I figured it out in the end, so it wasn't too difficult after all...

8 minutes ago, Angus Robertson said:

Changing that now would break all existing web servers.

I understand. That totally makes sense.

Share this post


Link to post
On 11/3/2022 at 7:24 PM, Angus Robertson said:

Changing that now would break all existing web servers.

Maybe add CRLF's conditionally?

Edited by Fr0sT.Brutal

Share this post


Link to post

Conditionally added CRLF to a header line is certainly possible, but it would be better done when the properties are set. 

 

I'm planning a new multi-threaded web server which will be an opportunity to clean up legacy problems with the existing server that has evolved over 25 years. 

 

Angus

 

  • Like 1

Share this post


Link to post
49 minutes ago, Angus Robertson said:

but it would be better done when the properties are set

That will lead to surprising behavior.
 

const Hdr = '...';
serv.PersistentHeader := Hdr;
Assert(serv.PersistentHeader = Hdr); // BANG

 

Share this post


Link to post

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
×