Retrieve form data with python - python

I am new to web communication.
I use ubuntu and try to learn fastapi.
Let's say I post a file using curl. Seems to be common opinion that this is the best way to do it:
curl -F "file=#image1.jpg" http://127.0.0.1:8000/image -v
Now, on the server side I want to retrieve the image and add 1 to every pixel-value and then return it. But I have now idea how I "catch" the image from curl, how do I do that? Right now, I only have the the dummy function below which does not do anything intelligent:
#app.post("/image")
async def post_test():
print("I don't know how to catch the image :( ")
return {"You sent an image..."}
Please help with how I should write the post_test function! (Flask would work as well.)

You can check the full answer from my SO answer for a similar question (How to send file to fastapi endpoint using postman)
Basically, you would have to change your code to
from fastapi import FastAPI, UploadFile, File
app = FastAPI()
#app.post("/file/")
async def create_upload_file(file: UploadFile = File(...)):
# Access your file object via file.file,
# and perform all the necessary transformations
# Return the filename, but you may return the file itself
return {"filename": file.filename}

Related

Flask: Some clients don't like responses

I have a Flask app that generates video stream links. It connects to a server using login credentials and grabs a one time use link (that expires when a new link is generated using the same credentials). Using a list of credentials I am able to stream to as many devices as I like, so long as I have enough accounts.
The issue I am having is that one of the clients doesn't like the way the stream is returned.
#app.route("/play", methods=["GET"])
def play():
def streamData():
try:
useAccount(<credentials>)
with requests.get(link, stream=True) as r:
for chunk in r.iter_content(chunk_size=1024):
yield chunk
except:
pass
finally:
freeAccount(<credentials>)
...
# return redirect(link)
return Response(streamData())
If I return a redirect then there are no playback issues at all. The problem with a redirect is I don't have a way of marking the credentials as in use, then freeing them after.
The problem client is TVHeadend. I am able to get it to work by enabling the additional avlib inside of TVHeadend... But I shouldn't have to do that. I don't have to when I return a redirect.
What could be the cause of this?
Is it possible to make my app respond in the same way as the links server does?
My guess is that TVHeadend is very strict on if something complies to whatever standards... and I am guessing my app doesn't?

Add value to OAuth2PasswordRequestForm in FastAPI

i want the client to pass aditional information while loggin in to FastApi. I think for that i have to change the scheme for OAuth2PasswordRequestForm. Can anyone explain how to do that?
Im using the code from the FastApi tutorial right now:
https://fastapi.tiangolo.com/tutorial/security/oauth2-jwt/
If I understand your question correctly, you would like to have the user pass the info required by OAuth2PasswordRequestForm and also include some extra required information.
The easiest way to do this would probably be to create your own scheme that is a subclass of OAuth2PasswordRequestForm.
import fastapi
from fastapi import Depends
from fastapi.security import OAuth2PasswordRequestForm
app = fastapi.FastAPI()
class ExtendedOAuth2PasswordRequestForm(OAuth2PasswordRequestForm):
extra_data_field: str
#app.post("/your_endpoint")
def login_for_access_token(form_data: ExtendedOAuth2PasswordRequestForm = Depends()):
#do stuff with all of the normal OAuth2PasswordRequestForm and your extra data field...
You can add extend parameter to body request as follow:
And add the parameter to form data in frontend part:

Microsoft Bot Emulator showing "sending failed. Retry". VSCode shows KeyError: 'HTTP_CONTEXT_TYPE'

