### Sven Gehring's Blog

I write about software, engineering and stupidly fun side projects.

# There is no magic in Elixir!

If you’re anything like me, you probably started to learn Elixir and wanted to skip to the shiny stuff right away. Sure there’s some basics to sift through like the data types and specific syntax elements but after that, we can finally build a distributed, scalable, performant masterpiece of an application! - Riiigt? Granted, even if you’re a bit more of a sane person, once you get to work with Supervisor, GenServer, Agent and other modules alike, you can’t help but feel that things have been simplified a lot for you. Continue reading

# Serving static assets on a subpath in Phoenix

If you create a new Phoenix project, without using the --no-html flag, a static plug will be added to your endpoint. Because of this, a lot of people recommend to just edit that, if you want to serve static files from a subdirectory. However, this can get a bit tricky if you have data stored in different directories - or use Phoenix purely as an API.

You don’t have to edit the endpoint, though, you can just use Plug.Static in a (sub)scope in your controller

I remembered I did get this working once but wasn’t quite sure how anymore, so I wanted to quickly test if my answer was correct…. and there was some caveats to it. I haven’t found a comprehensive guide on how to do this, so here’s what I learned.

This article assumes you already have a Phoenix project up and running, however, if you don’t, you can create one with mix phx.new --no-ecto --no-webpack phxstatic - leaving out the database and frontend JS components for the sake of simplicity. For testing, we add a file at priv/test/hello.txt that contains hello world.

For serving static assets, we need to add a pipeline with the Plug.Static plug to our router. We will also use that pipeline in the scope where we want to serve those files, using the pipe_through macro.

  1 2 3 4 5 6 7 8 9 10 11 12 13 14 15  defmodule PhxstaticWeb.Router do use PhxstaticWeb, :router pipeline :static do plug Plug.Static, at: "/static", from: {:phxstatic, "priv/test"} end scope "/", PhxstaticWeb do scope "/static" do pipe_through :static end end end

Caveat 1: Even though the plug is nested in the /static/ scope, the :at option has to be set to the full path!
Caveat 2: It doesn’t do anything yet, now that’s unfortunate.

## Making it work

Caveat 3: Now this is where I got stuck the first time. Everything looks right but why does it just display the phoenix 404 page? The reason for this is, that a pipeline is only invoked, once a route in the scope that uses it matches, as explained by José in this post.

So the solution is reasonably simple, we just add a catchall route to the respective scope. I am not including the source code of ErrorController.notfound here, since you can use any controller/function here for rendering a 404.

  1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16  defmodule PhxstaticWeb.Router do use PhxstaticWeb, :router pipeline :static do plug Plug.Static, at: "/static", from: {:phxstatic, "priv/test"} end scope "/", PhxstaticWeb do scope "/static" do pipe_through :static get "/*path", ErrorController, :notfound end end end

If we now open localhost:4000/static/hello.txt, we get hello world - yay! And if we try some other path in that scope, we will just get the response rendered by ErrorController.notfound.

# Phoenix end-to-end testing in real life

There are lots of articles on testing in Elixir, and probably ten times as many for each Javascript frontend framework. But what if we want to test all of it together? - Be advised that end-to-end tests do not replace unit and integration tests on either the backend or frontend, however, I think they do have their place in a good test suite for the following reasons: We can test for specific user workflows that caused issues in the past to ensure these stay fixed forever. Continue reading

# Elixir: Testing protected Phoenix controllers

Testing protected endpoints in Phoenix controllers is a topic that sparks confusion - at best, and controversy at worst - amongst a surprising lot of people. When using Guardian or other pluggable ways of authorizing requests, this behaviour has to be taken into consideration for controller tests. Multiple pull requests in the Guardian repository were working towards a solution for this, Guardian Backdoor, which has now been moved into its own repository. Continue reading

A few weeks ago, I decided to build a little tool for my Synology Download Station, since I was not quite satisfied with the features DS Download offered me for simple monitoring. However, while testing out the API as it was documented in official API docs, I stumbled upon some rather unusual behaviour, that allows you to access details of any download task, even if it does not belong to the user you’re authenticated as. Continue reading