<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:content="http://purl.org/rss/1.0/modules/content/">
  <channel>
    <title>Erik Straub</title>
    <link>https://erikstraub.com/</link>
    <description>Recent content on Erik Straub</description>
    <generator>Hugo -- gohugo.io</generator>
    <language>en-US</language>
    <managingEditor>hi@erikstraub.com (Erik Straub)</managingEditor>
    <webMaster>hi@erikstraub.com (Erik Straub)</webMaster>
    <copyright>Erik Straub</copyright>
    <lastBuildDate>Mon, 05 Jun 2023 00:00:00 +0000</lastBuildDate>
    <atom:link href="https://erikstraub.com/index.xml" rel="self" type="application/rss+xml" />
    <item>
      <title>Go Project Structure</title>
      <link>https://erikstraub.com/blog/go-project-structure/</link>
      <pubDate>Mon, 05 Jun 2023 00:00:00 +0000</pubDate><author>hi@erikstraub.com (Erik Straub)</author>
      <guid>https://erikstraub.com/blog/go-project-structure/</guid>
      <description>A lot has been written about organizing Go projects. While there is no &amp;ldquo;official&amp;rdquo; Go project layout, there are a few practices that make sense to me and have served me well. This post describes a sort-of minimal amount of organization to help me be productive and organized. It also describes some of the things I like to have around from the start of a project in order to help with some of the everyday development tasks.</description>
      <content:encoded><![CDATA[<p>A lot has been written about organizing Go projects. While there is no &ldquo;official&rdquo; Go project layout, there are a few practices that make sense to me and have served me well. This post describes a sort-of minimal amount of organization to help me be productive and organized. It also describes some of the things I like to have around from the start of a project in order to help with some of the everyday development tasks.</p>
<blockquote>
<p>These are just my opinions. It is the current state of my brain when it comes to organizing a Go project. I reserve the right to change these opinions later ;) Also, it&rsquo;s totally fine if you prefer something different. I&rsquo;d love to hear or read about why you feel differently.</p>
</blockquote>
<p>If you&rsquo;d like to do some homework, here is some light pre-reading on the topic:</p>
<ul>
<li>
<p><a href="https://appliedgo.com/blog/go-project-layout">The one-and-only, must-have, eternal Go project layout</a></p>
</li>
<li>
<p><a href="https://peter.bourgon.org/go-best-practices-2016/#repository-structure">Go best practices, six years in</a></p>
</li>
<li>
<p><a href="https://travisjeffery.com/b/2019/11/i-ll-take-pkg-over-internal/">I&rsquo;ll take pkg over internal</a></p>
</li>
<li>
<p><a href="https://go.dev/blog/organizing-go-code">Organizing Go code</a></p>
</li>
<li>
<p><a href="https://medium.com/golang-learn/go-project-layout-e5213cdcfaa2">Go Project Layout</a></p>
</li>
</ul>
<p>The TL;DR of this entire post is that I make use of a <code>cmd</code> directory for housing my main application packages and a <code>pkg</code> directory to contain my library code. That&rsquo;s it. Simple and to the point. Until the project evolves, this seems like a great base to start from.</p>
<p>Below you can see the general layout of a project directory. We&rsquo;ll go through each of these files and directories and describe their uses.</p>





<pre tabindex="0"><code>├── .dockerignore
├── .editorconfig
├── .gitignore
├── .gitlab-ci.yml
├── .golangci.yml
├── Makefile
├── README.md
├── cmd
│   └── main.go
├── deployments
│   ├── Dockerfile
│   └── docker-compose.yml
├── go.mod
├── go.sum
└── pkg
    ├── config
    │   └── config.go
    ├── db
    │   ├── db.go
    │   └── db_test.go
    ├── handler
    │   ├── handler.go
    │   └── handler_test.go
    ├── mailer
    │   ├── mailer.go
    │   └── mailer_test.go
    ├── router
    │   ├── router.go
    │   └── router_test.go
    ├── submission
    │   └── submission.go
    └── templs
        ├── layout.templ
        ├── layout_templ.go
        └── types.go</code></pre><h2 id="root-level-files">Root-level Files</h2>
<h3 id="dockerignore"><code>.dockerignore</code></h3>
<p>This file contains references to anything I do <em>not</em> want copied into containers when using the <code>COPY</code> command inside a <code>Dockerfile</code></p>
<p>Typically this includes secrets, local/development-only configuration, random binaries, and any other files not directly responsible for building the app into a container.</p>
<h3 id="editorconfig"><code>.editorconfig</code></h3>
<p><a href="https://editorconfig.org">EditorConfig</a> is helpful for maintaining consistent code style across different editors and IDEs.</p>
<h3 id="gitignore"><code>.gitignore</code></h3>
<p>There&rsquo;s no strict guide here, but essentially, avoid checking in binaries, zips, certs, locally generated things that you are not specifically vendoring, code editor or IDE-specific directories and configuration files (think <code>.vscode</code> or <code>.idea</code>). There are of course exceptions to these loosely defined rules, but until exceptions present themselves, these are decent guidelines to follow.</p>
<p>Generally, it is <a href="https://github.com/github/gitignore/blob/main/Go.gitignore">GitHub&rsquo;s Go.gitignore template</a> and adding a few things like:</p>





<pre tabindex="0"><code>.vscode
.idea

/bin
coverage.html
/test-reports
*.tar
*.zip
.DS_Store</code></pre><h3 id="gitlab-ciyml"><code>.gitlab-ci.yml</code></h3>
<p>This is configuration for GitLab CI/CD pipelines. Typically I will want to run tests, lint code, build binaries and/or containers, and push an image on each pushed commit to GitLab.</p>
<p>Swap this with your CI/CD automation of choice.</p>
<h3 id="golangciyml"><code>.golangci.yml</code></h3>
<p>I use <a href="https://golangci-lint.run/">golangci-lint</a> to aggregate the various linters that are used to check the code.</p>
<p>The general configuration I use:</p>





<pre tabindex="0"><code>run:
  modules-download-mode: readonly
  skip-files:
    - &#34;.*\\.pb\\.go$&#34;
linters:
  fast: true
  enable:
  - errcheck
  - godot
  - gosimple
  - govet
  - ineffassign
  - staticcheck
  - typecheck
  - unused
  - whitespace
  - revive</code></pre><p>I usually ignore linting files generated by external tools as I&rsquo;ve found that some generators don&rsquo;t create code that necessarily aligns with how strict I like to be for commenting or handling errors. There are sometimes other quirks when applying these broad rules on code that is generated by external tooling.</p>
<h3 id="makefile"><code>Makefile</code></h3>
<p>The <code>Makefile</code> is made up of targets that you can think of as individual development tasks that are made up of commands that might have many arguments or flags, or be dependent upon previously run commands. Think the Makefile as a list of more convenient and easy to remember commands.</p>
<p>For example, think about building a binary. In local development, we may be able to get away with simply running <code>go build main.go</code>, but can we do the same in a CI job? Are there additional compile-time flags you want to use? Would your development binary be able to run in a container or someone else&rsquo;s development machine? Perhaps, without additional input.</p>
<p>You may want to start with a simple <code>run</code> target defined like so:</p>





<pre tabindex="0"><code>.PHONY: run
run:
    go run ./cmd</code></pre><p>A more complex example of a <code>build</code> target:</p>





<pre tabindex="0"><code>BRANCH?=$(shell git rev-parse --abbrev-ref HEAD)
SHA:=$(shell git rev-parse --short HEAD)

GOOS?=$(shell go env GOOS)
GOARCH?=$(shell go env GOARCH)

BINDIR:=./bin
BINARY_PATH ?= ${BINDIR}/${GOOS}-${GOARCH}
BINARY_NAME ?= app

AWS_ACCT ?= XXXXXXXXXX
AWS_REGION ?= us-east-1
IMG_NAME ?= mybinary
DOCKER_REPO ?= $(AWS_ACCT).dkr.ecr.$(AWS_REGION).amazonaws.com/$(IMG_NAME)
DOCKER_BRANCH = $(subst /,-,$(BRANCH))
DOCKER_TAG ?= $(DOCKER_BRANCH)-$(SHA)
DOCKER_IMG ?= $(DOCKER_REPO):$(DOCKER_TAG)

.PHONY: build
build: ## Build the go binaries
	GOOS=${GOOS} GOARCH=${GOARCH} go build -o $(BINARY_PATH)/$(BINARY_NAME) -ldflags &#34;-X &#39;main.version=${DOCKER_TAG}&#39; -X &#39;main.desc=branch:${BRANCH},commit:${SHA}&#39;&#34; ./cmd
endif</code></pre><p>With this <code>make build</code> command, I have a lot more control over how the binary is made, mainly via environment variables. I have sensible defaults for ensuring the build command works as expected in local development. It builds a binary for our local OS and architecture and puts it in our <code>./bin</code> directory at the root of the project.</p>
<p>In CI, I am probably going to want to be explicit about the OS/architecture for the resulting binary. In this case I simply define the appropriate environment variables and can use the same <code>make build</code> that I would locally.</p>
<p>This is obviously a very <em>involved</em> example. Make it super simple until otherwise needed.</p>
<p>The same sort of ideas carry over into other tasks as well. Running tests, generating code from protobuf files, linting code, building and pushing application containers to a repository - the list goes on.</p>
<h3 id="readmemd"><code>README.md</code></h3>
<p>The README should contain a high-level overview of the project, instructions on fully setting up a development environment, and any other information about how to interact with the code repository. In other words, it&rsquo;s an instruction manual for someone who is brand new to the repo. It should contain everything they need to know about the development, build, and deploy experience.</p>
<h3 id="gomod--gosum"><code>go.mod</code> / <code>go.sum</code></h3>
<p>Do people write Go without modules anymore? These should be straightforward, but if not:</p>
<p>The <code>go.mod</code> file defines the module import path, the minimum version of Go required to create the module, and dependency requirements with version locks.</p>
<p>The <code>go.sum</code> file contains the checksum of the dependencies along with the version. It&rsquo;s used to confirm that none of the dependencies have been modified.</p>
<h2 id="root-level-directories">Root-level Directories</h2>
<h3 id="bin"><code>bin</code></h3>
<p>The <code>bin</code> directory is where local builds will be output. The majority of the time I simply have a single binary there after running my <code>go build...</code> command.</p>
<p>A more complex example would be using additional directories that are named by the OS and architecture of the binary files that they contain.</p>
<p>In the example below, you can see that there are two binaries. One is for MacOS on Apple Silicon and the other is for 64-bit Linux.</p>





<pre tabindex="0"><code>./bin
├── darwin-arm64
│   └── app
└── linux-amd64
    └── app</code></pre><p>I like to include the <code>bin</code> directory itself in Git, but not its contents.</p>
<h3 id="cmd"><code>cmd</code></h3>
<p>The <code>cmd</code> directory contains the main application(s) for this project.</p>
<p>For simple projects, I&rsquo;ll probably just have a single file in there called <code>main.go</code>.</p>
<p>In more complex situations where I have more than one binary that is built within a project, I use a separate directory for each application. The name should match the name of the executable you want to have.</p>
<p>In the example below, I have a <code>server</code> and a <code>cli</code> application.</p>





<pre tabindex="0"><code>./cmd
└── server
│   └── main.go
└── cli
    └── main.go</code></pre><h3 id="deployments"><code>deployments</code></h3>
<p>I tend to keep any IaaS, PaaS, system and container orchestration related files, deployment configurations and templates, and build/deploy scripts here. Basically anything outside of the code itself that would be needed to run the code elsewhere.</p>
<p>I&rsquo;ve worked on a bunch of different projects that are deployed and configured in many different ways. Generally, a root-level <code>deployments</code> directory would contain my Dockerfiles, bash scripts (useful when Make isn&rsquo;t enough, container entrypoints, or there are complex one-off tasks), configuration files for deployments, sidecar containers, etc.</p>
<p>Sometimes I keep environment-specific configuration here. Sometimes it&rsquo;s defined elsewhere. Depends on the project and what the infrastructure is like.</p>
<blockquote>
<p><em>No</em> secrets, though. <em>Never, never, ever</em> commit secrets to your repo. The thought sends chills down my spine. Please let me sleep at night and take proper care of your important information. Your SREs appreciate it as well.</p>
</blockquote>
<h3 id="pkg"><code>pkg</code></h3>
<p>Normally, a <code>pkg</code> directory would only contain library code that is OK to be used by external applications and anything private to this repository would live in an <code>internal</code> directory.</p>
<p>In order to simplify the project structure, I ususally start by only using the lone <code>pkg</code> directory to group Go library code in one place. It helps to not clutter our root directory and really limits the places you need to look around for code you&rsquo;re importing in other places.</p>
<p>Again, simple until it needs to be otherwise.</p>
<h3 id="post-viewing">Post-Viewing</h3>
<p>Did you think you were done? If you&rsquo;ve made it this far, you&rsquo;re either quite passionate about making software, slightly out of your mind, quite bored, or some combination of all of the above. Either way, if you really want to press on, there are a ton of others who have opinions on the topic as well.</p>
<ul>
<li>
<p><a href="https://www.youtube.com/watch?v=PTE4VJIdHPg">Best Practices for Industrial Programming</a> from GopherCon EU 2018</p>
</li>
<li>
<p><a href="https://www.youtube.com/watch?v=oL6JBUk6tj0">GopherCon 2018: Kat Zien - How Do You Structure Your Go Apps</a></p>
</li>
<li>
<p><a href="https://www.youtube.com/watch?v=3gQa1LWwuzk">GoLab 2018 - Massimiliano Pippi - Project layout patterns in Go</a>.</p>
</li>
</ul>
<h2 id="conclusion">Conclusion</h2>
<p>To me, this is the minimal amount of ceremony to be productive and organized in a small-to-medium sized Go project. I don&rsquo;t take a hard line on any of these opinions. If I&rsquo;m working with others, chances are they also have opinions and I&rsquo;d rather get things done than die on the mole hill I&rsquo;ve described above.</p>
<p>Also, I get this isn&rsquo;t the sexiest topic in the world, but I appreciate you sticking around and reading through. I&rsquo;m hoping that by forcing myself to write about some of the things I find myself doing on a daily basis, it will help me realize whether or not I&rsquo;m doing them for good reasons.</p>
]]></content:encoded>
    </item>
    <item>
      <title>Using Charles Proxy to Debug Android SSL Traffic</title>
      <link>https://erikstraub.com/blog/using-charles-proxy-to-debug-android-ssl-traffic/</link>
      <pubDate>Mon, 19 Jun 2017 00:00:00 +0000</pubDate><author>hi@erikstraub.com (Erik Straub)</author>
      <guid>https://erikstraub.com/blog/using-charles-proxy-to-debug-android-ssl-traffic/</guid>
      <description>I&amp;rsquo;ve been a longtime user of Charles for checking requests and responses from the web applications I write. It&amp;rsquo;s a great cross-platform tool to help debug any kind of HTTP request when developing applications locally.&#xA;Charles as described on its site:&#xA;Charles is an HTTP proxy / HTTP monitor / Reverse Proxy that enables a developer to view all of the HTTP and SSL / HTTPS traffic between their machine and the Internet.</description>
      <content:encoded><![CDATA[<p>I&rsquo;ve been a longtime user of <a href="https://www.charlesproxy.com/">Charles</a> for checking requests and responses from the web applications I write. It&rsquo;s a great cross-platform tool to help debug any kind of HTTP request when developing applications locally.</p>
<p>Charles as described on its site:</p>
<blockquote>
<p>Charles is an HTTP proxy / HTTP monitor / Reverse Proxy that enables a developer to view all of the HTTP and SSL / HTTPS traffic between their machine and the Internet. This includes requests, responses and the HTTP headers (which contain the cookies and caching information).</p>
</blockquote>
<p>Lately, however, I&rsquo;ve been doing a lot more work on Android apps than I have on server-side applications. I figured it would be similarly helpful to debug some of the requests we were making from our apps without logging out to Logcat and cluttering our app code.</p>
<p>The requests I wanted to check happened to be protected by SSL, so in addition to adding the proxy information to my device&rsquo;s networking configuration, I also needed to install Charles&rsquo; root certificate. It turns out that this is possible, but requires a bit of work. Luckily I have now done this enough times to feel good about writing it up.</p>
<p>First off, this setup will not work on an emulator without an additional step (see below). I admittedly haven&rsquo;t needed to do any proxy debugging without a test device, though.</p>
<p>Also, as of this post, we are targeting Android SDK version 25 in our applications, but this specific setup should work with all versions. If not, feel free to correct me so that I can update this post.</p>
<p>Now on with the show.</p>
<h3 id="setting-up-your-project">Setting Up Your Project</h3>
<p>If your test device is running Android 7.0 or newer, there are a few extra steps to ensure that you are able to trust the Charles CA Certificate. To ensure Android trusts the certificate, you&rsquo;ll need to specify a <a href="https://developer.android.com/training/articles/security-config.html">Network Security Configuration</a> for your application. There are a few different ways of adding your certificate to the application&rsquo;s trusted configuration, but I found that the easiest was not to include Charles&rsquo; certificate within my application code, but to simply trust the user-installed CA certificates (like previous versions of Android used to do).</p>
<p>Specifying the<code>android:networkSecurityConfig</code> property within your <code>AndroidManifest.xml</code> file:</p>




<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-xml" data-lang="xml"><span class="line"><span class="ln">1</span><span class="cl"><span class="nt">&lt;application</span>
</span></span><span class="line"><span class="ln">2</span><span class="cl">  <span class="na">android:allowBackup=</span><span class="s">&#34;true&#34;</span>
</span></span><span class="line"><span class="ln">3</span><span class="cl">  <span class="na">android:icon=</span><span class="s">&#34;@mipmap/ic_launcher&#34;</span>
</span></span><span class="line"><span class="ln">4</span><span class="cl">  <span class="na">android:label=</span><span class="s">&#34;@string/app_name&#34;</span>
</span></span><span class="line"><span class="ln">5</span><span class="cl">  <span class="na">android:roundIcon=</span><span class="s">&#34;@mipmap/ic_launcher_round&#34;</span>
</span></span><span class="line"><span class="ln">6</span><span class="cl">  <span class="na">android:supportsRtl=</span><span class="s">&#34;true&#34;</span>
</span></span><span class="line"><span class="ln">7</span><span class="cl">  <span class="na">android:theme=</span><span class="s">&#34;@style/AppTheme&#34;</span>
</span></span><span class="line"><span class="ln">8</span><span class="cl">  <span class="na">android:networkSecurityConfig=</span><span class="s">&#34;@xml/network_security_config&#34;</span><span class="nt">&gt;</span></span></span></code></pre></div>
<p>Specifying the <code>res/xml/network_security_config.xml</code> file:</p>




<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-xml" data-lang="xml"><span class="line"><span class="ln">1</span><span class="cl"><span class="cp">&lt;?xml version=&#34;1.0&#34; encoding=&#34;utf-8&#34;?&gt;</span>
</span></span><span class="line"><span class="ln">2</span><span class="cl"><span class="nt">&lt;network-security-config&gt;</span>
</span></span><span class="line"><span class="ln">3</span><span class="cl">  <span class="nt">&lt;debug-overrides&gt;</span>
</span></span><span class="line"><span class="ln">4</span><span class="cl">    <span class="nt">&lt;trust-anchors&gt;</span>
</span></span><span class="line"><span class="ln">5</span><span class="cl">      <span class="c">&lt;!-- Trust user added CAs while debuggable only --&gt;</span>
</span></span><span class="line"><span class="ln">6</span><span class="cl">      <span class="nt">&lt;certificates</span> <span class="na">src=</span><span class="s">&#34;user&#34;</span> <span class="nt">/&gt;</span>
</span></span><span class="line"><span class="ln">7</span><span class="cl">    <span class="nt">&lt;/trust-anchors&gt;</span>
</span></span><span class="line"><span class="ln">8</span><span class="cl">  <span class="nt">&lt;/debug-overrides&gt;</span>
</span></span><span class="line"><span class="ln">9</span><span class="cl"><span class="nt">&lt;/network-security-config&gt;</span></span></span></code></pre></div>
<h3 id="setting-up-charles">Setting Up Charles</h3>
<p>Open up Charles on your computer and then open <code>Proxy &gt; Proxy Settings</code> from the toolbar. You&rsquo;ll need to make note of the HTTP Proxy Port that is specified.</p>
<p><img src="/images/charles-proxy-settings.png" alt="Charles - Proxy &gt; Proxy Settings"></p>
<p>Then open up <code>Proxy &gt; SSL Proxying Settings</code> from the toolbar and add the appropriate Locations (host/port) for the requests you wish to debug. I usually just add a wildcard route like <code>*.myapidomain.com</code> but specific domains like <code>whatever-app.herokuapp.com</code> work fine as well.</p>
<p><img src="/images/charles-ssl-proxying-settings.png" alt="Charles - Proxy &gt; SSL Proxying Settings"></p>
<h3 id="setting-up-your-android-device">Setting Up Your Android device</h3>
<p>First, make note of your computer&rsquo;s IP address within your local network. You&rsquo;ll need it in the next step.</p>
<p>Also make sure Charles is open and that the computer is on the same wifi network as the Android device you&rsquo;ll be setting up.</p>
<p>Go to your device&rsquo;s settings and wifi configuration.</p>
<p>Press and hold on the network you&rsquo;re going to use and select <code>Modify network</code> from the alert modal.</p>
<p>Then check <code>Advanced Options</code> and scroll until you see <code>Proxy</code>.</p>
<p>Tap the <code>Proxy</code> dropdown and select <code>Manual</code>.</p>
<p>For the <code>Proxy hostname</code> input your computer&rsquo;s IP address that you noted above.</p>
<p>Then for the <code>Proxy port</code> use the HTTP Proxy Port that you noted from Charles&rsquo; Proxy Settings from above.</p>
<p>Tap <code>Save</code>.</p>
<p><img src="/images/charles-android-device-network-config.png" alt="Android device network config&quot;"></p>
<p>After saving, you may notice a pop-up on your computer like this:</p>
<p><img src="/images/charles-allow-device-connection.png" alt="Allow device connection within Charles&quot;"></p>
<p>You should now click <code>Allow</code> to let your Android device connect to Charles via the proxy it has set up.</p>
<p>If you don&rsquo;t see this prompt, you can ensure that your device can use the proxy from within Charles by going to <code>Proxy &gt; Access Control Settings</code> and adding your Android device&rsquo;s IP address on the wifi network.</p>
<p><img src="/images/charles-access-control-settings.png" alt="Charles - Proxy &gt; Access Control Settings&quot;"></p>
<p><strong>One more step!</strong></p>
<p>Now on your Android device, open up the browser and go to the following URL <code>chls.pro/ssl</code>. You can also see these instructions from within the Charles app - go to <code>Help &gt; SSL Proxying &gt; Install Charles Root Certificate on a Mobile Device or Remote Browser</code>.</p>
<p><img src="/images/help-install-charles-root-cert.jpg" alt="Help &gt; SSL Proxying &gt; Install Charles Root Certificate on a Mobile Device or Remote Browse"></p>
<p>The browser should download the cert and once finished, tap to open the file. Then Android should prompt you to install the file.</p>
<p><img src="/images/charles-cert-fire-tablet.png" alt="Installing Charles Root Certificate on Android&quot;"></p>
<p>After you&rsquo;ve named the certificate and tapped &ldquo;OK&rdquo;, you will either be prompted to input your device&rsquo;s pin/password or prompted to set up your device&rsquo;s pin/password. Once that process is complete, you should be ready to debug some requests.</p>
<p><strong>Note</strong> Until you remove the manual proxy from this device&rsquo;s wifi configuration, whenever you use this network again you will need to have Charles open and running on the same IP address. You can always set the network configuration back to &ldquo;Proxy: None&rdquo; once you&rsquo;re done debugging.</p>
<h3 id="using-an-emulator">Using An Emulator</h3>
<p><a href="https://www.charlesproxy.com/documentation/configuration/browser-and-system-configuration/">According to Charles&rsquo; site</a> you can start the emulator with a flag in order to use the proxy.</p>
<blockquote>
<p>In the Android emulator run configuration add an Additional Emulator Command Line Option:
-http-proxy http://LOCAL_IP:8888</p>
</blockquote>
<blockquote>
<p>Where LOCAL_IP is the IP address of your computer, not 127.0.0.1 as that is the IP address of the emulated phone.</p>
</blockquote>
<p><em>EDIT: Thanks to <a href="https://twitter.com/xBrandonDavisx">Brandon Davis</a> for pointing out that the full command would be</em></p>
<pre><code>emulator -avd EMULATOR_NAME -http-proxy IP_ADDRESS:PORT
</code></pre>
<p><em>In addition, Android Studio 3.0 will now allow managing proxy settings for your emulator images. <a href="https://developer.android.com/studio/preview/features/index.html">Read all about the new features here</a> and if you can&rsquo;t wait for a stable release, <a href="https://developer.android.com/studio/preview/index.html">3.0 is currently available in the dev channel</a>.</em></p>
<h3 id="debugging-requests">Debugging requests</h3>
<p>Now that you&rsquo;re set up, you should see Charles recording traffic from your device. As long as you&rsquo;re configured properly, you should see those SSL request details from the domains you specified in Charles&rsquo; SSL Proxying Settings.</p>
<p>Feel free to discuss your results and let me know if I missed anything obvious.</p>
]]></content:encoded>
    </item>
    <item>
      <title>Nodevember 2015 - Nashville, TN</title>
      <link>https://erikstraub.com/blog/nodevember-2015/</link>
      <pubDate>Tue, 24 Nov 2015 00:00:00 +0000</pubDate><author>hi@erikstraub.com (Erik Straub)</author>
      <guid>https://erikstraub.com/blog/nodevember-2015/</guid>
      <description>I wasn’t sure what to expect out of Nashville, but when we arrived we were almost immediately greeted with a buffet of the finest BBQ I&amp;rsquo;ve ever had. Our hosts at Overdog, who we have worked closely with over the past two years, brought us in to talk shop and meet the team face-to-face (some for the first time). We love collaborating with their team and I enjoyed getting to see how they work and hang out around town.</description>
      <content:encoded><![CDATA[<p><img src="/images/greenhouse.jpg" alt="GreenHouse Nashville"></p>
<p>I wasn’t sure what to expect out of Nashville, but when we arrived we were almost immediately greeted with a buffet of the finest BBQ I&rsquo;ve ever had. Our hosts at <a href="http://www.overdog.com/">Overdog</a>, who we have worked closely with over the past two years, brought us in to talk shop and meet the team face-to-face (some for the first time). We love collaborating with their team and I enjoyed getting to see how they work and hang out around town.</p>
<p>Nodevember&rsquo;s format seems to be of the &ldquo;go big or go home&rdquo; sort. There was a lot of variety in the talks and speakers and it was a bit overwhelming to choose where to go next with four tracks. The talks were all a half hour long, so there wasn&rsquo;t really too much time to dig deep, but there seemed to be a good balance between intro-level and higher-level content, which is always great. I love going into a talk and having the feeling like the concepts are way over my head. I like knowing what I don&rsquo;t know.</p>
<p>I also liked the venue, Libscomb University. All of the facilities seemed new and it was refreshing to be able to walk outside between talks. We stayed in a nice Airbnb about a mile from the campus, which was itself only about 5 miles to downtown Nashville, so everything was a short drive away.</p>
<h2 id="the-talks">The Talks</h2>
<p>Some of the standouts from day one, for me, were <a href="https://twitter.com/reverentgeek">David Neal</a> showing everyone how to get started writing <a href="http://www.slideshare.net/reverentgeek/crossplatform-desktop-apps-with-electron">&ldquo;Cross-Platform Desktop Apps with Electron&rdquo;</a>, <a href="https://twitter.com/benmvp">Ben Ilegbodu</a> priming us on the new hotness with <a href="http://benmvp.github.io/slides/nodevember2015-es6.html#/">&ldquo;Sugar and Spice and everything nice about ES6&rdquo;</a>, and <a href="https://twitter.com/wpreul">Wyatt Preul</a> giving an overview of how easy it can be to start building microservices with <a href="https://github.com/geek/nodevember-2015">&ldquo;The proof is in the pudding - seneca+hapi&rdquo;</a>.</p>
<p>I had already started using some of the new ES6 features with a React app I built recently, but I&rsquo;m especially excited about some of the things Ben shared about destructuring, rest/spread parameters, function defaults, and using for&hellip;of to iterate over iterable objects. This will definitely help with removing a lot of cruft from future code.</p>
<p>It was also great to meet Wyatt after his talk about seneca and hapi. We just so happen to use seneca at Odd Networks and one of the very best things about going to industry conferences is being able to connect with the folks that collaborate and work on some of the everyday tech that you use. We&rsquo;re pretty excited for the future of seneca and <a href="https://github.com/senecajs/contrib">can&rsquo;t wait to help contribute</a>.</p>
<p>The closing keynote from Day 1 was a talk by <a href="https://twitter.com/funkatron">Ed Finkler</a> regarding <a href="http://funkatron.com/osmi/">&ldquo;Open Sourcing Mental Illness&rdquo;</a>. I really admire Ed for getting in front of a room of his peers to tackle a tough subject and share his own personal struggles. His call to action was that we should all be working toward being open and accepting of the issues that affect more people than we probably realize (1 in 5 Americans, according to Ed) and making sure our employers do the same. I hope others will consider making a donation to <a href="http://j.mp/osmi2015campaign">Ed&rsquo;s Indiegogo campaign</a> to bring awareness to the mental health issues in our industry and what we can do about it. He&rsquo;s doing great work!</p>
<h2 id="after-hours">After Hours</h2>
<p>After filling our brains with much needed sustinence, it was time to see what else Nashville had to offer. The nightlife downtown was electric with a seemingly endless array of bars with a large crowd and a live band. A quick bite and a walkabout was it for me, though.</p>
<h2 id="day-2">Day 2</h2>
<p>The final day of Nodevember had an equally packed schedule and I really enjoyed the five talks I went to.</p>
<p>Things got kicked off for me listening to <a href="https://twitter.com/getify">Kyle Simpson</a> introduce everyone to <a href="https://speakerdeck.com/getify/blocking-across-the-wire">&ldquo;Blocking Across The Wire&rdquo;</a>. He explained CSP (Communicating Sequential Processes) and his experiments essentially using a websocket channel to coordinate blocking between the browser and server. This talk was refreshing and challenging and opened my eyes to a new approach to async programming. I suggest you check out Kyle&rsquo;s <a href="https://github.com/getify/a-tale-of-three-lists">A Tale Of Three Lists</a> if you&rsquo;re interested in seeing a comparison of async patterns.</p>
<p>Next up was <a href="https://twitter.com/mglukhovsky">Mike Glukhovsky</a> with a whirlwind demo titled &ldquo;RRR - React, RethinkDB, Raspberry Pi&rdquo;. I&rsquo;ve been interested in RethinkDB for some time and it was cool to see how changefeeds were used to display and tweet the photos taken by the hardware Mike had whipped up for Rethink HQ using a Raspberry Pi and a webcam. He gave everyone a broad overview of the three title technologies and I&rsquo;m pretty sure I heard quite a few people in the audience get psyched about RethinkDB and the possibilities of being able to react to the way your data changes in real-time.</p>
<p>Another interesting talk, albiet a bit unexpected, was &ldquo;Reactive Composition: TodoMVC Tutorial/Lab&rdquo; from <a href="https://twitter.com/@darkmarmot">Scott Southworth</a>. I have to admit that I totally thought this talk would be about <a href="https://github.com/Reactive-Extensions/RxJS">RxJS</a> and <a href="http://reactivex.io/">ReactiveX</a>. Instead, Scott walked everyone through a history of the many tools of web development past and posited that maybe we should be doing more visual programming. He also demoed a very interesting real-time data analysis tool that he and his team built for monitoring an enterprise health network&rsquo;s data flow. Definitely inspiring and worth a thought.</p>
<p><a href="https://twitter.com/seldo">Laurie Voss&rsquo;</a> talk, &ldquo;npm and SOA: how we use SOA, and why node is good at SOA&rdquo;, reinforced a lot of the ideas that the Odd Networks team has in regards to our microservice architecture. It was especially funny to see the &ldquo;less simple version&rdquo; of npm&rsquo;s architecture, entitled <a href="http://slides.com/seldo/nodevember-npm-and-soa?token=-RYQiKo5#/43">&ldquo;shitshow&rdquo;</a>. We&rsquo;ve already begun simplifying our architecure diagrams for new hires and interviewees because of this reminder of just how crazy things can be.</p>
<p>The final talk I was able to attend was &ldquo;React Native in Production&rdquo; from <a href="https://twitter.com/skevy">Adam Miskiewicz</a>. His talk and also getting the chance to pick the brains of a few of his coworkers at <a href="https://twitter.com/ChalkChisel">Chalk + Chisel</a> after his talk gave us some great insight into the state of React Native for both iOS and Android. I definitely left feeling more optimistic about React Native than I had been.</p>
<h2 id="closing-thoughts">Closing Thoughts</h2>
<p>I had a lot of fun and feel like what I learned and who I got to meet was well worth the trip. I would definitely go back to Nodevember again and highly recommend it for anyone using Node.js or even looking to get a feel for the language and the thriving community around it.</p>
<p>You can catch all videos of the talks as the <a href="https://www.youtube.com/playlist?list=PLSZHCj84JSDMInvIg8mxNRmemoMwrySFj">Nodevember YouTube playlist</a> gets updated.</p>
]]></content:encoded>
    </item>
    <item>
      <title>Wrapping for Fun and Profit</title>
      <link>https://erikstraub.com/blog/wrapping-for-fun-and-profit/</link>
      <pubDate>Fri, 20 Jun 2014 00:00:00 +0000</pubDate><author>hi@erikstraub.com (Erik Straub)</author>
      <guid>https://erikstraub.com/blog/wrapping-for-fun-and-profit/</guid>
      <description>Wrappers, libraries, SDKs, gems — there are probably more benefits to making a simple abstraction than you realize. Ridding your application of non-business related functionality can help you focus on what matters, give back to your community, and provide an excellent way to introduce you or your company to a new audience.&#xA;A few months back MadGlory began a project that requires internet connected devices to be in real-time communication with a web application.</description>
      <content:encoded><![CDATA[<p><img src="/images/nasa-Q1p7bh3SHj8-unsplash.jpg" alt="Earth from space"></p>
<p>Wrappers, libraries, SDKs, gems — there are probably more benefits to making a simple abstraction than you realize. Ridding your application of non-business related functionality can help you focus on what matters, give back to your community, and provide an excellent way to introduce you or your company to a new audience.</p>
<p>A few months back MadGlory began a project that requires internet connected devices to be in real-time communication with a web application. While MG was responsible for the web application, another team was responsible for the device’s hardware, firmware, and software. Since early development on any application can involve countless changes due to domain discovery and other factors, it was decided that both the web application and the devices would use <a href="https://www.digi.com/products/iot-software-services/digi-remote-manager">Device Cloud by Etherios</a> as an intermediary of sorts.</p>
<p>There is a very large feature set, but from our point of view Device Cloud was a service that provided a common, stable, and robust API to manage our internet connected devices and get access to their data. It stored our devices’ files (logs, images, event data, etc.), provided an interface to real-time status of a device, exposed the devices’ internal API, and even allowed us to provision and update the devices remotely.</p>
<p>One useful feature was the Device Cloud’s virtual filesystem. The devices we were working with pushed files (JSON data) to the Device Cloud, which were in turn sent our web application as push notifications (HTTP PUT), containing the file data and some other meta information, whenever a new file event occurred. There are a TON of different events for which you can set up monitors to receive push notifications using Device Cloud’s Monitor feature, so we figured out what needed to be monitored and got to work.</p>
<p>Eventually, we ended up with a working example of sending and receiving data from our devices. While our code worked, it was very tightly coupled to the inner workings of the Device Cloud API. We had an entire model namespace dedicated to interacting with the Device Cloud. There were separate classes for requests, responses, modeling API objects (like Monitor or PushNotification) mixed in with our business logic of how our devices use those things. It was evident that our application was splitting its domain logic between both business needs of working with our device data and a Ruby wrapper for the Device Cloud API. Something smelled funny.</p>
<p>We needed to model how our application uses the Device Cloud, not how everyone else interacts with it using Ruby. In an effort to decouple that Device Cloud wrapper from our business logic, we started extracting the API models to a separate gem, and the <a href="https://github.com/madglory/device_cloud">device_cloud repository</a> was born.</p>
<p>This technique is not new. Many third-party services provide SDKs, gems, libraries, or simple example code to show how to interact with their API from within a certain language. I think this is a good practice not only to provide a sort of hands-on documentation of interacting with a third-party, but also to keep your application’s code organized and relevant.</p>
<p>This simple change drastically helped form how I think about interacting with third-party services and what is really important to an application. First and foremost, it made our application’s code more concise. By abstracting the code that defined how the Device Cloud worked, we were left with exactly what we needed — our data. It also had a couple of interesting side-effects.</p>
<p>Creating the device_cloud gem allowed us to contribute some reusable code to the open-source community. This does two very powerful things.</p>
<p>First, it gives the contributors an avenue to publicly demonstrate their abilities. MadGlory is a consultancy and we are hired to be expert engineers. That said, it can sometimes be tough to give detailed examples of the work you or your company is capable of due to non-disclosure agreements (NDAs). Releasing your abstracted wrappers or gems can provide concrete examples. Its <a href="http://blog.stackoverflow.com/2011/03/careers-2-0-now-does-github/">no secret</a> that <a href="http://code.dblock.org/github-is-your-new-resume">more</a> and <a href="http://thenextweb.com/apps/2012/09/02/my-github-resume-generates-resume-github-account/">more</a> companies are using GitHub as a resume of sorts when searching for talented employees (don’t get me started on cold-call recruiting emails). Why not leverage your company’s GitHub organization as a sort of digital portfolio?</p>
<p>Lastly, and maybe most importantly, you are helping your community grow. Producing simple, well-documented tools is crucial to cultivating a thriving tech community. Programming novices are encouraged with quick wins and easy-to-grok code, as <a href="http://twitter.com/dhh">DHH</a> (<a href="https://www.youtube.com/watch?v=9LfmrkyP81M">video</a>) and <a href="http://twitter.com/farrahbostik">Farrah Bostik</a> (<a href="https://www.youtube.com/watch?v=wLCXkf-e_aY">video</a>) alluded to this year at RailsConf 2014 in their keynotes. In addition, the more knowledge we can share with one another, the easier it is for everyone to build on top of those common tools and push the community forward, which is what <a href="http://twitter.com/wycats">Yehuda Katz</a> (<a href="https://www.youtube.com/watch?v=9naDS3r4MbY">video</a>) was talking about in his RailsConf keynote.</p>
<p>Putting aside the intangible benefits of community building and showcasing work, abstracting small bits of non-business related code has the real benefit of helping you focus your energy on the task at hand, and that is enough for me.</p>
]]></content:encoded>
    </item>
    <item>
      <title>Contact Me</title>
      <link>https://erikstraub.com/contact/</link>
      <pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><author>hi@erikstraub.com (Erik Straub)</author>
      <guid>https://erikstraub.com/contact/</guid>
      <description>Phone: 518.400.0414&#xA;Email: erik@limeleaf.io</description>
      <content:encoded><![CDATA[<p>Phone: 518.400.0414</p>
<p>Email: <a href="mailto:erik@limeleaf.io">erik@limeleaf.io</a></p>
<p><img src="/images/qr-code.svg" alt=""></p>
]]></content:encoded>
    </item>
  </channel>
</rss>