I am new to Microsoft Bot Framework, I am learning it through a youtube video https://youtu.be/ynG6Muox81o and making my bot on python3 on Ubuntu.
The Microsoft Bot Emulator says "sending failed. Retry".
Visual Studio Code shows KeyError: 'HTTP_CONTEXT_TYPE'.
I did everything right, my bot is connected to http://localhost:3978/, and bot emulator is connected to http://localhost:3978/api/messages/.
Many people on stackoverflow who had the same issue faced it due to windows firewall, but mine is ubuntu and i did check if it was enabled but its not.
app.py
from flask import Flask, request, Response
from botbuilder.schema import Activity
from botbuilder.core import BotFrameworkAdapter,BotFrameworkAdapterSettings
import asyncio
from echobot import EchoBot
app = Flask(__name__)
loop = asyncio.get_event_loop()
botadaptersettings=BotFrameworkAdapterSettings("","")
botadapter = BotFrameworkAdapter(botadaptersettings)
ebot = EchoBot()
#POST is the message
#app.route("/api/messages",methods=["POST"])
def messages():
#checking if HTTP file format is JSON or not
if "application/json" in request.headers["context-type"]:
#reading the JSON message
jsonmessage = request.json
else:
#unsupported media type 415
return Response(status=415)
activity = Activity().deserialize(jsonmessage)
async def turn_call(turn_context):
await ebot.on_turn(turn_context)
task = loop.create_task(botadapter.process_activity(activity,"",turn_call))
loop.run_until_complete(task)
if __name__ == '__main__':
app.run('localhost',3978)
echobot.py
from botbuilder.core import TurnContext
class EchoBot:
async def on_turn(self,turn_context:TurnContext):
await turn_context.send_activity(turn_context.activity.text)
I cant seem to understand the issue and how to fix it. it would be really helpfull if someone could help me fix this as i am really interested in building bots.
I have uploaded my Bot Project on gitlab https://gitlab.com/pdmnbhrawal/myechobot01.
This is a simple typo. You've written "context-type" instead of "content-type." The YouTube tutorial you linked to tells you to write a line like this:
if "application/json" in request.headers["content-type"]:
In order to avoid this kind of typo, you can download the source code that the video links to directly instead of trying to rewrite it yourself.
You can troubleshoot this kind of error yourself by noticing in the stack trace that it tells you what line of code is throwing the error. When it says KeyError: 'HTTP_CONTEXT_TYPE' that should indicate to you that you've entered the wrong key and you should check for a typo. You can also try using a debugger and stepping through your code.
There are a few other problems with the bot that you may notice. It doesn't handle conversation update activities correctly because it doesn't account for the incoming activity having no text. It also doesn't return an HTTP response from the api/messages endpoint. You might want to fix those problems later, but your bot will run despite them.

How to distinguish two different calls to the same Flask webhook?

I am using Heroku platform to put simple webhook, which is written on python and uses Flask. Cloud system I use sends POST request to my webhook, sending me some data and I should respond.
I would like to keep a log of all requests and responses.
Sometimes it happens, that Cloud system may send the same requests to my webhook again (for whatever reason - I didn't send a response in specified time or something like that).
I would like to distinguish such request. If I simply put information into the log about what I get it may happen that I will see in my log something like:
1) Starting processing request (1st request)
2) Starting processing request (2nd request)
3) Calculating response (1st request)
4) Calculating response (2nd response)
I would like to put some unique identifier to each line, something like session id, to filter all entries that belong to the same process.
How is this possible?
Here is the sample code:
# import of necessary modules
import modules
app = Flask(__name__)
app.config.from_json('config.json')
#app.route("/", methods=['GET', 'POST'])
def index():
body = request.data
signature = request.headers['x-pyrus-sig']
secret = str.encode(app.config['SECRET_KEY'])
if _is_signature_correct(body, secret, signature):
return _prepare_response(body.decode('utf-8'))
def _is_signature_correct(message, secret, signature):
...
# Verifying that request is from trusted source
def _prepare_response(body):
...
# Sending the response
if __name__ == "__main__":
app.run()
It seems that instead of trying to find a unique session id from the system, it's better to generate your own.
Something like this:
How can I generate a unique ID in Python?

Postman, Python and passing images and metadata to a web service

this is a two-part question: I have seen individual pieces discussed, but can't seem to get the recommended suggestions to work together. I want to create a web service to store images and their metadata passed from a caller and run a test call from Postman to make sure it is working. So to pass an image (Drew16.jpg) to the web service via Postman, it appears I need something like this:
For the web service, I have some python/flask code to read the request (one of many variations I have tried):
from flask import Flask, jsonify, request, render_template
from flask_restful import Resource, Api, reqparse
...
def post(self, name):
request_data = request.get_json()
userId = request_data['UserId']
type = request_data['ImageType']
image = request.files['Image']
Had no problem with the data portion and straight JSON but adding the image has been a bugger. Where am I going wrong on my Postman config? What is the actual set of Python commands for reading the metadata and the file from the post? TIA
Pardon the almost blog post. I am posting this because while you can find partial answers in various places, I haven't run across a complete post anywhere, which would have saved me a ton of time. The problem is you need both sides to the story in order to verify either.
So I want to send a request using Postman to a Python/Flask web service. It has to have an image along with some metadata.
Here are the settings for Postman (URL, Headers):
And Body:
Now on to the web service. Here is a bare bones service which will take the request, print the metadata and save the file:
from flask import Flask, request
app = Flask(__name__)
# POST - just get the image and metadata
#app.route('/RequestImageWithMetadata', methods=['POST'])
def post():
request_data = request.form['some_text']
print(request_data)
imagefile = request.files.get('imagefile', '')
imagefile.save('D:/temp/test_image.jpg')
return "OK", 200
app.run(port=5000)
Enjoy!
Make sure `request.files['Image'] contains the image you are sending and follow http://flask.pocoo.org/docs/1.0/patterns/fileuploads/ to save the file to your file system. Something like
file = request.files['Image']
file.save('./test_image.jpg')
might do what you want, while you will have to work out the details of how the file should be named and where it should be placed.

Categories