Provide option to download file using aiohttp server - python-3.5

How would it be possible to serve a downloadable file using aiohttp / asyncio?
I'm using:
async def route_function(request):
return web.Response(body=b"Test")
to just simply serve content.

The Content-Disposition header can indicate that the response body is
to be downloaded as an actual file, as opposed to displayed in the
browser. [*]
Content-Disposition: Attachment
Content-Disposition: Attachment;filename=some_file.xyz with filename
With aiohttp:
from aiohttp import MultiDict
async def route_function(request):
return web.Response(
headers=MultiDict({'Content-Disposition': 'Attachment'}),
body=b"Test"
)

Related

How can I read a binary file from a post request sent to in Azure Function in Python?

I am writing an Azure Function in Python that is going to receive binary files, do some processing and then return a different binary. For now I am just trying to create some basic echo functionality. How can I get the binary data sent to via a POST request? Here is what I have been trying, but I always end up getting corrupted data in return.
import logging
import azure.functions as func
def main(req: func.HttpRequest) -> func.HttpResponse:
logging.info('Python HTTP trigger function processed a request.')
img = req.get_body()
return func.HttpResponse(body=img,mimetype='image/jpg')
The POST request is being generated with curl.
curl -X POST http://localhost:7071/api/my_function_name -H "Content-Type: application/octet-stream" -d #input.jpg > test.jpg
test.jpg is always corrupted upon return. I don't know if I am reading it wrong from the request or sending it back wrong in the response (or both).
Turns out I was looking in the wrong place. My curl was the problem. Use
--data-binary input.jpg

NodeJS upload files

I'm trying to implement a file uploading feature. I have watched and read many tutorials, but all of them require one or another library like multer, formidable, axios or something else. As far as I learnt, it can be done without any external library, so it is how I want it - with minimal to none additional libraries.
On frontend I pack the file into FormData and send it via fetch:
if (file) {
const fd = new FormData()
fd.append('file', file)
const res = await fetch('/api/files', {
method: 'POST',
body: fd
})
}
On backend the body of request looks like this:
-----------------------------26088851433443883591868954602
Content-Disposition: form-data; name="file"; filename="1.png"
Content-Type: image/png
�PNG
→
IHDR�♦☻g�V¶☺sRGB��∟�♦gAMA��♂�a♣ pHYs♫�♫�☺�o�d{�IDATx^��⌂��W}▼����č↔;��6�4�6m��Lg�5�;q�&D�ۦ�8Nm�4����n�
-----------------------------312671409112038349881281368983--
I tried so far:
sending file without packing it into FormData does not change anything
fs.writeFile() gives a file with about right size, but it is not valid file
fs.writeFile() with base64 option gives a file with only one line inside it
req.files.mv() which worked in tutorial with axios cannot read files and fails
req.body.mv() also fails with mv is not a function
What can I do about it to make it working? If it helps somehow, my project is written in NextJS.

RAML MimeType for text/plain

Am trying to send a application/flatfile . (fixed width format) file in response back to consumer. how do i specify that in RAML 1.0
am trying to provide mime type for RAML which will be used in mulesoft . am building application/flatfile in dataweave 2.0 and want to send that back in response as an attachment. what mime type should i choose in body ? and for the consumer can he download the file , i see postman can do that while invoking (send and download)
who ever consume this should be able to get response as a file attachment and how do i mention the properties in raml for application/flatfile
/test:
/sfdc:
/time:
get:
is: [client-id-required]
responses:
200:
body:
text/plain:
The mime type of the response should be whatever the type of content being downloaded is.
In cases where the response's content type may vary, say the server may respond with a plain text, pdf or an octet stream, then the raml should look something like this:
responses:
200:
body:
text/plain:
application/pdf:
application/octet-stream:
And in addition to the Content-Type header, the http response should also have a Content-Disposition header with a value of "attachment".
Something like the following:
Content-Type: text/plain
Content-Disposition: attachment; filename="my_flat_file.txt"

