<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: zach</title>
    <description>The latest articles on DEV Community by zach (@ctrlsquid).</description>
    <link>https://dev.to/ctrlsquid</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F94678%2Fe1e8a794-7185-4c83-b6b9-f5a8991aff07.jpg</url>
      <title>DEV Community: zach</title>
      <link>https://dev.to/ctrlsquid</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/ctrlsquid"/>
    <language>en</language>
    <item>
      <title>Creating a placeholder image generator microservice in Rust and now</title>
      <dc:creator>zach</dc:creator>
      <pubDate>Thu, 28 Nov 2019 23:07:54 +0000</pubDate>
      <link>https://dev.to/ctrlsquid/creating-a-placeholder-image-generator-microservice-in-rust-and-now-4j1i</link>
      <guid>https://dev.to/ctrlsquid/creating-a-placeholder-image-generator-microservice-in-rust-and-now-4j1i</guid>
      <description>&lt;p&gt;Over the majority of 2019 I've been practicing Rust. One service that I've fell in love with in general is &lt;a href="https://now.sh"&gt;now.sh&lt;/a&gt;. Now.sh allows serverless function deployment, and that includes using community builders so you can use your own custom language.&lt;/p&gt;

&lt;p&gt;In this tutorial we'll be utilizing the &lt;a href="https://github.com/mike-engel/now-rust"&gt;now-rust&lt;/a&gt; for deployment, and &lt;a href="https://github.com/image-rs/image"&gt;image-rs&lt;/a&gt; for quickly generating a image to server.&lt;/p&gt;

&lt;h2&gt;
  
  
  init
&lt;/h2&gt;

&lt;p&gt;First thing we need to generate is our new project. Normally, we'd directly initialize a cargo project, but this project will have a special file architecture.&lt;/p&gt;

&lt;p&gt;Create a new directory &lt;code&gt;mkdir placeholder-example&lt;/code&gt; and &lt;code&gt;cd placeholder-example&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;&lt;code&gt;placeholder-example&lt;/code&gt; is going to be our project root. We'll want to create a cargo project within this folder.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;cargo new api&lt;/code&gt; to create our api project. This is going to be our primary api endpoint.&lt;/p&gt;

&lt;p&gt;Next we'll want to create a &lt;code&gt;now.json&lt;/code&gt; file in the root directory.&lt;/p&gt;

&lt;p&gt;Your folder structure should now look like this&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;placeholder-example
 - now.json
 - api
  - Cargo.toml
  - src
    - main.rs
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  configuring now.sh
&lt;/h2&gt;

