How to use TIdHTTPSession in TIdHTTPServer? - delphi

I don't understand the idea of TIdHTTPSession in TIdHTTPServer. What is it for? Is it a kind of container for request, or what is it? How do I use it properly after I have enabled AutoSessionStart? And what will happen if I do not enable AutoSessions?
For example, say we have some shared resourse FMyMessages: TStringList; Then how should I request this shared resource with/without sessions?
TIdHTTPSession has an FLock: TIdCriticalSection; member - so maybe I should use it to lock my shared resource FMyMessages from other threads if I have AutoSessions, otherwise I should use my own critical section?
Also, how can I count Sessions in the moment? I tried like this but it doesn't work:
Server.Contexts.Count.ToString;

I don't understand the idea of TIdHTTPSession in TIdHTTPServer ? What is it for? Is it a kind of container for request, or what is it? How do I use it properly after I have enabled AutoSessionStart?
HTTP is a stateless protocol. It does not remember information from one request to the next. And it does not even guarantee or require that the TCP connection itself remain open between requests.
That is where sessions come into play. The server can create a session object to store information, such as during a client login, and that session's unique ID is sent to the client via an HTTP cookie, which the client can send back to the server on subsequent requests to reuse the same session object. Eventually, the session will timeout and be destroyed, if you do not end the session explicitly, such as during client logout.
And what will happen if I do not enable AutoSessions?
The server will simply not automatically create a new session object if one does not exist yet for each request. You would have to create a new session manually on an as-needed basis instead.
For example, say we have some shared resourse FMyMessages: TStringList; Then how should I request this shared resource with/without sessions?
Sessions have nothing to do with accessing shared resources, and everything to do with persisting per-client state data. Such as user logins, database connections, etc.
TIdHTTPSession has an FLock: TIdCriticalSection; member - so maybe I should use it to lock my shared resource FMyMessages from other threads if I have AutoSessions, otherwise I should use my own critical section?
No. You can use Indy's TIdThreadSafeStringList instead.
Also, how can I count Sessions in the moment? I tried like this but it doesn't work:
Server.Contexts.Count.ToString;
The Contexts property stores the active client TCP connections. That has nothing to do with HTTP sessions. Those are stored in the server's SessionList property instead.

Related

How to manage and reload multiple QuickFIX/J sessions independently?

I can configure multiple sessions in a single QuickFIX/J settings file and then start them all with a single SocketInitiator. But I would like to be able to modify the configuration of one or more sessions and then restart just those sessions without affecting any others.
I could do this by having multiple settings files and using one SocketInitiator per session. But it seems as though QuickFIX/J is not intended to be used this way. Would it cause me any problems?
It is perfectly fine to start up an Initiator per session. It is a matter of taste. In any case: having a separate Initiator per session is independent and will not affect the other sessions.
If you want to follow the approach with a single Initiator then you could try to add/remove sessions dynamically via createDynamicSession()/removeDynamicSession(). There still is some manual work though.
Find the Session that you want to reload. logout() and close() it.
Call removeDynamicSession() for that Session.
Get the settings for the SessionID that you want to reload from the running Initiator. Remove these from the running Initiator via removeSetting().
Then reload the settings from the settings file for the needed Session and put them to the settings of the Initiator.
Then call createDynamicSession() for the SessionID

Do constants stay the same for ALL users?

I have a web app that I built. It communicates with the Salesforce API. I have users and administrators. All connections to the API use the same credentials.
I am concerned that my API connection is going to be created multiple times because each admin that is logged in has their own instance of the connection.
If I hold the API connection in a constant, do all other sessions/users have access to that exact connection or do I have to connect for each user, or how can I share one single API connection for ALL users?
A stateless API will never have a persistent connection, so there's no use in holding these in constants. Every HTTP request is a separate TCP connection by definition.
It's only things like database or Websocket connections that persist and if you need to manage those you need a connection pool, not a simple constant. If the connection ever fails it needs to be replaced, and if more than one thread potentially requires it you have to handle acquisition and locking properly.
Create your API connectors as necessary. Unless you have a measurable performance problem don't worry about it.
A Ruby constant is like a variable, except that its value is supposed to remain constant for the duration of the program. The Ruby interpreter does not actually enforce the constancy of constants, but it does issue a warning if a program changes the value of a constant.
Reference: http://rubylearning.com/satishtalim/ruby_constants.html

Does a before_filter in the application controller slow down the app?

