{"id":11228,"date":"2017-08-23T04:50:26","date_gmt":"2017-08-23T04:50:26","guid":{"rendered":"https:\/\/passkit.com\/blog\/?p=11228"},"modified":"2017-08-23T04:50:26","modified_gmt":"2017-08-23T04:50:26","slug":"how-to-use-golang-aws-lambda-to-build-a-scalable-barcode-generator-part-1","status":"publish","type":"post","link":"https:\/\/passkit.com\/blog\/how-to-use-golang-aws-lambda-to-build-a-scalable-barcode-generator-part-1\/","title":{"rendered":"How to use Golang &amp; AWS Lambda to build a scalable Barcode Generator (Part 1)"},"content":{"rendered":"<h3>1. Introduction<\/h3>\n<p><em>This is part 1 of a 2 part series. For part 2, please click <a href=\"https:\/\/passkit.com\/blog\/how-to-use-golang-aws-lambda-to-build-a-scalable-barcode-generator-part-2\/\" target=\"_blank\" rel=\"noopener\">here<\/a>.<\/em><br \/>\nThis article covers how-to:<\/p>\n<ul>\n<li>Write golang functions for AWS Lambda.<\/li>\n<li>Use AWS API Gateway to return binary content.<\/li>\n<li>Link together AWS Lambda &#038; API Gateway to create a scalable HTTPS service for barcode generation.<\/li>\n<\/ul>\n<p><b>Why do we need this at PassKit?<\/b><\/p>\n<ul>\n<li>To display a \u2018live&#8217; pass-render with accurate barcode in our <a href=\"https:\/\/app.loopyloyalty.com\" target=\"_blank\" rel=\"noopener\">Pass Designer &amp; Management Tools<\/a>.<\/li>\n<li>To generate QR codes (at scale) for our merchants for printing their Loyalty-program enrolment links onto tent-cards, menu\u2019s, websites, Facebook pages, etc.<\/li>\n<\/ul>\n<p><b>Why Golang?<\/b><\/p>\n<ul>\n<li><a href=\"https:\/\/hashnode.com\/post\/comparison-nodejs-php-c-go-python-and-ruby-cio352ydg000ym253frmfnt70\" target=\"_blank\" rel=\"noopener\">Speed<\/a>! Very fast &#038; a perfect choice for CPU-intensive tasks.<\/li>\n<li>Quick &#038; easy to master in a very short amount of time.<\/li>\n<li>Portability across platforms.<\/li>\n<li>Compiled binariers: plays nice with Docker.<\/li>\n<li><a href=\"https:\/\/blog.golang.org\/pipelines\" target=\"_blank\" rel=\"noopener\">Excellent concurreny primitives<\/a>.<\/li>\n<li>Well defined error handling patterns.<\/li>\n<li>Rich standard libraries.<\/li>\n<li>Standard code formatting \/ ease of maintenance.<\/li>\n<\/ul>\n<p><b>Why AWS Lambda?<\/b><br \/>\nAWS Lambda is a cloud computing service that lets you run code without provisioning or managing servers. AWS Lambda executes your code only when needed and scales automatically. In other words, it&#8217;s efficient and easy to use at scale, and you only pay for the resources that you use.<br \/>\n<b>What else could this logic be applied to?<\/b><\/p>\n<ul>\n<li>Scalable image generators \/ manipulators on AWS (although keep in mind that if you\u2019d want to use external image-libraries like Imagick or VIPS &#8211; AWS Lambda won&#8217;t be your optimal solution).<\/li>\n<li>Scalable document generator (PDF, Excel files, etc) on AWS.<\/li>\n<\/ul>\n<p><b>What is needed to get started?<\/b><br \/>\nYou will need an <a href=\"https:\/\/aws.amazon.com\/free\" target=\"_blank\" rel=\"noopener\">AWS account<\/a> with access to Lambda &#038; API Gateway in order to build this.<\/p>\n<h3>2. Samples<\/h3>\n<p>By the end of this article you will be able to create barcodes in QR and PDF417 format. Have a look at below samples:<br \/>\nA QR code of 200px by 200px, with the content &#8216;testing&#8217;.<br \/>\nURL: <a target=\"_blank\" href=\"https:\/\/utils.passkit.net\/barcode?m=testing&#038;f=qrcode&#038;h=200&#038;w=200\" rel=\"noopener\">https:\/\/utils.passkit.net\/barcode?m=testing&#038;f=qrcode&#038;h=200&#038;w=200<\/a><br \/>\n<img decoding=\"async\" src=\"https:\/\/utils.passkit.net\/barcode?m=testing&#038;f=qrcode&#038;h=200&#038;w=200\" alt=\"\" title=\"\"><br \/>\nA PDF417 code of 200px by 50px, with the content &#8216;testing&#8217;.<br \/>\nURL: <a target=\"_blank\" href=\"https:\/\/utils.passkit.net\/barcode?m=testing&#038;f=pdf417&#038;h=100&#038;w=300\" rel=\"noopener\">https:\/\/utils.passkit.net\/barcode?m=testing&#038;f=pdf417&#038;h=100&#038;w=300<\/a><br \/>\n<img decoding=\"async\" src=\"https:\/\/utils.passkit.net\/barcode?m=testing&#038;f=pdf417&#038;h=100&#038;w=300\" alt=\"\" title=\"\"><\/p>\n<h3>3. Let\u2019s get started &#8211; Tech Specification<\/h3>\n<p><em>Note: The article assumes that you have basic knowledge of AWS Lambda, API Gateway &#038; Golang. If you are new to all 3, then I&#8217;d recommend you first read the following resources:<\/p>\n<ul>\n<li><a href=\"http:\/\/docs.aws.amazon.com\/lambda\/latest\/dg\/welcome.html\" target=\"_blank\" rel=\"noopener\">What is AWS Lambda?<\/li>\n<li><a href=\"http:\/\/docs.aws.amazon.com\/apigateway\/latest\/developerguide\/welcome.html\" target=\"_blank\" rel=\"noopener\">What is Amazon API Gateway?<\/li>\n<li><a href=\"https:\/\/thenewstack.io\/the-new-stack-intros-go-programming-for-beginners\/\" target=\"_blank\" rel=\"noopener\">Go Programming For Beginners<\/a><\/li>\n<\/ul>\n<p><\/em><br \/>\n<b>System Flow<\/b><br \/>\nThe image below outlines the system &#038; data flow on what will be built over the course of this article. The final objective is to be able to use this barcode web-service by simply including its URL in an HTML image tag:<br \/>\n<img decoding=\"async\" src=\"https:\/\/dxjl3qy52c1o9.cloudfront.net\/wp-content\/uploads\/2017\/08\/13131526\/barcode_lambda.png\" alt=\"Barcode Generator Web Service Flow\" title=\"\"><br \/>\nThe API endpoint will be built according to the following specification:<br \/>\nSample URL: <b>\/barcode?width=200&#038;height=200&#038;type=qr&#038;message=testing<\/b><br \/>\nEndpoint: <b>\/barcode<\/b><br \/>\nMethod: <b>GET<\/b><br \/>\nRequest Parameters:<\/p>\n<ul>\n<li><b>width<\/b>: barcode width (int).<\/li>\n<li><b>height<\/b>: barcode height (int).<\/li>\n<li><b>message<\/b>: barcode contents, UTF8 support (string).<\/li>\n<li><b>type<\/b>: barcode type, &#8216;qr&#8217; or &#8216;pdf417&#8217; (string).<\/li>\n<\/ul>\n<p>For the purpose of this web-service, there are the following limitations:<\/p>\n<ul>\n<li>Minimum barcode with &amp; height: 150px.<\/li>\n<li>Maximum barcode width &amp; height of: 3000px.<\/li>\n<li>Maximum length of barcode contents: 600 bytes.<\/li>\n<li>Barcode types that are supported: QR, PDF417.<\/li>\n<\/ul>\n<h3>4. The Lambda Function in Go<\/h3>\n<p><b>Code Repository<\/b><br \/>\nThe code repository with the sample code can be downloaded from Github:<br \/>\n<a href=\"https:\/\/github.com\/pkosterman\/aws-lambda-barcode-generator\" target=\"_blank\" rel=\"noopener\">https:\/\/github.com\/pkosterman\/aws-lambda-barcode-generator<\/a><br \/>\n<b>Code Structure<\/b><br \/>\nEssentially, the lambda consists of a simple Node.js function that spawns off a child process which executes a compiled Go binary. The Node.js function ensures it passes the Stdin &#038; Stdout to the Go binary, so that the function receives the Lambda Context &#038; Event JSON, and when it&#8217;s finished, it can write the output back to Stdout for the Lambda to pass back to the invoker:<br \/>\n<a href=\"https:\/\/dxjl3qy52c1o9.cloudfront.net\/wp-content\/uploads\/2017\/08\/15044440\/node_js_go_wrapper_flow.png\" target=\"_blank\" rel=\"noopener\"><img fetchpriority=\"high\" decoding=\"async\" src=\"https:\/\/dxjl3qy52c1o9.cloudfront.net\/wp-content\/uploads\/2017\/08\/15044440\/node_js_go_wrapper_flow.png\" alt=\"node_js_go_wrapper_flow\" width=\"1315\" height=\"444\" class=\"alignnone size-full wp-image-11258\" title=\"\"><\/a><br \/>\nThere are 3 important parts in the code repo:<\/p>\n<ol>\n<li><b>main.go<\/b>: this contains the actual barcode generation (wrapped in our Node.Js wrapper).<\/li>\n<li><b>lib\/nodewrapper\/nodewrapper.go<\/b>: this library marshalls input from\/to the stdin &#038; stdout between our Go function and the Node.Js Lambda function.\n<li><b>index.js<\/b> &#038; <b>build.sh<\/b> &#8211; the build script needs to be executed in order to compile our zipped Lambda Node.Js bundle<\/li>\n<\/ol>\n<p>For this article, we will mainly focus on item 1 &#8211; the main.go program. If you want to re-use the nodewrapper for another project, you can simply do so by changing the contents of the Handler function, and, renaming the executable file in index.js to the name of your compiled binary.<br \/>\n<b>Barcode Generation<\/b><br \/>\nLet&#8217;s have a look at main.go. At the top it lists the libraries that the function uses. Quite basic:<br \/>\n[js]<br \/>\nimport (<br \/>\n\t&quot;bytes&quot;<br \/>\n\t&quot;encoding\/base64&quot;<br \/>\n\t&quot;encoding\/json&quot;<br \/>\n\t&quot;fmt&quot;<br \/>\n\t&quot;image\/png&quot;<br \/>\n\t&quot;os&quot;<br \/>\n\t&quot;aws-lambda-barcode-generator\/config&quot;<br \/>\n\t&quot;aws-lambda-barcode-generator\/lib\/nodewrapper&quot;<br \/>\n\t&quot;github.com\/boombuler\/barcode&quot;<br \/>\n\t&quot;github.com\/boombuler\/barcode\/pdf417&quot;<br \/>\n\t&quot;github.com\/boombuler\/barcode\/qr&quot;<br \/>\n)<br \/>\n[\/js]<br \/>\nThe function uses an <a href=\"https:\/\/github.com\/boombuler\/barcode\" target=\"_blank\" rel=\"noopener\">existing barcode library<\/a> for Go, since it&#8217;s well maintained, reasonably fast, and works like a charm! For the rest it uses standard Go libraries.<br \/>\nAfter the import statement, there is the LambdaInput struct &#8211; this is the struct that will be used to Marshall the Lambda eventJSON into. This struct conforms to our API endpoint specification, since this is all the data that is required to generate a barcode:<br \/>\n[js]<br \/>\ntype LambdaInput struct {<br \/>\n\tWidth   *int    `json:&quot;width,omitempty&quot;`<br \/>\n\tHeight  *int    `json:&quot;height,omitempty&quot;`<br \/>\n\tMessage *string `json:&quot;message,omitempty&quot;`<br \/>\n\tType    *string `json:&quot;type,omitempty&quot;`<br \/>\n}<br \/>\n[\/js]<br \/>\nAll of the fields in the struct are pointers so that the function can return helpful error messages in case if one of them isn&#8217;t present (i.e. <em>nil<\/em>).<br \/>\nIf you were to use this code to perform some different action with a Lambda (let&#8217;s say send an SMS message), then this is where you would specify the fields that you expect in your Lambda eventJSON.<br \/>\nNext, lets have a look at the main() function:<br \/>\n[js]<br \/>\nfunc main() {<br \/>\n\tnodewrapper.Run(func(context *nodewrapper.Context, eventJSON json.RawMessage) (interface{}, error) {<br \/>\n\t\t\/\/ declare this functions variables<br \/>\n\t\tvar input LambdaInput<br \/>\n\t\tvar c barcode.Barcode<br \/>\n\t\tvar err error<br \/>\n\t\tif err = json.Unmarshal(eventJSON, &amp;input); err != nil {<br \/>\n\t\t\t\/\/ Add error prefixes to all final error strings to allow for AWS API Gateway regex<br \/>\n\t\t\treturn nil, fmt.Errorf(&quot;400 Bad Request: Invalid Request &#8211; cannot marshal JSON input. Object received: %s&quot;, string(eventJSON))<br \/>\n\t\t}<br \/>\n\t\t\/\/ ensure our input is valid and contains all the data we need<br \/>\n\t\terr = checkValidRequest(input)<br \/>\n\t\tif err != nil {<br \/>\n\t\t\treturn nil, err<br \/>\n\t\t}<br \/>\n\t\t\/\/ based on the barcode type &#8211; generate the barcode<br \/>\n\t\tswitch barcodeType := *input.Type; barcodeType {<br \/>\n\t\tcase &quot;qr&quot;:<br \/>\n\t\t\tc, err = qr.Encode(*input.Message, qr.M, qr.Unicode)<br \/>\n\t\tcase &quot;pdf417&quot;:<br \/>\n\t\t\tc, err = pdf417.Encode(*input.Message, 3)<br \/>\n\t\t}<br \/>\n\t\tif err != nil {<br \/>\n\t\t\treturn nil, fmt.Errorf(&quot;500 Server Error: Could not generate barcode. Details: %s&quot;, err)<br \/>\n\t\t}<br \/>\n\t\t\/\/ Scale the barcode to the provided width &amp; height<br \/>\n\t\tc, err = barcode.Scale(c, *input.Width, *input.Height)<br \/>\n\t\tif err != nil {<br \/>\n\t\t\treturn nil, fmt.Errorf(&quot;500 Server Error: Could not scale the barcode to input width and height. Details: %s&quot;, err)<br \/>\n\t\t}<br \/>\n\t\t\/\/ if we have develop set to true, then also export as PNG (so its easy to view the barcode output on local machine)<br \/>\n\t\tif config.DEVELOP {<br \/>\n\t\t\t\/\/ create the output file<br \/>\n\t\t\tfile, _ := os.Create(&quot;code.png&quot;)<br \/>\n\t\t\tdefer file.Close()<br \/>\n\t\t\t\/\/ encode the barcode as png<br \/>\n\t\t\tpng.Encode(file, c)<br \/>\n\t\t}<br \/>\n\t\t\/\/ write image to buffer<br \/>\n\t\tbuf := new(bytes.Buffer)<br \/>\n\t\terr = png.Encode(buf, c)<br \/>\n\t\tif err != nil {<br \/>\n\t\t\treturn nil, fmt.Errorf(&quot;500 Server Error: Could not write image to buffer. Details: %s&quot;, err)<br \/>\n\t\t}<br \/>\n\t\t\/\/ return the image as a base64 encoded string<br \/>\n\t\treturn base64.StdEncoding.EncodeToString(buf.Bytes()), err<br \/>\n\t\t\/\/ append true here, so the nodewrapper returns our data without trying to marshall it into any response object<br \/>\n\t}, true)<br \/>\n}<br \/>\n[\/js]<br \/>\nThe function validates the input struct, and then uses the struct to generate a barcode according to the API specification. It then returns the barcode as a base64 encoded string, which the Lambda will pass onto API Gateway.<br \/>\nYou can see from the code that all errors are prefixed with their HTTP status code. This will later-on make it easy for API Gateway to do the proper HTTP header mapping.<br \/>\nOne important point to note. If you want to re-use this code for some other Lambda logic, all your code should go into the Nodewrapper.Run handler function:<br \/>\n[js]<br \/>\nfunc main() {<br \/>\n\tnodewrapper.Run(func(context *nodewrapper.Context, eventJSON json.RawMessage) (interface{}, error) {<br \/>\n        \/\/ CODE GOES HERE<br \/>\n\t}, true)<br \/>\n}<br \/>\n[\/js]<br \/>\nBased on the required output (JSON, or raw), the <em>rawOutput<\/em> boolean can be either true or false.<br \/>\n<b>Building the Lambda deployment package<\/b><br \/>\nAll that is required, is to open the terminal, and cd into the root directory of the repo, then type:<br \/>\n[js]<br \/>\n.\/build.sh<br \/>\n[\/js]<br \/>\nThis will create a build folder with in there the <em>lambda.zip<\/em> file. This zip file contains the compiled Go binary, and the index.js code that executes this binary.<br \/>\nIf the build succeeded, then the result is something like this:<br \/>\n[js]<br \/>\nCleaning build folder<br \/>\nSetting Production Mode<br \/>\nCompiling for Linux<br \/>\nPreparing Lambda bundle<br \/>\n  adding: main (deflated 65%)<br \/>\n  adding: index.js (deflated 61%)<br \/>\nCleaning up<br \/>\nDone!<br \/>\n[\/js]<br \/>\nNext, we need to upload the zipped deployment package to AWS.<br \/>\n<b>Upload the Lambda<\/b><br \/>\nLogin to your AWS account, and navigate to Lambda.<br \/>\n<em>1. Create a new function:<\/em><br \/>\n<a href=\"https:\/\/dxjl3qy52c1o9.cloudfront.net\/wp-content\/uploads\/2017\/08\/15115808\/lambda-flow.001.jpeg\" target=\"_blank\" rel=\"noopener\"><img decoding=\"async\" src=\"https:\/\/dxjl3qy52c1o9.cloudfront.net\/wp-content\/uploads\/2017\/08\/15115808\/lambda-flow.001.jpeg\" alt=\"lambda-flow.001\" width=\"1024\" height=\"640\" class=\"alignnone size-full wp-image-11281\" title=\"\"><\/a><br \/>\n<em>2. Click &#8216;Author from scratch&#8217;:<\/em><br \/>\n<a href=\"https:\/\/dxjl3qy52c1o9.cloudfront.net\/wp-content\/uploads\/2017\/08\/15115857\/lambda-flow.002.jpeg\" target=\"_blank\" rel=\"noopener\"><img decoding=\"async\" src=\"https:\/\/dxjl3qy52c1o9.cloudfront.net\/wp-content\/uploads\/2017\/08\/15115857\/lambda-flow.002.jpeg\" alt=\"lambda-flow.002\" width=\"1024\" height=\"640\" class=\"alignnone size-full wp-image-11282\" title=\"\"><\/a><br \/>\n<em>3. Click next on the &#8216;Triggers&#8217; page. We will setup API Gateway later:<\/em><br \/>\n<a href=\"https:\/\/dxjl3qy52c1o9.cloudfront.net\/wp-content\/uploads\/2017\/08\/15115910\/lambda-flow.003.jpeg\" target=\"_blank\" rel=\"noopener\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/dxjl3qy52c1o9.cloudfront.net\/wp-content\/uploads\/2017\/08\/15115910\/lambda-flow.003.jpeg\" alt=\"lambda-flow.003\" width=\"1024\" height=\"640\" class=\"alignnone size-full wp-image-11283\" title=\"\"><\/a><br \/>\n<em>4. Fill out the function details:<\/em><br \/>\nFor the runtime version, we will pick the latest Node.Js version that Lambda supports (which at the time of writing is 6.10).<br \/>\n<a href=\"https:\/\/dxjl3qy52c1o9.cloudfront.net\/wp-content\/uploads\/2017\/08\/15115935\/lambda-flow.004.jpeg\" target=\"_blank\" rel=\"noopener\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/dxjl3qy52c1o9.cloudfront.net\/wp-content\/uploads\/2017\/08\/15115935\/lambda-flow.004.jpeg\" alt=\"lambda-flow.004\" width=\"1024\" height=\"640\" class=\"alignnone size-full wp-image-11284\" title=\"\"><\/a><br \/>\n<em>5. Upload the lambda.zip that we built in the previous step:<\/em><br \/>\n<a href=\"https:\/\/dxjl3qy52c1o9.cloudfront.net\/wp-content\/uploads\/2017\/08\/15120018\/lambda-flow.005.jpeg\" target=\"_blank\" rel=\"noopener\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/dxjl3qy52c1o9.cloudfront.net\/wp-content\/uploads\/2017\/08\/15120018\/lambda-flow.005.jpeg\" alt=\"lambda-flow.005\" width=\"1024\" height=\"640\" class=\"alignnone size-full wp-image-11285\" title=\"\"><\/a><br \/>\n<a href=\"https:\/\/dxjl3qy52c1o9.cloudfront.net\/wp-content\/uploads\/2017\/08\/15120055\/lambda-flow.006.jpeg\" target=\"_blank\" rel=\"noopener\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/dxjl3qy52c1o9.cloudfront.net\/wp-content\/uploads\/2017\/08\/15120055\/lambda-flow.006.jpeg\" alt=\"lambda-flow.006\" width=\"1024\" height=\"640\" class=\"alignnone size-full wp-image-11286\" title=\"\"><\/a><br \/>\n<em>6. Set the role permissions:<\/em><br \/>\nAll that is needed for this particular lambda to run is the <b>lambda_basic_execution<\/b> role.<br \/>\n<em>Note: If you plan to write a Lambda that will be accessing other AWS services, then this will not be sufficient enough. In that case you&#8217;d have to create a new custom role and add additional permissions for the AWS services that your Lambda will consume. <\/em><br \/>\n<a href=\"https:\/\/dxjl3qy52c1o9.cloudfront.net\/wp-content\/uploads\/2017\/08\/15120211\/lambda-flow.007.jpeg\" target=\"_blank\" rel=\"noopener\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/dxjl3qy52c1o9.cloudfront.net\/wp-content\/uploads\/2017\/08\/15120211\/lambda-flow.007.jpeg\" alt=\"lambda-flow.007\" width=\"1024\" height=\"640\" class=\"alignnone size-full wp-image-11287\" title=\"\"><\/a><br \/>\n<a href=\"https:\/\/dxjl3qy52c1o9.cloudfront.net\/wp-content\/uploads\/2017\/08\/15115451\/lambda-flow.008.jpeg\" target=\"_blank\" rel=\"noopener\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/dxjl3qy52c1o9.cloudfront.net\/wp-content\/uploads\/2017\/08\/15115451\/lambda-flow.008.jpeg\" alt=\"lambda-flow.008\" width=\"1024\" height=\"640\" class=\"alignnone size-full wp-image-11273\" title=\"\"><\/a><br \/>\n<a href=\"https:\/\/dxjl3qy52c1o9.cloudfront.net\/wp-content\/uploads\/2017\/08\/15115500\/lambda-flow.009.jpeg\" target=\"_blank\" rel=\"noopener\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/dxjl3qy52c1o9.cloudfront.net\/wp-content\/uploads\/2017\/08\/15115500\/lambda-flow.009.jpeg\" alt=\"lambda-flow.009\" width=\"1024\" height=\"640\" class=\"alignnone size-full wp-image-11274\" title=\"\"><\/a><br \/>\n<em>7. Increase the timeout:<\/em><br \/>\nBy default an AWS Lambda function times out after 3 seconds. For this particular Lambda we don&#8217;t need to increase the timeout, since the Go barcode generation is reasonably fast (~10-20ms). But in case you are writing a more complex Lambda, then you might want to change these settings.<br \/>\n<a href=\"https:\/\/dxjl3qy52c1o9.cloudfront.net\/wp-content\/uploads\/2017\/08\/15115507\/lambda-flow.010.jpeg\" target=\"_blank\" rel=\"noopener\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/dxjl3qy52c1o9.cloudfront.net\/wp-content\/uploads\/2017\/08\/15115507\/lambda-flow.010.jpeg\" alt=\"lambda-flow.010\" width=\"1024\" height=\"640\" class=\"alignnone size-full wp-image-11275\" title=\"\"><\/a><br \/>\n<em>8. Check the method summary and create the function:<\/em><br \/>\n<a href=\"https:\/\/dxjl3qy52c1o9.cloudfront.net\/wp-content\/uploads\/2017\/08\/15115518\/lambda-flow.011.jpeg\" target=\"_blank\" rel=\"noopener\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/dxjl3qy52c1o9.cloudfront.net\/wp-content\/uploads\/2017\/08\/15115518\/lambda-flow.011.jpeg\" alt=\"lambda-flow.011\" width=\"1024\" height=\"640\" class=\"alignnone size-full wp-image-11276\" title=\"\"><\/a><br \/>\n<em>9. Configure test event and test:<\/em><br \/>\nFor a successful barode generation, we can test with the following JSON object:<br \/>\n[js]<br \/>\n{<br \/>\n  &quot;message&quot;: &quot;testing&quot;,<br \/>\n  &quot;width&quot;: 200,<br \/>\n  &quot;height&quot;: 200,<br \/>\n  &quot;type&quot;: &quot;qr&quot;<br \/>\n}<br \/>\n[\/js]<br \/>\n<a href=\"https:\/\/dxjl3qy52c1o9.cloudfront.net\/wp-content\/uploads\/2017\/08\/15115540\/lambda-flow.013.jpeg\" target=\"_blank\" rel=\"noopener\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/dxjl3qy52c1o9.cloudfront.net\/wp-content\/uploads\/2017\/08\/15115540\/lambda-flow.013.jpeg\" alt=\"lambda-flow.013\" width=\"1024\" height=\"640\" class=\"alignnone size-full wp-image-11278\" title=\"\"><\/a><br \/>\nTadaaaa &#8211; it works:<br \/>\n<a href=\"https:\/\/dxjl3qy52c1o9.cloudfront.net\/wp-content\/uploads\/2017\/08\/15115617\/lambda-flow.014.jpeg\" target=\"_blank\" rel=\"noopener\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/dxjl3qy52c1o9.cloudfront.net\/wp-content\/uploads\/2017\/08\/15115617\/lambda-flow.014.jpeg\" alt=\"lambda-flow.014\" width=\"1024\" height=\"640\" class=\"alignnone size-full wp-image-11279\" title=\"\"><\/a><br \/>\nTo test if the error handling works OK, the following JSON object can be used (remember, the function requires a minimum height of 150px for successful generation):<br \/>\n[js]<br \/>\n{<br \/>\n  &quot;message&quot;: &quot;testing&quot;,<br \/>\n  &quot;width&quot;: 200,<br \/>\n  &quot;height&quot;: 100,<br \/>\n  &quot;type&quot;: &quot;qr&quot;<br \/>\n}<br \/>\n[\/js]<br \/>\nAs expected, this outputs a properly JSON formatted error (including error-code prefix for API Gateway):<br \/>\n<a href=\"https:\/\/dxjl3qy52c1o9.cloudfront.net\/wp-content\/uploads\/2017\/08\/15115702\/lambda-flow.015.jpeg\" target=\"_blank\" rel=\"noopener\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/dxjl3qy52c1o9.cloudfront.net\/wp-content\/uploads\/2017\/08\/15115702\/lambda-flow.015.jpeg\" alt=\"lambda-flow.015\" width=\"1024\" height=\"640\" class=\"alignnone size-full wp-image-11280\" title=\"\"><\/a><br \/>\nThe Lambda function is setup correctly!<br \/>\nNext, <a href=\"https:\/\/passkit.com\/blog\/how-to-use-golang-aws-lambda-to-build-a-scalable-barcode-generator-part-2\/\">Part 2<\/a>: learn how-to setup the API endpoint in API Gateway, so that it can call the Lambda via a GET HTTP request.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>1. Introduction This is part 1 of a 2 part series. For part 2, please click here. This article covers how-to: Write golang functions for AWS Lambda. Use AWS API Gateway to return binary content. Link together AWS Lambda &#038; API Gateway to create a scalable HTTPS service for barcode generation. Why do we need [&hellip;]<\/p>\n","protected":false},"author":5,"featured_media":13754,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[37],"tags":[],"class_list":["post-11228","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-tech"],"_links":{"self":[{"href":"https:\/\/passkit.com\/blog\/wp-json\/wp\/v2\/posts\/11228","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/passkit.com\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/passkit.com\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/passkit.com\/blog\/wp-json\/wp\/v2\/users\/5"}],"replies":[{"embeddable":true,"href":"https:\/\/passkit.com\/blog\/wp-json\/wp\/v2\/comments?post=11228"}],"version-history":[{"count":0,"href":"https:\/\/passkit.com\/blog\/wp-json\/wp\/v2\/posts\/11228\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/passkit.com\/blog\/wp-json\/wp\/v2\/media\/13754"}],"wp:attachment":[{"href":"https:\/\/passkit.com\/blog\/wp-json\/wp\/v2\/media?parent=11228"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/passkit.com\/blog\/wp-json\/wp\/v2\/categories?post=11228"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/passkit.com\/blog\/wp-json\/wp\/v2\/tags?post=11228"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}