Commit a951d737 authored by Terence Lee's avatar Terence Lee

ability to use env vars in proxies origin with `${}`

parent 21a24261
......@@ -112,6 +112,25 @@ For single page web applications like Ember, it's common to back the application
}
```
##### Interpolating Env Var Values
It's common to want to be able to test the frontend against various backends. The `origin` key supports environment variable substitution using `${ENV_VAR_NAME}`. For instance, if there was a staging and production Heroku app for your API, you could setup the config above like the following:
```json
{
"proxies": {
"/api/": {
"origin": "https://${API_APP_NAME}.herokuapp.com/"
}
}
}
```
Then using the [config vars](https://devcenter.heroku.com/articles/config-vars), you can point the frontend app to the appropriate backend. To match the original proxy setup:
```bash
$ heroku config:set API_APP_NAME="hone-ember-todo-rails"
```
#### Custom Headers
Using the headers key, you can set custom response headers. It uses the same operators for pathing as [Custom Routes](#custom-routes).
......
......@@ -20,11 +20,12 @@ class NginxConfig
json["encoding"] ||= DEFAULT[:encoding]
json["proxies"] ||= {}
json["proxies"].each do |loc, hash|
if hash["origin"][-1] != "/"
json["proxies"][loc].merge!("origin" => hash["origin"] + "/")
evaled_origin = NginxConfigUtil.interpolate(hash['origin'], ENV)
if evaled_origin != "/"
json["proxies"][loc].merge!("origin" => evaled_origin + "/")
end
uri = URI(hash["origin"])
uri = URI(evaled_origin)
json["proxies"][loc]["path"] = uri.path
uri.path = ""
json["proxies"][loc]["host"] = uri.to_s
......
......@@ -44,4 +44,16 @@ module NginxConfigUtil
false
end
def self.interpolate(string, vars)
regex = /\${(\w*?)}/
string.scan(regex).inject(string) do |acc, capture|
var_name = capture.first
value = vars[var_name] if vars
acc.sub!("${#{var_name}}", value) if value
acc
end
end
end
......@@ -16,4 +16,70 @@ RSpec.describe NginxConfigUtil do
end
end
end
describe ".interpolate" do
context "single instance" do
let(:string) { "hello ${FOO}" }
let(:env) do
{
"FOO" => "world"
}
end
let(:result) { "hello world" }
it "should interpolate" do
expect(NginxConfigUtil.interpolate(string, env)).to eq(result)
end
end
context "multiple instances" do
let(:string) { "${FOO}, ${BAR}" }
let(:env) do
{
"FOO" => "hello",
"BAR" => "world"
}
end
let(:result) { "hello, world" }
it "should interpolate" do
expect(NginxConfigUtil.interpolate(string, env)).to eq(result)
end
end
context "instance not found" do
let(:string) { "${FOO}" }
let(:env) { {} }
let(:result) { "${FOO}" }
it "should interpolate" do
expect(NginxConfigUtil.interpolate(string, env)).to eq(result)
end
end
context "vars is nil" do
let(:string) { "${FOO}" }
let(:env) { nil }
let(:result) { "${FOO}" }
it "should interpolate" do
expect(NginxConfigUtil.interpolate(string, env)).to eq(result)
end
end
context "complex example" do
let(:string) { "${FOO} ${BAR} ${BAZ} ${FOO}" }
let(:env) do
{
"FOO" => "foo",
"BAZ" => "baz"
}
end
let(:result) { "foo ${BAR} baz foo" }
it "should interpolate" do
expect(NginxConfigUtil.interpolate(string, env)).to eq(result)
end
end
end
end
......@@ -196,6 +196,34 @@ STATIC_JSON
expect(response.body.chomp).to eq("api")
end
end
context "env var substitution" do
before do
File.open(static_json_path, "w") do |file|
file.puts <<STATIC_JSON
{
"proxies": {
"/api/": {
"origin": "http://${PROXY_HOST}/foo"
}
}
}
STATIC_JSON
end
end
let(:env) do
{
"PROXY_HOST" => "#{AppRunner::HOST_IP}:#{AppRunner::HOST_PORT}"
}
end
it "should proxy requests" do
response = app.get("/api/bar/")
expect(response.code).to eq("200")
expect(response.body.chomp).to eq("api")
end
end
end
describe "custom headers" do
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment