opensrf_over_http
Differences
This shows you the differences between two versions of the page.
opensrf_over_http [2007/10/18 10:38] – created miker | opensrf_over_http [2022/02/10 13:34] (current) – external edit 127.0.0.1 | ||
---|---|---|---|
Line 1: | Line 1: | ||
+ | As posted on the open-ils-dev mailing list: | ||
+ | ---- | ||
+ | Bill and I have been puzzling over how to give HTTP clients support | ||
+ | for the more advanced features of OpenSRF, such as stateful, | ||
+ | transactional sessions and streaming responses. | ||
+ | that HTTP is entirely stateless on its own, and OpenSRF is not. The | ||
+ | second biggest problem is that most current HTTP clients do not lend | ||
+ | themselves to the kind of connection control we'd like to have. | ||
+ | |||
+ | Well, with the addition of (what really should be) a fairly trivial | ||
+ | translator service written as an Apache module, and a new server-side | ||
+ | setting that allows OpenSRF Applications to loosen their restrictions | ||
+ | on who can talk to them and when, we think we have a way to provide | ||
+ | advanced, robust, degradable OpenSRF services to all modern HTTP | ||
+ | clients. | ||
+ | |||
+ | Let us know what you think. | ||
+ | |||
+ | And so, herein follows ... | ||
+ | |||
+ | |||
+ | **A modest proposal for streaming, stateful OpenSRF-over-HTTP** | ||
+ | ---- | ||
+ | |||
+ | |||
+ | |||
+ | ====Client Request==== | ||
+ | |||
+ | The method is POST, URL is that of the HTTP/XMPP translator. | ||
+ | POST data should be a JSON encoded array of one or more osrfMessage objects. | ||
+ | See the bottom of this document for both XMPP and HTTP examples of OpenSRF | ||
+ | communication. | ||
+ | |||
+ | OpenSRF HTTP headers from client to server: | ||
+ | |||
+ | * X-OpenSRF-service=< | ||
+ | * X-OpenSRF-to=< | ||
+ | * X-OpenSRF-xid=< | ||
+ | * X-OpenSRF-thread=< | ||
+ | |||
+ | The **X-OpenSRF-service** and **X-OpenSRF-to** headers are mutually exclusive, and | ||
+ | cannot be used together. | ||
+ | **X-OpenSRF-service** header should be used: | ||
+ | |||
+ | - At the beginning of a stateful session, when sending the CONNECT message | ||
+ | - For stateless requests | ||
+ | |||
+ | In all other instances, which is to say within any stateful session that is | ||
+ | past the **CONNECT** phase, the client should use the **X-OpenSRF-to** header. | ||
+ | value of this header is set to the XMPP address returned in the by **STATUS_OK** | ||
+ | message from the current session **CONNECT** request. | ||
+ | |||
+ | |||
+ | If **multipart/ | ||
+ | send the following header with every HTTP request: | ||
+ | |||
+ | | ||
+ | |||
+ | Otherwise, the translator must assume multipart is not supported by the client. | ||
+ | |||
+ | Setting aside the underlying transport and supposing the complete equivalence | ||
+ | of the HTTP headers to XMPP XML attributes as described above, all other data | ||
+ | within the OpenSRF message remains entirely the same. In other words, The body | ||
+ | of the HTTP request is exactly equivalent to the ''< | ||
+ | ''< | ||
+ | |||
+ | |||
+ | ===Treament of these connection headers within the HTTP/XMPP translator=== | ||
+ | |||
+ | * **X-OpenSRF-service** -- Should be mapped to the XMPP endpoint within the | ||
+ | configured router, as described in the core config file for OpenSRF clients. | ||
+ | Typically this will look something like '' | ||
+ | where the service name provided in the header is used as the last component, | ||
+ | the XMPP resource. | ||
+ | the XMPP network. | ||
+ | connection or for stateless requests. | ||
+ | |||
+ | * **X-OpenSRF-to** -- Within the client, he value for this header is taken by from | ||
+ | value provided in the first **X-OpenSRF-from** header from the **STATUS_OK** message | ||
+ | provided by the server in response to the initial **CONNECT** request. | ||
+ | used in the '' | ||
+ | |||
+ | * **X-OpenSRF-xid** -- Typically, the time since the Unix epoc in milliseconds. | ||
+ | Used to trace the path of messages through the OpenSRF network. | ||
+ | supplied by the client, this should be created and supplied by the translator. | ||
+ | This datum is used in the '' | ||
+ | network. | ||
+ | |||
+ | * **X-OpenSRF-thread** -- A unique identifier for this request or session. | ||
+ | any string, though typically, a combination of the epoc time and originating | ||
+ | process id are used. This is used by OpenSRF endpoints for identifying and | ||
+ | continuing stateful sessions. | ||
+ | should create and supply a value for this element. | ||
+ | text content of the ''< | ||
+ | |||
+ | |||
+ | ====Response from the server==== | ||
+ | |||
+ | Assuming no error was encountered, | ||
+ | other things several bits of data that are critical to the ongoing | ||
+ | communication between the client and server. | ||
+ | the XMPP '' | ||
+ | for all future requests within a stateful session, assuming a stateful session | ||
+ | was requested and created. | ||
+ | HTTP header called **X-OpenSRF-from** in the response to the client. | ||
+ | The client will then use this value in the **X-OpenSRF-to** header of all | ||
+ | future in-session communication. | ||
+ | |||
+ | The body of the response, or responses if a multipart request is used and a | ||
+ | streaming method called, will each be an array of one or more '' | ||
+ | objects. | ||
+ | |||
+ | If the client does not request **multipart/ | ||
+ | **X-OpenSRF-multipart** header, as described above, then the translator will | ||
+ | collect all response '' | ||
+ | **COMPLETE** message, and packaged them into a single array object as a single | ||
+ | request response to the client. | ||
+ | |||
+ | |||
+ | ====Changes to OpenSRF==== | ||
+ | |||
+ | Stateful communication with backend OpenSRF service instances will be made | ||
+ | possible by giving each service the ability to accept " | ||
+ | remote IDs. If the configuration section for a given OpenSRF application | ||
+ | has the setting | ||
+ | |||
+ | < | ||
+ | < | ||
+ | </ | ||
+ | |||
+ | then that service will ignore the requirement that the remote ID of a stateful | ||
+ | client must match across all communication within a session, and instead rely | ||
+ | only on the thread of the session for session tracking. | ||
+ | currently always, an error condition for multiple client XMPP identifiers to | ||
+ | be used with one thread and one session. | ||
+ | among other security concerns. | ||
+ | in order to support OpenSRF-over-HTTP, | ||
+ | requiring the service to allow the feature explicitly in its configuration. | ||
+ | |||
+ | There is no restriction on the type of '' | ||
+ | and as long as their order (and associated succesful responses) would | ||
+ | constitute a normal stateful OpenSRF session on an XMPP network, the use of | ||
+ | the ''< | ||
+ | HTTP. | ||
+ | |||
+ | |||
+ | ====Overview of the HTTP/XMPP translator==== | ||
+ | |||
+ | The translator will be written as an Apache module. | ||
+ | smooth out the differences between the HTTP and XMPP transports with respect | ||
+ | to OpenSRF communication. | ||
+ | of data as possible, modifying only that data which must absolutely be changed | ||
+ | in order to support certain sub-optimal client software, and to map concepts | ||
+ | between HTTP and XMPP. | ||
+ | |||
+ | |||
+ | ===Upstream HTTP-side handling=== | ||
+ | |||
+ | For upstream (client to server) communication, | ||
+ | other than the mapping request headers to XMPP attributes, and the adding of | ||
+ | XMPP-specific router information to the service initially requested by the | ||
+ | client. | ||
+ | upstream communication. | ||
+ | |||
+ | ===Downstream HTTP-side handling=== | ||
+ | |||
+ | For downstream (server to client) communication, | ||
+ | paths. | ||
+ | on the client end, is the case where the client supports | ||
+ | **multipart/ | ||
+ | version 1.7 on and all version of the Firefox browser. | ||
+ | **multipart mode**. | ||
+ | no other browsers are known to support this mode at this time. We will call | ||
+ | this **collected mode**. | ||
+ | |||
+ | - For **multipart mode** capable clients, no modification of any data will occur | ||
+ | other than the mapping of the XMPP attributes to their respective HTTP | ||
+ | counterparts. | ||
+ | passed unaltered as a multipart chunk followed by a boundary marker. | ||
+ | translator will use this response mode when it receives a request that is | ||
+ | accompanied by a **X-OpenSRF-multipart** header set to **true**. | ||
+ | |||
+ | - For **collected mode** clients, all osrfMessage objects sent by the server will | ||
+ | be collected into a single JSON array, in the order they arrive, and delivered | ||
+ | as a single HTTP response to the client. | ||
+ | in order to pull all '' | ||
+ | the response array. | ||
+ | |||
+ | |||
+ | ===XMPP-side communication=== | ||
+ | |||
+ | The translator will use standard OpenSRF libraries to communicate with the XMPP | ||
+ | network-based services, just as the existing gateway and srfsh applications do. | ||
+ | |||
+ | |||
+ | ====Example Data==== | ||
+ | |||
+ | ===XMPP message example=== | ||
+ | |||
+ | < | ||
+ | <message | ||
+ | | ||
+ | | ||
+ | | ||
+ | | ||
+ | | ||
+ | < | ||
+ | < | ||
+ | [ | ||
+ | { | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | } | ||
+ | } | ||
+ | } | ||
+ | } | ||
+ | ] | ||
+ | </ | ||
+ | </ | ||
+ | </ | ||
+ | |||
+ | ===HTTP message example=== | ||
+ | |||
+ | < | ||
+ | |||
+ | X-OpenSRF-to=open-ils.search | ||
+ | X-OpenSRF-xid=1192540419313673 | ||
+ | X-OpenSRF-thread=1192540427.567678.119254042731367 | ||
+ | X-OpenSRF-multipart=true | ||
+ | |||
+ | [ | ||
+ | { | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | } | ||
+ | } | ||
+ | } | ||
+ | } | ||
+ | ] | ||
+ | |||
+ | </ |