What does "content-type" mean in headers of python requests library and if the value is text/html;charset=UTF-8?

I want to do some operations with response from python requests library. After I use below function;
response = requests.get(f'{AUTHORIZE_URL}?client_id={CLIENT_ID}&response_type=code&state={STATE}&redirect_uri={REDIRECT_URI}')
I need to get an URL something like this in return;
http://127.0.0.1:8000/products/auth/?state=2b33fdd45jbevd6nam&code=MGY1MTMyNWY0YjQ0MzEwNmMxMjY2ZjcwMWE2MWY5ZDE5MzJlMjA1YjdkNWExNGRhYjIzOGI5NzQ5OWZkNTA5NA
While doing it, it will be easier to use JSON in order to get state and code values from URL but I cannot use it because I think the content type does not allow this.
See this for Content-Type explanation: Content-Type
In short the "content-type" in the headers of response got by using requests.get tells you what kind of the content server did send, in your case you'we got a response in the form of the HTML (like .html document) and you can read that response with response.text, if the "content-type" is "application/json" then you can read it as JSON like this response.json().
I see that you use some local server, your local server should send in headers "Content-Type": "application/json" and then you should be able to read JSON from response like this (you need to send JSON not hmtl or text from server):
targetURL = 'http://127.0.0.1:8000/products/auth/?state=2b33fdd45jbevd6nam&code=MGY1MTMyNWY0YjQ0MzEwNmMxMjY2ZjcwMWE2MWY5ZDE5MzJlMjA1YjdkNWExNGRhYjIzOGI5NzQ5OWZkNTA5NA'
response.get(targetURL).json()

How to mock a sendgrid web api v.3 method in python

I'm trying to test that a SendGrid method was called without sending an email. When I run my test, the method is not patched and instead runs the original method which sends an email. I'm not sure why my patch is not working. This question is similar to How to mock a SendGrid method in Python but using a different version of SendGrid.
# api/Login/utils_test.py
from .utils import send_email
from unittest.mock import patch
#patch('api.Login.utils.sg.client.mail.send.post')
def test_send_email(mock_mail_send):
send_email(email, subject, html)
assert mock_mail_send.called
# api/Login/utils.py
from api import sg
def send_email(email, subject, html):
msg = create_email(email, subject, html)
request_body = msg.get()
response = sg.client.mail.send.post(request_body=request_body)
# api/__init__.py
from server import sg
# server.py
import sendgrid
import os
sg = sendgrid.SendGridAPIClient(apikey=os.environ.get('SENDGRID_API_KEY'))
Currently when I run pytest Login/utils_test.py from inside the api directory, I get an AssertionError:
assert False
+ where False = <MagicMock name='post' id='4370000808'>.called
I expect the test to pass with no output.
Found a workaround from the sendgrid-python repo issues https://github.com/sendgrid/sendgrid-python/issues/293
Going to wrap the call because patch doesn't seem to be working with SendGrid web api v.3 and it doesn't look like they are going to support it.
Updating to the following:
# api/utils.py
def send_email(email, subject, html):
msg = create_email(email, subject, html)
request_body = msg.get()
response = _send_email(request_body)
print(response.status_code)
print(response.body)
print(response.headers)
def _send_email(request_body):
"""Wrapping the SendGrid mail sending method in order to patch it
while testing. https://github.com/sendgrid/sendgrid-
python/issues/293"""
response = sg.client.mail.send.post(request_body=request_body)
return response
# api/utils_test.py
#patch('api.Login.utils._send_email')
def test_send_email(mock_mail_send):
send_email(email, subject, html)
assert mock_mail_send.called
Not on the Python side, but on the SendGrid side, have you tried using sandbox mode?
Another option is to use Prism in conjunction with our Open API definition. This will create a local mocked version of the SendGrid API so you can test against any of our endpoints.
Then you can run prism run --mock --list --spec https://raw.githubusercontent.com/sendgrid/sendgrid-oai/master/oai_stoplight.json from your command line.
To have Prism auto-start, please see this example.

Resources