This is my first application using Flask and Python.
I am using below URL format to send a POST request from Arduino to the flask application running on Pythonanywhere server instance.
Valid POST request: 3 URL parameters
http://voyagers.pythonanywhere.com/senddata?node=1234&lat=18.5580&lng=73.8075
I need to block the request from further processing by validating the URL in some form. I want this to secure my app from un-authenticated POST requests.
Say something like this:Anything more than 3 URL Parameters
http://voyagers.pythonanywhere.com/senddata?node=324&lat=18.5580&lng=73.8075&a=c&a=d
How can I achieve this in Flask ?
Also suggest , If there is any better way which could be used to secure application from un-authorised requests.
You can get flask to validate the parameters and throw an error automatically if you are willing to switch from URL parameters (i.e. anything after the '?' symbol in the URL) to path parameters (i.e. anything that is in the Path HTTP header, or the part of the URL after the first '/' and abefore the '?').
Your example could look like this:
#app.route('/post/<int:node_id>/<float:lat>/<float:lng>', methods=['POST'])
def process_post_request(node_id, lat, lng):
# do some work
return your_result
Then you could send request to URL that would look for example like this: http://example.com/post/1234/-11.45/21.34
You can find more about this here: http://flask.pocoo.org/docs/0.12/quickstart/#variable-rules
For securing access you can use some of the example snippets here: http://flask.pocoo.org/snippets/category/authentication/
I would recommend restricting access to HTTPS only and using the basic auth if you are just playing around. This is something you can do with a simple decorator as described here: http://flask.pocoo.org/snippets/8/
You will get a prompt in your browser asking you for username and password and browser will remember it for the duration of the session. Alternatively, you can set the username and password in base64 encoded form in the Authorization header: https://en.wikipedia.org/wiki/Basic_access_authentication
Related
I have a FastAPI app with a download endpoint. What this download endpoint does is to use a BlobServiceClient (for Azure Blob Storage) to generate a token and a Blob URL to a file specified in the request. What I want to do is to redirect the user to that URL. Here is a code snippet of the download enpoint (I commented some things out because I'm not allowed to show the code).
#router.get("..path", tags=["some tags"], summary=..., responses={404: {"model": ...}, 403: {"model": ...}, 307: {"model": ...}}, response_model_exclude_none=True)
async def download_file(
# there's a depends on an API key
blob_path: str = Query(
...
)):
credential = ClientSecretCredential(...) //secrets
blob_service_client = BlobServiceClient(f"https://{storage_account}.blob.core.windows.net", credential=credential)
user_delegation_key = blob_service_client.get_user_delegation_key(key_start_time=datetime.utcnow(),key_expiry_time=datetime.utcnow() + timedelta(minutes=30))
token = generate_blob_sas(account_name=...,
container_name=...,
blob_name=blob_path,
user_delegation_key=user_delegation_key,
permission=BlobSasPermissions(read=True),
expiry=datetime.utcnow() + timedelta(minutes=30))
blob_url = f'https://{storage_account}.blob.core.windows.net/{container_name}/{blob_path}?{token}'
print(blob_url)
response = RedirectResponse(blob_url)
return response
What I expected is the query to be executed, and after the response is returned, the download to start in the background or in a separate tab. What I've got instead is a different response as you can see in the Swagger:
I also had a look in the Network tab to see what is happening with that request:
Looks like there is an OPTIONS request and I assume that I'm getting the response to that request. Not sure if this is how Swagger handles the request. Any idea how/why this is happening and how to fix it? Thank you!
To start with, the HTTP OPTIONS, in CORS, is a preflight request that is automatically issued by the browser, before the actual request—is not the one that returns the File response. It requests the permitted communication options for a given server, and the server responds with an Access-Control-Allow-Methods header including a set of permitted methods (e.g., Access-Control-Allow-Methods: OPTIONS, GET, HEAD, POST, DELETE). The preflight response can be optionally cached for the requests created in the same URL using Access-Control-Max-Age header, thus allowing the server to limit the number of preflight requests. The value of this header is expressed in seconds; hence, allowing caching for 10 minutes, for example, would look as Access-Control-Max-Age: 600.
As for the RedirectResponse, Swagger UI always follows redirect responses. In a fetch request, for instance, the redirect parameter would be set to follow, indicating that the redirect should be followed. This means that Swagger UI follows the redirect and waits for the response to be completely received before providing you with a Download file link (as shown in the screenshot you provided above) that would allow you to download the file. That is also why you can't see the download starting either in the background or in a new tab. As mentioned in the linked github post above, it is not possible to change that behaviour, which could allow you to handle it differently, similar to the approach demonstrated in this answer.
Instead of using Swagger UI to test that specific endpoint, you can either test it directly through typing the URL to your API endpoint in the address bar of your browser (since it is a GET endpoint, you can do that, as when you type a URL in the address bar of your browser, it performs a GET request), or create your own custom Template (or use HTMLResponse) and submit an HTML <form>, as shown in this answer.
I am working on a url redirector application, in Python. The idea of this application is simple: when a user performs an http request to a certain domain (e.g. to https://google.com), the app stops the request and performs another http request (e.g. to https://github.com), thereby redirecting the user to the second page.
Unfortunately, I have looked through SO and I haven't found any question that addresses this issue directly:
Intercept and filter HTTP request doesn't redirect
Sending a HTTP request using python doesn't either
Admittedly, I only have some fabricated pseudocode to demonstrate what I wish to do, but it may prove useful:
import requests
original_site = "https://google.com"
redirect_site = "https://github.com"
def redirect_request():
if requests.get(original_site) == True:
requests.kill(request.original_site.id)
requests.get(redirect_site)
I greatly appreciate any suggestions.
EDIT - Here is a clarification of what I mean:
The user runs my python script, which I will call foobar.py, as follows:
python foobar.py
Then the user opens their web browser, and enters the url https://google.com, and as the script is running, the user will not actually visit https://google.com, but be redirected to https://github.com
One option is if you are trying to build a lightweight web app using python where you can mess with HTTP redirects, you can use Flask to accept a GET on a route and then simply do a redirect.
from flask import Flask, redirect
app = Flask(__name__)
#app.route('/')
def index():
return redirect("https://www.google.com")
But to answer your question more directly, you don't "stop" the initial request. You simply find a way to handle it and serve back a response that you specify.
I am using Python flask. I have a POST request with some payload coming on say:
abc.com/hello/hello1
I want to redirect this (302) to:
xyz.com/hello/hello1
only changing the domain name while keeping the remaining part as it is and also the payload. Is there a simple way to do this?
As per RFC, redirect requests (all 3xx) cannot contain request data or headers. You will miss the payload, supplied via POST in original request.
There are two possible workaround I could think of right away:
Give the client new URL, and implement further logic on client side;
Create a proxy handler on backend, which will do a request by itself and give the answer back as it's own.
EDIT: As per Andrejs Cainikovs's comment below, this would not work for a POST with payload.
In your endpoint, get the url that was used using request.url (see request API here for more options). Then you can rewrite it and make a redirect.
newUrl = "xyz.com/" + route
return redirect(newUrl, code=302)
I have two questions. I am new to python and not fluent enough with all the BIF's in python.
I am developing a website database is on amazon simple db.
I am handling all database related queries and code using python scripts.
My first question is given an HTML page where the user gives his his login credentials I call in a python script using my handler javascript function send in a post request and get a response from my python script.
I can send a post request all right and get the values from sdb for validation. What I need to know is how to send in a response from my script back to my html page which could react to the information given.
My second question is how do I maintain an HTTP session using python?
My python code is given below although it shouldn't make for much since no response code is added:
form=cgi.FieldStorage()
organisationID= form['orgID'].value
username= form['username'].value
password= form['password'].value
sdb=sdbhelper.connect()
connection= sdb.get_domain('AdminTable')
itemnames=''
flag=False
for item in connection:
if (item.name==username+'$'+organisationID):
retrieved_item=connection.get_item(item.name)
if(retrieved_item['Password']==password):
flag=True
#Now Id like to respond with flag so that login validation can be done
If I am correctly getting your question what you want to do is to create a small API , Where you send some information to a webpage and get some other .
What you can do is once the user is authenticated you should return it a access key that is valid for a short time period .
One of the way to send data could be inform of JSON objects .
For example if user is authenticated then return
{
'KEY' : 'dklsfeir5rufui435uejhfjh5ewh5rf'
}
From the next request you can associate this short lived key along the url for access .For example send the next request to abc.py?key=dklsfeir5rufui435uejhfjh5ewh5rf (by get or by post ) . If the key is valid then process the request else send a json response saying error occurred .
The main advantage of using JSON is it can be easily decoded/ encoded for communication
(JSON | http://docs.python.org/2/library/json.html )
Secondly as you have generated access key you would not require any session .
I want to send some variable in post when i am doing redirecting in my application.
Scenario is like this
def redirect_with_post():
post_variable = "i am a post variable"
return HttpRedirect(location="/confirm?id=23&user=user1")
# Now i want to send
post_variable
I want to send variable in post instead of querystring as a post request while redirecting.
tools and software used:-
python, webob, route
Redirect is performed by the client (your browser). And it only support a single Location header. You can't send POST data through a redirect. See https://en.wikipedia.org/wiki/HTTP_302