#1 2012-01-06 10:03:34

esmondb
Member
From: London
Registered: 2010-07-20
Posts: 299

using POST with Client-Server Services

Could Post requests be made possible with the SOA part of the framework?

I want to upload a jpeg file, using an html form, from a javascript client. I've had a go changing the http method in TSQLite3HttpServer.Request from 'post' to 'get' forcing TSQLRestServer.URI to process the request. This works OK but uploading a large file over a slow connection blocks any other requests to the server until the transfer's finished. Is there a simple way to do this without blocking the server?

Offline

#2 2012-01-06 10:45:24

ab
Administrator
From: France
Registered: 2010-06-21
Posts: 14,660
Website

Re: using POST with Client-Server Services

The server is multi-threaded.

I suspect the issue is on the client side.

Offline

#3 2012-01-06 12:36:06

esmondb
Member
From: London
Registered: 2010-07-20
Posts: 299

Re: using POST with Client-Server Services

I'm not sure it's on the client side as I'm testing with two clients on separate computers (using http://blueimp.github.com/jQuery-File-Upload/). The server (using http.sys) is multi-threaded while it processes the request but only seems able to handle recieving requests in series. It's puzzling - can you suggest where I'm going wrong?

Below is the start of my server function - does the session access look OK?

Thanks

function TServiceServer.upload(aSession: Cardinal; aRecord: TSQLRecord; aParameters: PUTF8Char;
      const aSentData: RawUTF8; var aResp, aHead: RawUTF8): Integer;
var
  sess : TAuthSession;
  hasAccess : boolean;
begin
  EnterCriticalSection(fSessionCriticalSection);
  try
    sess := SessionAccess(aSession);
    hasAccess := (1 in sess.AccessRights.POST);
  finally
    LeaveCriticalSection(fSessionCriticalSection);
  end;
  if hasAccess then begin
  ...
  end;
end;

Offline

#4 2012-01-06 13:38:57

ab
Administrator
From: France
Registered: 2010-06-21
Posts: 14,660
Website

Re: using POST with Client-Server Services

Using http.sys, you'll have to CLONE the server threads to make it explicitly multi-threaded.

See THttpApiServer.Clone method.

Offline

#5 2012-01-06 14:25:46

esmondb
Member
From: London
Registered: 2010-07-20
Posts: 299

Re: using POST with Client-Server Services

What does this note above THttpApiServer.Clone mean?
// - will work only if the OnProcess property was set
I cann't see any other reference to OnProcess.

It's also mentioned on page 266 of the SAD documentation.

Offline

#6 2012-01-06 14:55:47

ab
Administrator
From: France
Registered: 2010-06-21
Posts: 14,660
Website

Re: using POST with Client-Server Services

It means that the OnProcess property should be already set before the THttpApiServer.Clone method is called.

For our mORMot server as defined in SQlite3HttpServer, this is always the case.
The TSQLite3HttpServer.Create() constructor set the OnProcess property to its internal TSQLite3HttpServer.Request method.

In fact, the TSQLite3HttpServer.Create() constructor also call Clone:

  if fHttpServer.InheritsFrom(THttpApiServer) then
    // allow fast multi-threaded requests
    THttpApiServer(fHttpServer).Clone(SystemInfo.dwNumberOfProcessors-1);

In fact, the parameter used sounds a bit too small for best concurrent access process.

I've added a ServerThreadPoolCount parameter to TSQLite3HttpServer.Create() constructor, set by default to 32.
See http://synopse.info/fossil/info/6464f1ac45
It should help multi-threading process.

Offline

#7 2012-01-09 00:54:14

esmondb
Member
From: London
Registered: 2010-07-20
Posts: 299

Re: using POST with Client-Server Services

Great, thanks got it working.

I've got another problem, probably unrelated, with authentication timestamp coherency. The server and client are on the same computer (mormot server and firefox client) and about 20% of the time I'm getting 403 errors when sending two requests immediately after each other (to be processed together in javascript). There's no problem if the server and client are on different machines (so it's not much of an issue) or if I add 500ms leeway to TAuthSession.IsValidURL when they're on the same machine.  Is there a limit to how close timestamps are in the signature? Below is the log from the firebug console when it isn't working - strangely some of the requests are responded to in negative time which must be impossible, but this also occasionally happens when the requests go through without a problem.

GET http://localhost:8080/root/TimeStamp 200 OK 164ms
GET http://localhost:8080/root/auth?UserName=Guest 200 OK -6ms
GET http://localhost:8080/root/auth?UserName=Guest&Password=83bf9bc2feb7c4133125eef1021a5e142bd2636b3ee1b135b57f86555fd4425d&ClientNonce=32d8ca66ae1537411d2f1940cb52e1f136af024c4ac98f402ecf8cccc1f260f2 OK -19ms
GET http://localhost:8080/root/EWPicRec?Select=count(*)+as+total&Where=&session_signature=0000006f00000208ee735494 403 Forbidden 13ms
GET http://localhost:8080/root/EWPicRec?Select=*&StartIndex=0&Results=51&Where=&session_signature=0000006f00000211a6d19bd3 200 OK 15ms

btw do you mean OnRequest instead of OnProcess.

Offline

#8 2012-01-09 06:48:06

ab
Administrator
From: France
Registered: 2010-06-21
Posts: 14,660
Website

Re: using POST with Client-Server Services

Yes, the THttpServerGeneric.OnRequest event points to TSQLite3HttpServer.Request.
I made a confusion with THttpServer.Process method which is not involved here.

About the 403 Forbidden issue, I do not have such problem with the client coded in Delphi.
So I guess there is something wrong in the javascript client code.

Offline

#9 2012-01-09 19:34:53

esmondb
Member
From: London
Registered: 2010-07-20
Posts: 299

Re: using POST with Client-Server Services

With the 403 Forbidden issue there was only a couple of miliseconds between two http requests and they seemed to occasionally arrive at the server in a swapped order. I've solved it by forcing a pause between the javascript requests.

Offline

#10 2012-05-17 11:54:37

mpv
Member
From: Ukraine
Registered: 2012-03-24
Posts: 1,571
Website

Re: using POST with Client-Server Services

In your case 403 Forbidden is not because a couple of miliseconds between two http requests, but because http request is going from browser in async way. Do each next request after getting response from previous, and all will be OK.
Pause is not a good solution.

Offline

#11 2012-05-18 05:47:18

esmondb
Member
From: London
Registered: 2010-07-20
Posts: 299

Re: using POST with Client-Server Services

I'm using jquery's ajax function and in the end found that setting the option async:false solved it.

Offline

#12 2012-05-18 07:25:26

mpv
Member
From: Ukraine
Registered: 2012-03-24
Posts: 1,571
Website

Re: using POST with Client-Server Services

It's a solution, but it not good - setting async:false will block current browser page. The best(and right in javaScritp world) way is async call and making next request in success callback function. Something like jquery.ajax({....., success: function(){.... jquery.ajax(....);}).  There are many solutions how to get round the problem of nested function calls - events for example. (I don't know how do in in jquery - I'm not use jquery).

Offline

Board footer

Powered by FluxBB