Giter Site home page Giter Site logo

poteto / terraform Goto Github PK

View Code? Open in Web Editor NEW
414.0 11.0 12.0 20 KB

A simple plug for incrementally transforming an API into Phoenix. Check out the blog post:

Home Page: https://www.no.lol/2016-08-12-rise-from-the-ashes-incremental-apis-with-phoenix/

License: MIT License

Elixir 100.00%
elixir phoenix plug reverse-proxy

terraform's Introduction

terraform Hex Build Status Phoenix compatibility

Terraform is a simple Plug designed to work with Phoenix. Terraform allows you to incrementally transform a HTTP API into one powered by Phoenix - one endpoint at a time.

View the demo Phoenix app.

Phoenix Compatibility

This package is explicitly tested against the following Phoenix versions:

Phoenix version Compatibility
~> 1.2.0
~> 1.3.0
~> 1.4.0
~> 1.5.0

Installation

Add terraform to your list of dependencies in mix.exs:

def deps do
  [{:terraform, "~> 1.0.1"}]
end

Usage

First, add it to web/router.ex:

defmodule MyApp.Router do
  use Terraform, terraformer: MyApp.Terraformers.Foo

  # ...
end

Then, define a new Terraformer, which uses Plug.Router. Any request that goes to a route that isn't defined on your Phoenix app will hit this plug, and you can then handle it using a familiar DSL. Refer to hexdocs for documentation about Plug.Router.

Here's a basic example:

defmodule MyApp.Terraformers.Foo do
  alias MyApp.Clients.Foo # example client made with HTTPoison
  use Plug.Router

  plug :match
  plug :dispatch

  # match specific path
  get "/v1/hello-world", do: send_resp(conn, 200, "Hello world")

  # match all `get`s
  get _ do
    %{method: "GET", request_path: request_path, params: params, req_headers: req_headers} = conn
    res = Foo.get!(request_path, req_headers, [params: Map.to_list(params)])
    send_response({:ok, conn, res})
  end

  def send_response({:ok, conn, %{headers: headers, status_code: status_code, body: body}}) do
    conn = %{conn | resp_headers: headers}
    send_resp(conn, status_code, body)
  end
end

Reading the request body

Plug has an elegant solution to this problem using Plug.Conn.read_body. Refer to this comment for details.

terraform's People

Contributors

danmcclain avatar poteto avatar warmwaffles avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

terraform's Issues

Proxy from within controller action

Hi, great library, it has made migrating my legacy rails app to Phoenix a breeze.

Recently I had an endpoint I needed to migrate that has drastically different behavior depending on request params. Not an ideal design, but since I'm dealing with some pretty complex legacy code, I really wanted to migrate only one implementation at a time. However, since Phoenix doesn't support matching routes based on query parameters (AFAIK), I couldn't rely on terraform's default behavior. What I ended up doing was using pattern matching and manually calling the plug, which seemed to work great, but I did run into an issue where since the raw body had already been read and discarded, they weren't getting sent along to the Rails app. So I just wrote another simple plug to cache the original body and check for that in my terraform plug.

So my question is, would it make sense to build in an official way to handle this within terraform? I would be happy to contribute the code I already wrote and/or open a PR.

Switch CI

TravisCI no longer has unlimited open source library support, so we'll need to look at alternatives. Maybe GitHub actions?

Dependency requirements do not allow for integration with Phoenix v1.3.0-rc

When running mix deps.get (Phoenix 1.3.0-rc.2):

Failed to use "phoenix" (version 1.3.0-rc.2) because
  terraform (version 1.0.0) requires >= 1.2.0 and < 2.0.0 *
  mix.lock specifies 1.3.0-rc.2

* This requirement does not match pre-releases. To match pre-releases include a pre-release in the requirement, such as: "~> 2.0-beta".

Perhaps change {:phoenix, ">= 1.2.0 and < 2.0.0"} to {:phoenix, ">= 1.2.0 and < 2.0.0 or ~> 1.3.0-rc"}

Terraforming with a request body?

Hi, first of all, thanks very much for this library! 😸 The concept seems very useful for our current project. However, we've encountered an issue with request bodies — they don't seem to be present by the time the connection reaches the terraformer.

With irrelevant details removed, the terraformer looks like this:

defmodule OurApp.Terraformer do
  use Plug.Router

  plug :match
  plug :dispatch

  @base_uri "http://localhost:4001"

  match _ do
    method = conn.method |> String.downcase |> String.to_atom
    uri = @base_uri |> URI.merge(conn.request_path) |> URI.to_string
    {:ok, request_body, conn} = read_body(conn)
    # When inspected here, the request body is always an empty string!
    # IO.inspect(request_body)
    conn = fetch_query_params(conn)
    options = [params: conn.query_params |> Map.to_list]

    response = HTTPoison.request!(method, uri, request_body, conn.req_headers, options)

    conn = %{conn | resp_headers: response.headers}
    send_resp(conn, response.status_code, response.body)
  end
end

It's possible this is related to phoenixframework/phoenix#459, although I hope not because it seems like that would be extremely complicated to work around. In any case, I'd love to know if there's example code someplace where terraform is being used with request bodies — all the code I can find uses only GET requests.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.