I need to write a cgi page which will act like a reverse proxy between the user and another page (mbean). The issue is that each mbean uses different port and I do not know ahead of time which port user will want to hit.
Therefore want I need to do is following:
A) Give user a page which will allow him to choose which application he wants to hit
B) spawn a reverse proxy base on information above (which gives me port, server, etc..)
C) the user connects to the remote mbean page via the reverse proxy and therefore never "leaves" the original page.
The reason for C is that user does not have direct access to any of the internal apps only has access to initial port 80.
I looked at twisted and it appears to me like it can do the job. What I don't know is how to spawn twisted process from within cgi so that it can establish the connection and keep further connection within the reverse proxy framework.
BTW I am not married to twisted, if there is another tool that would do the job better, I am all ears. I can't do things like mod_proxy (for instance) since the wide range of ports would make configuration rather silly (at around 1000 different proxy settings).
You don't need to spawn another process, that would complicate things a lot. Here's how I would do it based on something similar in my current project :
Create a WSGI application, which can live behind a web server.
Create a request handler (or "view") that is accessible from any URL mapping as long as the user doesn't have a session ID cookie.
In the request handler, the user can choose the target application and with it, the hostname, port number, etc. This request handler creates a connection to the target application, for example using httplib and assigns a session ID to it. It sets the session ID cookie and redirects the user back to the same page.
Now when your user hits the application, you can use the already open http connection to redirect the query. Note that WSGI supports passing back an open file-like object as response, including those provided by httplib, for increased performance.
Related
I have my application which communicates over its own protocol, suppose if a user installs the application and want to get data, then he needs to use that protocol. Let my protocol be XYZ so the user is able to use the same from their existing browsers to get the data. Example: XYZ://myApplication/Query. I am not sure how can I achieve it. I should be noted that the application is running on the user's device itself.
Basically, I want to route a specific request to my application, and let the other request function normally. I am using python for the development of my application.
Additionally, If my approach is wrong then what can I do to create my own communication protocol which can be easily used with existing browsers?
You want to create your own scheme?
Only if you create the right backend server which can response to your request in your protocol, you can do it.
You can also find the details here.
I read the Flask doc, it said whenever you need to access the GET variables in the URL, you can just import the request object in your current python file?
My question here is that if two user are hitting the same Flask app with the same URL and GET variable, how does Flask differentiate the request objects? Can someone tell me want is under the hood?
From the docs:
In addition to the request object there is also a second object called
session which allows you to store information specific to a user from
one request to the next. This is implemented on top of cookies for you
and signs the cookies cryptographically. What this means is that the
user could look at the contents of your cookie but not modify it,
unless they know the secret key used for signing.
Means every user is associated with a flask session object which distinguishes them from eachother.
Just wanted to highlight one more fact about the requests object.
As per the documentation, it is kind of proxy to objects that are local to a specific context.
Imagine the context being the handling thread. A request comes in and the web server decides to spawn a new thread (or something else, the underlying object is capable of dealing with concurrency systems other than threads). When Flask starts its internal request handling it figures out that the current thread is the active context and binds the current application and the WSGI environments to that context (thread). It does that in an intelligent way so that one application can invoke another application without breaking.
I want to have a front-end server where my clients can connect, and depending on the client, be redirected (transparently) to another Flask application that will handle the specific client needs (eg. there can be different applications).
I also want to be able to add / remove / restart those backend clients whenever I want without killing the main server for the other clients.
I'd like the clients to:
not detect that there are other servers in the backend (the URL should be the same host)
not have to reenter their credentials when they are redirected to the other process
What would be the best approach?
The front-end server that you describe is essentially what is known as a reverse proxy.
The reverse proxy receives requests from clients and forwards them to a second line of internal servers that clients cannot reach directly. Typically the decision of which internal server to forward a request to is made based on some aspect of the request URL. For example, you can assign a different sub-domain to each internal application.
After the reverse proxy receives a response from the internal server it forwards it on to the client as if it was its own response. The existence of internal servers is not revealed to the client.
Solving authentication is simple, as long as all your internal servers share the same authentication mechanism and user database. Each request will come with authentication information. This could for example be a session cookie that was set by the login request, direct user credentials or some type of authentication token. In all cases you can validate logins in the same way in all your applications.
Nginx is a popular web server that works well as a reverse proxy.
Sounds like you want a single sign-on setup for a collection of service endpoints with a single entry point.
I would consider deploying all my services as Flask applications with no knowledge of how they are to be architected. All they know is all requests for resources need some kind of credentials associated with them. The manner you pass those credentials can vary. You can use something like the FAS Flask Auth Plugin to handle authentication. Or you can do something simpler like package the credentials provided to your entry service in the HTTP headers of the subsequent requests to other services. Flask.request.headers in your subsequent services will give you access to the right headers to pass to your authentication service.
There are a lot of ways you can go when it comes to details, but I think this general architecture should work for you.
I have a problem and can't solve it. Maybe I'm making it too hard or complex or I'm just going in the wrong direction and thinking of things that don't make sense. Below is a description of what happens. (Multiple tabs opened in a browser or a page that requests some other pages at the same time for example.)
I have a situation where 3 requests are received by the web application simultaneously and new user session has to be created. This session is used to store notification, XSRF token and login information when the user logs in. The application uses threads to handle requests (CherryPy under Bottle.py).
The 3 threads (or processes in case or multiple application instances) start handling the 3 requests. They check the cookie, no session exists, and create a new unique token that is stored in a cookie and in Redis. This will all happen at the same time and they don't know if a session already has been created by another thread, because all 3 tokens are unique.
These unused sessions will expire eventually, but it's not neat. It means everytime a client simultaneously does N requests and a new session needs to be created, N-1 session are useless.
If there is a property that can be used to identify a client, like an IP address, it would be a lot easier, but an IP address is not safe to use in this case. This property can be used to atomically store a session in Redis and other requests would just pick up that session.
If this is through a browser and is using cookies then this shouldn't be an issue at all. The cookie will, from what I can tell, the last session value that it is set to. If the client you are using does not use cookies then of course it will open a new session for each connection.
I'm using CherryPy to make a web-based frontend for SymPy that uses an asynchronous process library on the server side to allow for processing multiple requests at once without waiting for each one to complete. So as to allow for the frontend to function as expected, I am using one process for the entirety of each session. The client-side Javascript sends the session-id from the cookie to the server when the user submits a request, and the server-side currently uses a pair of lists, storing instances of a controller class in one and the corresponding session-id's in another, creating a new interpreter proxy and sending the input if a non-existant session-id is submitted. The only problem with this is that the proxy classes are not deleted upon the expiration of their corresponding sessions. Also, I can't see anything to retrieve the session-id for which the current request is being served.
My questions about all this are: is there any way to "connect" an arbitrary object to a CherryPy session so that it gets deleted upon session expiration, is there something I am overlooking here that would greatly simplify things, and does CherryPy's multi-threading negate the problem of synchronous reading of the stdout filehandle from the child process?
You can create your own session type, derived from CherryPy's base session. Use its clean_up method to do your cleanup.
Look at cherrypy/lib/sessions.py for details and sample session implementations.