Вопрос

motivation and context

I am designing and implementing the web interface of my bismon server program (a research prototype; in a few words: an orthogonally persistent, reflexive, homoiconic, dynamically-typed, multi-threaded, domain-specific language for static source code analysis; it runs on Linux only). It is free software (on http://github.com/bstarynk/bismon ...), GPLv3+ licensed, still officially unreleased (so 𝛂 stage). A draft report (a draft deliverable for some H2020 research project) describing it in some details is available on http://starynkevitch.net/Basile/bismon-chariot-doc.pdf (whose section §4.1 describes the web interface internals).

The web interface is for some kind of syntactic editor (grossly speaking, imagine "emacs" thru HTTP). I want it to be a single-page web application. I am not very familiar with web technologies (even if I read dozen of books about them). I am using the HTTP server library libonion in bismon, so the bismon process becomes a specialized web server.

My bismon is not a usual web application: it is expected to be used, by a small team (3 to 10 colleagues working on the same project) of trusted people. So there are only a dozen of browsers connected -on a trusted local area network- to a given bismon process. During several months, I would be the only user of that bismon thru the http://localhost:8086/ URL (but I might open that URL in two tabs of the same firefox browser window). There is already a login mechanism which sets a BISMONCOOKIE cookie identifying the web session. And a websocket is used. The web browser is Firefox 65 on Linux, if that matters.

question

how can such a Web application distinguish two tabs on the same browser?

My understanding is that both tabs will share the same URL (e.g. http://localhost:8086/) and the same cookie (e.g. BISMONCOOKIE being the same string, such as n000041R970099188t330716425o_6IHYL1fOROi_58xJPnBLCTe and that string corresponds to some web session object inside the bismon server). The two tabs could show two different views into the global state of my bismon.

Is there some programmatic way, browser side, to uniquely identify a tab? What exactly happens at the level of the HTTP protocol itself? I don't know any HTTP request header field uniquely identifying the tab. Or is it known in the DOM? How?

Let's suppose, for simplicity, that there is some equivalent of <a href='http://localhost:8086/'>link</a> in the DOM (of the dynamic page served by the bookmarked http://localhost:8086/ URL). How can the bismon server separate the action "click to follow the link" from the menu "open link in new tab", assuming a recent Firefox browser? My incomplete understanding is that the same HTTP exchange happens in both cases, and I really want to separate them.

It is well known that a modern browser (like Firefox) makes several TCP connections simultaneously for the same tab; so I cannot use that reliably.

As a simpler example, this very question has some "edit" link. What is happening server-side or protocol-side when I "open that link in other tab" two times?

(perhaps I need to use the websocket -which would be reopened in every different tab and might not be shared between tabs? this could be an answer)

PS. Queinnec's paper Inverting back the inversion of control or, Continuations versus page-centric programming could be related to my question, but I don't yet understand how.

Это было полезно?

Решение

You may create a unique ID (for example a UUID) at the client or let the server create it (and send it to the client at some occasion).

Each request at which the server needs to discern the particular tab should contain that ID.

To transfer that ID in the request you may include it in its parameters or (in case of AJAX) add a custom header.

If the server itself is building all URLs (for example when rendering HTML pages or JSON including URLs), you may have to build the ID server-side if none was given in the request or use the one given in the request and add it to all built URLs (query parameters for GET requests) and forms (hidden form fields for POST requests) to already have them in the first page load. Of course it's possible to modify URLs with a client-side executed script afterwards to contain your ID, too.

If the first page delivered by the server does not have to include any ID and you are really building a Single Page Application, the client usually builds the URLs by itself (or has the ability to add parameters at will) and you have to write your own JavaScript function which stores the ID in some place you can access it to actually augment the requests when building them.

Actually without further ado this lets the server distinguish between single executions of the client and not between the tabs. If you reload the page within the same tab, you would create a new ID instead of reusing the previous one.

You may store that ID in the SessionStorage (client-side) to reuse the ID within the tab across page reloads. Your script may then first lookup that ID in the storage and create a new one if there is none found.

Другие советы

Session storage is tab specific (i.e. not shared across tabs). So you can check session storage for a given key value, create it if it doesn't exist, and include it in any requests you send to your server. This will let both your server-side and client-side applications identify specific tabs.

Scopes (lifetimes)

Request scope

  • all info is give as request parameters

Session scope

  • a session is maintained, probably by cookie

Application scope

  • (irrelevant) info is maintained globally

For tabs typically:

Conversation scope

  • As mentioned typically works with maintaining a UUID (for the conversation).

On the server side one could have a thread-safe map by UUID as session attribute for instance. All kind of efficiency considerations. This solution is motivated by the fact that a conversation scope hangs under a session, above a request.

If your server does not provide a conversation scope, one can implement itself.

Лицензировано под: CC-BY-SA с атрибуция
scroll top