&lt;p&gt;Next we're going to want to configure the now.json file to serve our serverless function. The primary piece we're going to need is telling now what builder to use. Make your &lt;code&gt;now.json&lt;/code&gt; file look like this&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;{
  "functions": {
    "api/**/*.rs": {
      "runtime": "now-rust@1.0.1"
    }
  }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This is going to tell now which runtime that any &lt;code&gt;.rs&lt;/code&gt; file within our api folder should use the &lt;a href="https://github.com/mike-engel/now-rust"&gt;now-rust&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Next let's move on to configuring the serverless function itself&lt;/p&gt;

&lt;h2&gt;
  
  
  adding our dependencies
&lt;/h2&gt;

&lt;p&gt;We're going to want to add our dependencies first. Open &lt;code&gt;api/Cargo.toml&lt;/code&gt; and add these dependencies to it.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;...

[dependencies]
image = "0.22.3"
http = "0.1"
now_lambda = "0.1"
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The &lt;a href="https://github.com/image-rs/image"&gt;image-rs&lt;/a&gt; is going to be for serving our generated image. The &lt;a href="https://github.com/hyperium/http"&gt;http&lt;/a&gt; is going to be for wrapping our function into an http handler, and the &lt;a href="https://crates.io/crates/now_lambda"&gt;now_lambda&lt;/a&gt; is a wrapper that configures that lambda functionality for us&lt;/p&gt;

&lt;h2&gt;
  
  
  configuring our image handler
&lt;/h2&gt;

&lt;p&gt;Now for the juicy stuff! We finally get to configure the actual handler!&lt;/p&gt;

&lt;p&gt;&lt;a href="https://i.giphy.com/media/dkGhBWE3SyzXW/giphy.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://i.giphy.com/media/dkGhBWE3SyzXW/giphy.gif" alt="" width="500" height="375"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Don't worry if you're new to Rust like I am! It's only a few lines of code!&lt;/p&gt;

&lt;p&gt;For this part, we're actually going to delete our src folder. We don't really need any binary or anything, now is going to handle all that for us. So remove the &lt;code&gt;api/src&lt;/code&gt; folder and create a new file in the api folder called &lt;code&gt;placeholder.rs&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Your folder structure should now look like this&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;placeholder-example
- now.json
- api
  - Cargo.toml
  - placeholder.rs
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Open &lt;code&gt;api/placeholder.rs&lt;/code&gt; and add our dependencies to the top of the file&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;use http::{StatusCode};
use now_lambda::{error::NowError, IntoResponse, Request, Response};
use image::{DynamicImage};
use image::ImageOutputFormat::PNG;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;For http we're simply utilizing a status code. For now_lambda we're utilizing it's wrapper around http to server our requests, and responses. For image, we're utilizing the DynamicImage enum for actually generating our image, and then we're also utilizing image's ImageOutputFormat to output into a PNG&lt;/p&gt;

&lt;p&gt;We need to create a &lt;code&gt;handler&lt;/code&gt; function that accepts a Request and outputs a Result. We want to allow our users to supploy a &lt;em&gt;width&lt;/em&gt; and a &lt;em&gt;height&lt;/em&gt; via the path in the URL, so we'll want to decode those two things from the path in the URL.&lt;br&gt;
Once we have our width and height we can generate a new image, convert it into a buffer, then convert it into a PNG, and then server that image in the response. &lt;/p&gt;

&lt;p&gt;That's going to look like this in your &lt;code&gt;api/placeholder.rs&lt;/code&gt; file&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;use http::{StatusCode};
use now_lambda::{error::NowError, IntoResponse, Request, Response};
use image::{DynamicImage};
use image::ImageOutputFormat::PNG;

fn handler(req: Request) -&amp;gt; Result&amp;lt;impl IntoResponse, NowError&amp;gt; {
  // Get the path
  let uri = req.uri();
  // Split the path
  let uri_split = uri.path().split("/");
  // Create a Vector containing each parameter
  let parameters = uri_split.collect::&amp;lt;Vec&amp;lt;&amp;amp;str&amp;gt;&amp;gt;();
  // The first parameter [1] (0 is the first "/") and the second parameter [2] are our values for (x, y)
  let img_x = parameters[1].parse::&amp;lt;u32&amp;gt;().unwrap();
  let img_y = parameters[2].parse::&amp;lt;u32&amp;gt;().unwrap();
  // Create our buffer for serving later
  let mut buffer = Vec::new();
  // Create our dynamic image
  let img = DynamicImage::new_rgb8(img_x, img_y);
  // Write to our buffer
  img.write_to(&amp;amp;mut buffer, PNG);
  // Build our response
  let response = Response::builder().status(StatusCode::OK).header("Content-Type", "image/png").body(buffer).expect("Interal Server Error");
  // Server our response
  Ok(response)
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now we have our function! Yay! The last thing we need to do is configure our &lt;code&gt;now.json&lt;/code&gt; file to look for a specific path when serving our handler. If we don't have those width and height the function will fail.&lt;/p&gt;

&lt;p&gt;So open your &lt;code&gt;now.json&lt;/code&gt; file and add these lines:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;{
  "functions": {
    "api/**/*.rs": {
      "runtime": "now-rust@1.0.1"
    }
  },
  "routes": [
    { "src": "/([0-9]+)/([0-9]+)", "dest": "/api/image.rs" }
  ]
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This just tells now.json that when the user requests &lt;a href="http://example.com/%5Bdigit%5D/%5Bdigit%5D"&gt;http://example.com/[digit]/[digit]&lt;/a&gt; to server our function.&lt;/p&gt;

&lt;p&gt;Last but not least, deploy our new serverless function via the now cli by running &lt;code&gt;now&lt;/code&gt; in your terminal&lt;/p&gt;

&lt;p&gt;Once now deploys your serverless function you should have a working placeholder image generator!&lt;/p&gt;

</description>
    </item>
  </channel>
</rss>