I have a few before_filter in my application controller to check 1) If the current_user is banned, 2) If the current_user has received a new message and 3) If the current_user has any pending friend requests.
This means that before every request the app will check for these things. Will this cause server issues in the future, possible a server overload?
I wouldn't definitely say that it would create a server overload on it's own, for a server overload you need many concurrent requests and rails have a connection pool to the database out of the box, but this will slow down the process as you have 3 queries before each request is even at the controller to do what it was intended to do.
Facebook solved this at 2009 using what they called BigPipe, it is not a new technology rather it is leveraging the browsers and the ability to send a few requests with fragmented parts of the page and only then compose it using some Javascript.
You can have a read here http://www.facebook.com/note.php?note_id=389414033919.
As for your check if the user is banned, yes that is something you'd have to check either way, perhaps you can have this in cache using memcached or redis so it won't hit your database directly every time.

Delphi XE2 Datasnap Session Management - get session information after page reload

I am trying to determine how to retrieve session information using a Delphi REST DataSnap server.
I know that, when on the same client page, you have access to the current thread session using the TDSSession method GetThreadSession.
What I want to do, however, is store data in the session (putData) and still be able to retrieve it when the user moves from page1 to page2. At present, if the user moves to a different page, the session is lost and a new one is created, thus loosing the data in the session that I had previously set.
I have tried playing with TDSSessionManager.SetThreadSession(sessionid) - but I cant seem to get it working.
I've reviewed the much acclaimed Marco Cantu white paper, however, it doesn't provide a solution to this issue.
Any help I can get on this would be great - even if its just 'hey, this topic is covered in book X'.
Thanks!
The TDSSessionManager.SetThreadSession(sessionid) works with Session.sessionname.
Plus make sure your Lifecycle is set to Session (as stated by tondrej).
If you reconnect your client. a new session is started. So you want to keep your Datasnap connection open.
Or you can set the lifecycle to Server and mannage the client-sessions yourself.
Edit: Rest Servers are Stateless. So you need to store the page you are on on the Client. And Query the needed Page from the Server
You have to tweak the client side JavaScript to use a cookie to store session info.
See the last part of JavaScript Client Sessions
If you want to keep server side objects active for the session use the Session life cycle.
I believe what you need to do is set LifeCycle property of your TDSServerClass instance to Session (stateful). From your question it seems you are currently using Invocation (stateless).
Well, in Datasnap REST (GET, POST, DELETE, PUT) if you set your TDSServerClass to session, as is a REST in this case session is the same as invocation, is stateless (http://docwiki.embarcadero.com/RADStudio/Tokyo/en/Server_Class_LifeCycle#REST_Clients). It is right, you give the oportunity to all kind of clients to use your datasnap server with JSONs for example.
You need to create your owner model to session control to your REST server, or look for some framework to do this. In my case I use custom objects on lifecicle server (some cases with database too), and using tokens on request headers and other informations, I know if is the same client and I control too when the token expires and need to do new login, for exemple and I can give much more security too as on PUT resquests, only on records gave to client (it is only one case, but there are much others...). You need to resolve other way, not with classic way using TDSSession.

Rails w/custom TCP data service

I'm building a Rails app that needs to connect to a custom TCP data service, which uses XML messages to exchange data. Functionally, this is not a problem, but I'm having trouble architecting it in a way that feels "clean".
Brief overview:
User logs in to the Rails app. At login, the credentials are validated with the data service and a "context id" is returned.
Request:
<login><username>testuser</username><password>mypass</password></login>
Response:
<reply><context_id>123456</context_id></reply>
This context_id is basically a session token. All subsequent requests for this user must supply this context_id in the XML message.
Request:
<history><context_id>123456</context_id><start_date>1/1/2010</start_date><end_date>1/31/2010</end_date></history>
Response:
<reply><history_item>...</history_item><history_item>..</history_item></reply>
I have hidden away all the XML building/parsing in my models, which is working really well. I can store the context_id in the user's session and retrieve it in my controllers, passing it to the model functions.
#transactions = Transaction.find( { :context_id => 123456, :start_date => '1/1/2010', :end_date => '1/31/2010' } )
From a design point of view, I have 2 problems I'd like to solve:
Passing the context_id to every Model action is a bit of a pain. It would be nice if the model could just retrieve the id from the session itself, but I know this breaks the separation of concerns rule.
There is a TcpSocket connection that gets created/destroyed by the models on every request. The connection is not tied to the context_id directly, so it would be nice if the socket could be stored somewhere and retrieved by the models, so I'm not reestablishing the connection for every request.
This probably sounds really convoluted, and I'm probably going about this all wrong. If anybody has any ideas I'd love to hear them.
Technical details: I'm running Apache/mod_rails, and I have 0 control over the TCP service and it's architecture.
Consider moving the API access to a new class, and store the TcpSocket instance and the context ID there. Change your models to talk to this API access class instead of talking to the socket themselves.
Add an around_filter to your controller(s) that pulls the context ID out of the session, stores it into the API access class, and nils it after running the action. As long as your Rails processes remain single-threaded, you'll be fine. If you switch to a multi-threaded model, you'll also need to change the API access class to store the context ID and the TcpSocket in thread-local storage, and you'll need one TcpSocket per thread.

Resources