# Write a REST interface like Flask

**URL:** <https://discourse.julialang.org/t/write-a-rest-interface-like-flask/18538>\
**Category:** Web Stack\
**Created:** [December 10, 2018, 8:38pm UTC](https://discourse.julialang.org/t/write-a-rest-interface-like-flask/18538 "2018-12-10T20:38:59Z")\
**Posts on this page:** 20\
**Page:** 1

<div class="post-metadata">

**Author:** ![Seanny123](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/seanny123/32/5271_2.png) [@Seanny123](https://discourse.julialang.org/u/Seanny123)\
**Post date:** [December 10, 2018, 8:38pm UTC](https://discourse.julialang.org/t/write-a-rest-interface-like-flask/18538/1 "2018-12-10T20:38:59Z")

</div>

There are a [few](https://discourse.julialang.org/t/restful-web-services/10046) [posts](https://discourse.julialang.org/t/implement-a-rest-server-in-julia/9117) about write a REST interface using Julia wherein a number of libraries are recommended. However, I’m unclear if any of them resemble [Flask](http://flask.pocoo.org/)?

What I appreciate about Flask is how easy it is to define a set of routes and extract variables from them. For example, I can create a route and define argument types/parsing in a few lines:

```julia

@app.route("/init/"
           "region/<str:region>/"
           "site/<int:site_id>/"
           "channel/<int:channel_id>/")
def init(region: str, site_id: int, channel_id: int):
    ...

@app.route("/update/"
           "region/<str:region>/"
           "site/<int:site_id>/"
           "channel/<int:channel_id>/")
def update(region: str, site_id: int, channel_id: int):
    ...

```

From what I understand so far of the available Julia libraries:

- [HTTP.jl](https://github.com/JuliaWeb/HTTP.jl) is the foundational library, like Python’s `requests` library, which doesn’t provide any route or argument parsing functionality
- [Pages.jl](https://github.com/EricForgy/Pages.jl) seems pretty intuitive, but is lacking a routing and argument parsing example
- [Bukdu.jl](https://github.com/wookay/Bukdu.jl) is a full-on framework which is inspired by [Pheonix](https://phoenixframework.org/). Given my lack of familiarity with Pheonix, this seems like overkill for my use-case.
- [Mux.jl](https://github.com/JuliaWeb/Mux.jl) (related to [JuliaWebApi.jl](https://github.com/JuliaWeb/JuliaWebAPI.jl)) seems to provide the [ability to parse routes/URLs](https://discourse.julialang.org/t/implement-a-rest-server-in-julia/9117/14)?

Consequently, am I correct to conclude Mux.jl would be the most familiar to Python users coming from Flask?

---

<div class="post-metadata">

**Author:** ![DoktorMike](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/doktormike/32/2736_2.png) [@DoktorMike](https://discourse.julialang.org/u/DoktorMike)\
**Post date:** [December 10, 2018, 9:07pm UTC](https://discourse.julialang.org/t/write-a-rest-interface-like-flask/18538/2 "2018-12-10T21:07:12Z")

</div>

Not an expert but I believe Genie.jl can be used quite nicely for anything REST like. It a complete MVC framework but you don’t need to implement all of it.

---

<div class="post-metadata">

**Author:** ![essenciary](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/essenciary/32/210469_2.png) [@essenciary](https://discourse.julialang.org/u/essenciary)\
**Post date:** [December 11, 2018, 2:42pm UTC](https://discourse.julialang.org/t/write-a-rest-interface-like-flask/18538/3 "2018-12-11T14:42:29Z")

</div>

@Seanny123 Yes, that’s quite straightforward with Genie. You can just check the README: [GitHub - GenieFramework/Genie.jl: 🧞The highly productive Julia web framework](https://github.com/essenciary/Genie.jl)

You can see here how to create a new app, how to define routes and inline request handlers, as well as start the web server:  
[https://github.com/essenciary/Genie.jl#working-with-genie-apps-projects](https://github.com/essenciary/Genie.jl#working-with-genie-apps-projects)

Also, look here to see how to define routes with parameters and how to read the params:  
[https://github.com/essenciary/Genie.jl#using-genie-in-an-interactive-environment-jupyterijulia-repl-etc](https://github.com/essenciary/Genie.jl#using-genie-in-an-interactive-environment-jupyterijulia-repl-etc)

That’s pretty much all you need if you decide to simply return JSON from the route handlers. But if you have some larger app, I recommend that you set up a proper MVC structure and use controllers and JSON views, as described here: [https://github.com/essenciary/Genie.jl#rendering-json](https://github.com/essenciary/Genie.jl#rendering-json)

I hope this helps - if you have other questions, let me know.

---

<div class="post-metadata">

**Author:** ![Seanny123](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/seanny123/32/5271_2.png) [@Seanny123](https://discourse.julialang.org/u/Seanny123)\
**Post date:** [December 11, 2018, 6:54pm UTC](https://discourse.julialang.org/t/write-a-rest-interface-like-flask/18538/4 "2018-12-11T18:54:43Z")

</div>

To run an actual Genie application, you recommend doing `Genie.REPL.new_app("rest_service")`. However, this creates a lot of files that I don’t really need for a REST service. I tried reading through the docs to determine what an actual minimal working example would look like, but I’m a bit lost. Is there a more minimal example than `new_app("blah")`?

I’ll try to figure this out on my own and will try to make a PR for docs or maybe a `new_rest("blah")` command once I get some understanding.

---

<div class="post-metadata">

**Author:** ![Seanny123](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/seanny123/32/5271_2.png) [@Seanny123](https://discourse.julialang.org/u/Seanny123)\
**Post date:** [December 11, 2018, 7:06pm UTC](https://discourse.julialang.org/t/write-a-rest-interface-like-flask/18538/5 "2018-12-11T19:06:42Z")

</div>

This is the best minimal example I could come up with:

```julia
using Genie

import Genie.Router: route, @params
import Base.convert

convert(::Type{Int}, s::SubString{String}) = parse(Int, s)

route("/sum/:x::Int/:y::Int") do
    return @params(:x) + @params(:y)
end

route("/hello") do
    return "Welcome to Genie!"
end

route("/") do
    return "root"
end

Genie.AppServer.startup()

Base.JLOptions().isinteractive == 0 && wait()

```

---

<div class="post-metadata">

**Author:** ![essenciary](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/essenciary/32/210469_2.png) [@essenciary](https://discourse.julialang.org/u/essenciary)\
**Post date:** [December 11, 2018, 8:06pm UTC](https://discourse.julialang.org/t/write-a-rest-interface-like-flask/18538/6 "2018-12-11T20:06:13Z")

</div>

@Seanny123 Correct 🙂

This is mine, in 7 lines of code:

```julia
using Genie
import Genie.Router: route
import JSON: json

route("/") do
  (:message => "Hi there!") |> json
end

Genie.AppServer.startup() 

```

I just put it all in a `rest.jl` file and run it.  
You can build from it by adding more routes, parsing params, etc.

---

<div class="post-metadata">

**Author:** ![Seanny123](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/seanny123/32/5271_2.png) [@Seanny123](https://discourse.julialang.org/u/Seanny123)\
**Post date:** [December 11, 2018, 8:21pm UTC](https://discourse.julialang.org/t/write-a-rest-interface-like-flask/18538/7 "2018-12-11T20:21:22Z")

</div>

Can you run this outside of the REPL without the line at the end of my script `Base.JLOptions().isinteractive == 0 && wait()`?

---

<div class="post-metadata">

**Author:** ![essenciary](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/essenciary/32/210469_2.png) [@essenciary](https://discourse.julialang.org/u/essenciary)\
**Post date:** [December 11, 2018, 8:27pm UTC](https://discourse.julialang.org/t/write-a-rest-interface-like-flask/18538/8 "2018-12-11T20:27:48Z")

</div>

Let me try

---

<div class="post-metadata">

**Author:** ![essenciary](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/essenciary/32/210469_2.png) [@essenciary](https://discourse.julialang.org/u/essenciary)\
**Post date:** [December 11, 2018, 8:29pm UTC](https://discourse.julialang.org/t/write-a-rest-interface-like-flask/18538/9 "2018-12-11T20:29:29Z")

</div>

Small correction, this is the right approach (though a bit uglier) as it returns a proper JSON response (`Content-Type: application/json`):

```julia
using Genie
import Genie.Router: route
import Genie.Renderer: respond
import JSON: json

route("/") do
  Dict(:json => json(:message => "Hi there!")) |> respond
end

Genie.AppServer.startup()

```

I’ll add a bit of syntactic sugar to make it prettier, maybe:

```julia
json!(:message => "Hi there!")

```

---

<div class="post-metadata">

**Author:** ![essenciary](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/essenciary/32/210469_2.png) [@essenciary](https://discourse.julialang.org/u/essenciary)\
**Post date:** [December 11, 2018, 8:44pm UTC](https://discourse.julialang.org/t/write-a-rest-interface-like-flask/18538/10 "2018-12-11T20:44:31Z")

</div>

It exits when running `$ julia rest.jl`

It’s because `Genie.AppServer.startup()` calls `@async HTTP.Servers.serve`. It should not start the server `@async` to _not_ exit.

I guess the simplest (though ugliest) is to add this at the end:

```julia
while true
  sleep(1_000_000)
end

```

I’ll take a look - maybe I’ll remove the `@async` and switch to starting the server with  
`@async Genie.AppServer.startup() `

Or maybe add an `async` param to `startup()`?

* * *

## Update 1

OK, I couldn’t stand that ugliness so I pushed a few enhancements 🙂

Please make sure you update:

```julia
pkg> up

```

Then you can have `rest.jl` as:

```julia
using Genie
import Genie.Router: route
import Genie.Renderer: json!

Genie.config.session_auto_start = false

route("/") do
  (:message => "Hi there!") |> json!
end

Genie.AppServer.startup(async = false)

```

And you can run it with

```julia-auto
$ julia rest.jl

```

---

<div class="post-metadata">

**Author:** ![wookyoung](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/wookyoung/32/157_2.png) [@wookyoung](https://discourse.julialang.org/u/wookyoung)\
**Post date:** [December 15, 2018, 5:20am UTC](https://discourse.julialang.org/t/write-a-rest-interface-like-flask/18538/11 "2018-12-15T05:20:18Z")

</div>

You could try this with `Bukdu.jl v0.3.4` (tagged today)

```julia
# Bukdu v0.3.4
using Bukdu

struct RestController <: ApplicationController
    conn::Conn
end

function init(c::RestController, region::String, site_id::Int, channel_id::Int)
    render(JSON, (:init, region, site_id, channel_id))
end

function update(c::RestController, region::String, site_id::Int, channel_id::Int)
    render(JSON, (:update, region, site_id, channel_id))
end

function build_params(c::RestController)
    region::String = c.params.region
    site_id::Int, channel_id::Int = parse.(Int, (c.params.site_id, c.params.channel_id))
    (c, region, site_id, channel_id)
end

init(c::RestController) = init(build_params(c)...)
update(c::RestController) = update(build_params(c)...)

routes() do
    get("/init/region/:region/site/:site_id/channel/:channel_id/", RestController, init)
    get("/update/region/:region/site/:site_id/channel/:channel_id/", RestController, update)
end

Bukdu.start(8080)

#=
curl localhost:8080/init/region/west/site/1/channel/2/
curl localhost:8080/update/region/west/site/1/channel/2/
=#

```

---

<div class="post-metadata">

**Author:** ![Seanny123](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/seanny123/32/5271_2.png) [@Seanny123](https://discourse.julialang.org/u/Seanny123)\
**Post date:** [December 18, 2018, 3:46pm UTC](https://discourse.julialang.org/t/write-a-rest-interface-like-flask/18538/12 "2018-12-18T15:46:12Z")

</div>

Similar to `Genie`, I have to add `Base.JLOptions().isinteractive == 0 && wait()` to the end of the script to stop it from terminating. Is there any other way to stop it from terminating?

---

<div class="post-metadata">

**Author:** ![essenciary](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/essenciary/32/210469_2.png) [@essenciary](https://discourse.julialang.org/u/essenciary)\
**Post date:** [December 18, 2018, 4:19pm UTC](https://discourse.julialang.org/t/write-a-rest-interface-like-flask/18538/13 "2018-12-18T16:19:58Z")

</div>

If you updated to the latest master doing the `wait` thing should not be necessary anymore. See above, you can pass `Genie.AppServer.startup(async = false)`

---

<div class="post-metadata">

**Author:** ![Seanny123](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/seanny123/32/5271_2.png) [@Seanny123](https://discourse.julialang.org/u/Seanny123)\
**Post date:** [December 18, 2018, 4:21pm UTC](https://discourse.julialang.org/t/write-a-rest-interface-like-flask/18538/14 "2018-12-18T16:21:11Z")

</div>

Sorry, I mis-typed. I did update Genie to master and it worked!

I’m trying Bukdu, because I’m currently having trouble using it in Docker, but I’ll open an issue on the repo when I have more details.

---

<div class="post-metadata">

**Author:** ![essenciary](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/essenciary/32/210469_2.png) [@essenciary](https://discourse.julialang.org/u/essenciary)\
**Post date:** [December 18, 2018, 4:22pm UTC](https://discourse.julialang.org/t/write-a-rest-interface-like-flask/18538/15 "2018-12-18T16:22:26Z")

</div>

Awesome 😃

---

<div class="post-metadata">

**Author:** ![Seanny123](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/seanny123/32/5271_2.png) [@Seanny123](https://discourse.julialang.org/u/Seanny123)\
**Post date:** [January 7, 2019, 5:33pm UTC](https://discourse.julialang.org/t/write-a-rest-interface-like-flask/18538/16 "2019-01-07T17:33:10Z")

</div>

I understand how to pass an `@params` via the URL, but is it also possible to send a formatted data via a “header”. For example, make a route able to respond to:

```julia
curl -H "Content-type: application/json" \
-X POST http://127.0.0.1:5000/messages -d '{"message":"Hello Data"}'

```

Which I’ve taken from this [Flask example](http://blog.luisrei.com/articles/flaskrest.html).

---

<div class="post-metadata">

**Author:** ![essenciary](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/essenciary/32/210469_2.png) [@essenciary](https://discourse.julialang.org/u/essenciary)\
**Post date:** [January 7, 2019, 7:27pm UTC](https://discourse.julialang.org/t/write-a-rest-interface-like-flask/18538/17 "2019-01-07T19:27:46Z")

</div>

Can you please explain what you are trying to achieve? That’s a rather long page that you’re linking to…

---

<div class="post-metadata">

**Author:** ![Seanny123](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/seanny123/32/5271_2.png) [@Seanny123](https://discourse.julialang.org/u/Seanny123)\
**Post date:** [January 7, 2019, 7:52pm UTC](https://discourse.julialang.org/t/write-a-rest-interface-like-flask/18538/18 "2019-01-07T19:52:39Z")

</div>

Sorry for the long page. I was hoping you could just search for the command and read the code, despite a lack of familiarity with Python. This was not very considerate of me. Let me try again.

I would like to be able to send float values to my REST API. I thought I would have to accomplish this by sending a JSON “payload”. In the above URL, this “payload” is `{"message":"Hello Data"}`, but I would modify it to `{"x": 1.2, "y":2.3}`.

Alternatively, if there was some way to pass a float via URL, such as `http://127.0.0.1/fsum/1.2/2.3` this would also solve my problem.

---

<div class="post-metadata">

**Author:** ![Tero\_Frondelius](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/tero_frondelius/32/7629_2.png) [@Tero\_Frondelius](https://discourse.julialang.org/u/Tero_Frondelius)\
**Post date:** [January 7, 2019, 10:02pm UTC](https://discourse.julialang.org/t/write-a-rest-interface-like-flask/18538/19 "2019-01-07T22:02:13Z")

</div>

For sending json this named pipe / socket is a good option: [Which is the right way to integrate Julia program with Node.js](https://discourse.julialang.org/t/which-is-the-right-way-to-integrate-julia-program-with-node-js/19223)

---

<div class="post-metadata">

**Author:** ![essenciary](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/essenciary/32/210469_2.png) [@essenciary](https://discourse.julialang.org/u/essenciary)\
**Post date:** [January 7, 2019, 10:16pm UTC](https://discourse.julialang.org/t/write-a-rest-interface-like-flask/18538/20 "2019-01-07T22:16:14Z")

</div>

Thanks for the details. I did some digging.

Indeed, there is no logic to handle POST requests with `Content-type: application/json` although it should be straightforward (it should check the header, extract the body of the request and parse it as JSON). I will add this.

For the other issue, passing floats into the URL, it seems you stumbled onto a bug. Normally something like this should have worked:

```julia
Base.convert(::Type{Float64}, s::String) = parse(Float64, s)
route("/somefloats/:x::Float64/:y::Float64") do 
    "x+y is $(@params(x) + @params(y))"
end

```

But it ends up in a 404 error - so the route matching is getting confused by something.

I’m afraid that until I fix this, the only option is to pass the values over GET:

```julia
route("/somefloats") do 
    "x+y is $(parse(Float64, @params(:x)) + parse(Float64, @params(:y)))"
end

```

and request: [http://localhost:8000/somefloats?x=2.5&y=4.5](http://localhost:8000/somefloats?x=2.5&y=4.5)

You could also send a payload as text over GET or POST (as application/x-www-form-urlencoded) and parse the text payload as JSON on the server-side.

I hope this helps.

Do you have a few minutes to open issues on Github for these 2 problems please, so I can look into them these days? Thanks

[Next page](https://discourse.julialang.org/t/write-a-rest-interface-like-flask/18538.md?page=2)
