Create an Azure function that takes in an image from a HTTP request, parses it with parse-multipart, and returns the base64 code of the image
✅ Task:
[x] Create a new branch called emotionalgifs
[x] 1: Create a new Azure Function called emotionalgifs with the HTTP Trigger template, install and use parse-multipart to parse an image from an HTTP request, and save its raw data in a variable
[x] 2: Return the image data encoded in base64 in the body of the Azure Function response
[x] 🚀 Place your function URL in a repository secret called EMOTIONAL_ENDPOINT and commit your code to emotionalgifs/index.js on your emotionalgifs branch
[x] 🚀 Create a pull request that merges emotionalgifs to main, but do not merge it
🚧 Test your Work
Use Postman! Paste the function url and make a POST request. Remember to attach the file in Body! In the output box, you should get the output. Make sure you're using an image with a real face on it or else it won't work. Here's an example of an output I get with this image:
:white_check_mark: Expected Output
The output should be the base64 code of the inputted image, like this:
```base64
/9j/4AAQSkZJRgABAQAAAQABAAD/2wBDAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQIC...
```
:question: Confused about Postman?
1. Navigate back to the Postman app and change GET to POST
2. Publish/deploy your function and copy your function url from the VS Code output like this:
3. Use the function url and any image you want to send the POST request. Remember to attach the file in `Body`, and send it using `form-data`!
💡 Keep in mind
- Note that when adding a file to `form-data`, you do NOT need to specify a key, and can send only a value (which in our case is a file).
- To change the value to a file, hover over the value box, click on the `Text` dropdown and select `File`.
![Untitled_ Nov 11, 2020 6_40 PM](https://user-images.githubusercontent.com/69332964/98876997-780afd80-244d-11eb-87fc-13822d909f2f.gif)
1. Create emotionalgifs HTTP trigger function that parses images
What is multipart request?
A HTTP multipart request is a HTTP request that HTTP clients construct to send files and data over to a HTTP Server.
💡 This is commonly used by browsers and HTTP clients to upload files to the server.
Because we want to send an image file through an HTTP Request, we need a piece of software to parse the raw data to extract the image file. Here comes the handy NPM package: parse-multipart!
The raw payload formatted as multipart/form-data will looks like this (expand)
```
------WebKitFormBoundaryDtbT5UpPj83kllfw
Content-Disposition: form-data; name="uploads[]"; filename="somebinary.dat"
Content-Type: application/octet-stream
some binary data...maybe the bits of a image..
------WebKitFormBoundaryDtbT5UpPj83kllfw
Content-Disposition: form-data; name="uploads[]"; filename="sometext.txt"
Content-Type: text/plain
hello how are you
------WebKitFormBoundaryDtbT5UpPj83kllfw--
```
The lines above represents a raw multipart/form-data payload sent by some HTTP client via form submission containing two files. We need to extract all the files contained inside it. The multipart format allows you to send more than one file in the same payload, so that's why it is called multipart.
:package: Installing `parse-multipart`
Before you can install `parse-multipart`, you need to enter `npm init -y` into the terminal. This command allows us to set up a new npm package:
[Open up a terminal in VSCode](https://code.visualstudio.com/docs/editor/integrated-terminal) inside your function's directory, type `npm install parse-multipart`, and press enter.
> :bulb: Forgot how to navigate a terminal? [Check this out.](https://computers.tutsplus.com/tutorials/navigating-the-terminal-a-gentle-introduction--mac-3855)
**Note:** the text outputted by the console does not mean there was an error! The npm package has successfully been installed.
How do I use this package?
First, we need to declare the variable `multipart` outside of the async function so that we can access the NPM package:
```js
var multipart = require('parse-multipart');
```
Notice that `multipart.Parse(body, boundary)` requires two arguments, as it has two parameters. I've already gotten the boundary for you – just like the documentation example, our boundary is a string in the format `"----WebKitFormBoundary(random characters here)"`.
In the `multipart.Parse()` call, you need to figure out what the body parameter should be.
> :bulb: **Hint:** It should be the request body. Think about the template HTTP Trigger Azure function. How did we access the body in there?
```js
// here's your boundary:
var boundary = multipart.getBoundary(req.headers['content-type']);
// TODO: assign the body variable the correct value
var body = ''
// parse the body
var parts = multipart.Parse(body, boundary);
```
2. 🖼️ Receiving the image
When the POST request is made to this function with an image, we need to:
Get the image from the parts (parse-multipart) variable
Convert the image to base64
Store the converted image in the response body
:question: What parts of the template code do we need?
Take a look at the standard `module.exports` function code:
```js
module.exports = async function (context, req) {
// the code
}
```
This is the function that runs **every time your HTTP trigger gets a request**. As a parameter of this function, the `req` parameter contains all the information the request was sent with. *This contains*:
* Headers
* The body
Remove all of the content in `module.exports` except this:
```js
context.res = {
// status: 200, /* Defaults to 200 */
body: //LEAVE THIS BLANK
};
```
:question: How do we output the image in base64?
Next, we want to output the **base64** code of the inputted image. The parsed image data that we need to convert to base64 is is stored in index 0 of `parts` since we only sent one file, and we want the data property of this image to access the binary file. Thus, we will be converting `parts[0].data` to base64 and assigning the code to a new variable:
```javascript
var convertedResult = Buffer.from(parts[0].data).toString('_____');
// FILL IN THE BLANK
```
The `Buffer` part of the code provides **temporary storage** for the binary image data as it is converted to **base64**.
Now, complete the following so that the **base64** code is outputted when the function is called:
```js
context.res = {
// status: 200, /* Defaults to 200 */
body: //WHAT GOES HERE?
};
```
Week 2 Step 2 ⬤⬤◯◯◯◯◯◯ | 🕐 Estimated completion: 5-20 minutes
Getting Emotional ~ With Parse-Multipart
✅ Task:
emotionalgifs
emotionalgifs
with the HTTP Trigger template, install and useparse-multipart
to parse an image from an HTTP request, and save its raw data in a variableEMOTIONAL_ENDPOINT
and commit your code toemotionalgifs/index.js
on youremotionalgifs
branchemotionalgifs
tomain
, but do not merge it🚧 Test your Work
Use Postman! Paste the function url and make a POST request. Remember to attach the file in
Body
! In the output box, you should get the output. Make sure you're using an image with a real face on it or else it won't work. Here's an example of an output I get with this image::white_check_mark: Expected Output
The output should be the base64 code of the inputted image, like this: ```base64 /9j/4AAQSkZJRgABAQAAAQABAAD/2wBDAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQIC... ```:question: Confused about Postman?
1. Navigate back to the Postman app and change GET to POST 2. Publish/deploy your function and copy your function url from the VS Code output like this: 3. Use the function url and any image you want to send the POST request. Remember to attach the file in `Body`, and send it using `form-data`! 💡 Keep in mind - Note that when adding a file to `form-data`, you do NOT need to specify a key, and can send only a value (which in our case is a file). - To change the value to a file, hover over the value box, click on the `Text` dropdown and select `File`. ![Untitled_ Nov 11, 2020 6_40 PM](https://user-images.githubusercontent.com/69332964/98876997-780afd80-244d-11eb-87fc-13822d909f2f.gif)1. Create
emotionalgifs
HTTP trigger function that parses imagesWhat is multipart request?
A HTTP multipart request is a HTTP request that HTTP clients construct to send files and data over to a HTTP Server.
Because we want to send an image file through an HTTP Request, we need a piece of software to parse the raw data to extract the image file. Here comes the handy NPM package:
parse-multipart
!The raw payload formatted as multipart/form-data will looks like this (expand)
``` ------WebKitFormBoundaryDtbT5UpPj83kllfw Content-Disposition: form-data; name="uploads[]"; filename="somebinary.dat" Content-Type: application/octet-stream some binary data...maybe the bits of a image.. ------WebKitFormBoundaryDtbT5UpPj83kllfw Content-Disposition: form-data; name="uploads[]"; filename="sometext.txt" Content-Type: text/plain hello how are you ------WebKitFormBoundaryDtbT5UpPj83kllfw-- ```The lines above represents a raw multipart/form-data payload sent by some HTTP client via form submission containing two files. We need to extract all the files contained inside it. The multipart format allows you to send more than one file in the same payload, so that's why it is called multipart.
:package: Installing `parse-multipart`
Before you can install `parse-multipart`, you need to enter `npm init -y` into the terminal. This command allows us to set up a new npm package:[Open up a terminal in VSCode](https://code.visualstudio.com/docs/editor/integrated-terminal) inside your function's directory, type `npm install parse-multipart`, and press enter. > :bulb: Forgot how to navigate a terminal? [Check this out.](https://computers.tutsplus.com/tutorials/navigating-the-terminal-a-gentle-introduction--mac-3855) **Note:** the text outputted by the console does not mean there was an error! The npm package has successfully been installed.
How do I use this package?
First, we need to declare the variable `multipart` outside of the async function so that we can access the NPM package: ```js var multipart = require('parse-multipart'); ``` Notice that `multipart.Parse(body, boundary)` requires two arguments, as it has two parameters. I've already gotten the boundary for you – just like the documentation example, our boundary is a string in the format `"----WebKitFormBoundary(random characters here)"`. In the `multipart.Parse()` call, you need to figure out what the body parameter should be. > :bulb: **Hint:** It should be the request body. Think about the template HTTP Trigger Azure function. How did we access the body in there? ```js // here's your boundary: var boundary = multipart.getBoundary(req.headers['content-type']); // TODO: assign the body variable the correct value var body = '2. 🖼️ Receiving the image
When the POST request is made to this function with an image, we need to:
:question: What parts of the template code do we need?
Take a look at the standard `module.exports` function code: ```js module.exports = async function (context, req) { // the code } ``` This is the function that runs **every time your HTTP trigger gets a request**. As a parameter of this function, the `req` parameter contains all the information the request was sent with. *This contains*: * Headers * The body Remove all of the content in `module.exports` except this: ```js context.res = { // status: 200, /* Defaults to 200 */ body: //LEAVE THIS BLANK }; ```:question: How do we output the image in base64?
Next, we want to output the **base64** code of the inputted image. The parsed image data that we need to convert to base64 is is stored in index 0 of `parts` since we only sent one file, and we want the data property of this image to access the binary file. Thus, we will be converting `parts[0].data` to base64 and assigning the code to a new variable: ```javascript var convertedResult = Buffer.from(parts[0].data).toString('_____'); // FILL IN THE BLANK ``` The `Buffer` part of the code provides **temporary storage** for the binary image data as it is converted to **base64**. Now, complete the following so that the **base64** code is outputted when the function is called: ```js context.res = { // status: 200, /* Defaults to 200 */ body: //WHAT GOES HERE? }; ```